dpif-netdev: Translate Geneve options per-flow, not per-packet.
[cascardo/ovs.git] / lib / tun-metadata.c
1 /*
2  * Copyright (c) 2015 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include <errno.h>
19 #include <stdbool.h>
20
21 #include "bitmap.h"
22 #include "compiler.h"
23 #include "hmap.h"
24 #include "match.h"
25 #include "nx-match.h"
26 #include "odp-netlink.h"
27 #include "ofp-util.h"
28 #include "ovs-thread.h"
29 #include "ovs-rcu.h"
30 #include "packets.h"
31 #include "tun-metadata.h"
32
33 struct tun_meta_entry {
34     struct hmap_node node;      /* In struct tun_table's key_hmap. */
35     uint32_t key;               /* (class << 16) | type. */
36     struct tun_metadata_loc loc;
37     bool valid;                 /* True if allocated to a class and type. */
38 };
39
40 /* Maps from Geneve option class+type to positions in a struct tun_metadata's
41  * 'opts' array.  */
42 struct tun_table {
43     /* TUN_METADATA<i> is stored in element <i>. */
44     struct tun_meta_entry entries[TUN_METADATA_NUM_OPTS];
45
46     /* Each bit represents 4 bytes of space, 0-bits are free space. */
47     unsigned long alloc_map[BITMAP_N_LONGS(TUN_METADATA_TOT_OPT_SIZE / 4)];
48
49     /* The valid elements in entries[], indexed by class+type. */
50     struct hmap key_hmap;
51 };
52 BUILD_ASSERT_DECL(TUN_METADATA_TOT_OPT_SIZE % 4 == 0);
53
54 static struct ovs_mutex tab_mutex = OVS_MUTEX_INITIALIZER;
55 static OVSRCU_TYPE(struct tun_table *) metadata_tab;
56
57 static enum ofperr tun_metadata_add_entry(struct tun_table *map, uint8_t idx,
58                                           uint16_t opt_class, uint8_t type,
59                                           uint8_t len) OVS_REQUIRES(tab_mutex);
60 static void tun_metadata_del_entry(struct tun_table *map, uint8_t idx)
61             OVS_REQUIRES(tab_mutex);
62 static void memcpy_to_metadata(struct tun_metadata *dst, const void *src,
63                                const struct tun_metadata_loc *);
64 static void memcpy_from_metadata(void *dst, const struct tun_metadata *src,
65                                  const struct tun_metadata_loc *);
66
67 static uint32_t
68 tun_meta_key(ovs_be16 class, uint8_t type)
69 {
70     return (OVS_FORCE uint16_t)class << 8 | type;
71 }
72
73 static ovs_be16
74 tun_key_class(uint32_t key)
75 {
76     return (OVS_FORCE ovs_be16)(key >> 8);
77 }
78
79 static uint8_t
80 tun_key_type(uint32_t key)
81 {
82     return key & 0xff;
83 }
84
85 /* Returns a newly allocated tun_table.  If 'old_map' is nonnull then the new
86  * tun_table is a deep copy of the old one. */
87 static struct tun_table *
88 table_alloc(const struct tun_table *old_map) OVS_REQUIRES(tab_mutex)
89 {
90     struct tun_table *new_map;
91
92     new_map = xzalloc(sizeof *new_map);
93
94     if (old_map) {
95         struct tun_meta_entry *entry;
96
97         *new_map = *old_map;
98         hmap_init(&new_map->key_hmap);
99
100         HMAP_FOR_EACH (entry, node, &old_map->key_hmap) {
101             struct tun_meta_entry *new_entry;
102             struct tun_metadata_loc_chain *chain;
103
104             new_entry = &new_map->entries[entry - old_map->entries];
105             hmap_insert(&new_map->key_hmap, &new_entry->node, entry->node.hash);
106
107             chain = &new_entry->loc.c;
108             while (chain->next) {
109                 chain->next = xmemdup(chain->next, sizeof *chain->next);
110                 chain = chain->next;
111             }
112         }
113     } else {
114         hmap_init(&new_map->key_hmap);
115     }
116
117     return new_map;
118 }
119
120 /* Frees 'map' and all the memory it owns. */
121 static void
122 table_free(struct tun_table *map) OVS_REQUIRES(tab_mutex)
123 {
124     struct tun_meta_entry *entry;
125
126     if (!map) {
127         return;
128     }
129
130     HMAP_FOR_EACH (entry, node, &map->key_hmap) {
131         tun_metadata_del_entry(map, entry - map->entries);
132     }
133
134     free(map);
135 }
136
137 /* Creates a global tunnel metadata mapping table, if none already exists. */
138 void
139 tun_metadata_init(void)
140 {
141     ovs_mutex_lock(&tab_mutex);
142
143     if (!ovsrcu_get_protected(struct tun_table *, &metadata_tab)) {
144         ovsrcu_set(&metadata_tab, table_alloc(NULL));
145     }
146
147     ovs_mutex_unlock(&tab_mutex);
148 }
149
150 enum ofperr
151 tun_metadata_table_mod(struct ofputil_geneve_table_mod *gtm)
152 {
153     struct tun_table *old_map, *new_map;
154     struct ofputil_geneve_map *ofp_map;
155     enum ofperr err = 0;
156
157     ovs_mutex_lock(&tab_mutex);
158
159     old_map = ovsrcu_get_protected(struct tun_table *, &metadata_tab);
160
161     switch (gtm->command) {
162     case NXGTMC_ADD:
163         new_map = table_alloc(old_map);
164
165         LIST_FOR_EACH (ofp_map, list_node, &gtm->mappings) {
166             err = tun_metadata_add_entry(new_map, ofp_map->index,
167                                          ofp_map->option_class,
168                                          ofp_map->option_type,
169                                          ofp_map->option_len);
170             if (err) {
171                 table_free(new_map);
172                 goto out;
173             }
174         }
175         break;
176
177     case NXGTMC_DELETE:
178         new_map = table_alloc(old_map);
179
180         LIST_FOR_EACH (ofp_map, list_node, &gtm->mappings) {
181             tun_metadata_del_entry(new_map, ofp_map->index);
182         }
183         break;
184
185     case NXGTMC_CLEAR:
186         new_map = table_alloc(NULL);
187         break;
188
189     default:
190         OVS_NOT_REACHED();
191     }
192
193     ovsrcu_set(&metadata_tab, new_map);
194     ovsrcu_postpone(table_free, old_map);
195
196 out:
197     ovs_mutex_unlock(&tab_mutex);
198     return err;
199 }
200
201 void
202 tun_metadata_table_request(struct ofputil_geneve_table_reply *gtr)
203 {
204     struct tun_table *map = ovsrcu_get(struct tun_table *, &metadata_tab);
205     int i;
206
207     gtr->max_option_space = TUN_METADATA_TOT_OPT_SIZE;
208     gtr->max_fields = TUN_METADATA_NUM_OPTS;
209     list_init(&gtr->mappings);
210
211     for (i = 0; i < TUN_METADATA_NUM_OPTS; i++) {
212         struct tun_meta_entry *entry = &map->entries[i];
213         struct ofputil_geneve_map *map;
214
215         if (!entry->valid) {
216             continue;
217         }
218
219         map = xmalloc(sizeof *map);
220         map->option_class = ntohs(tun_key_class(entry->key));
221         map->option_type = tun_key_type(entry->key);
222         map->option_len = entry->loc.len;
223         map->index = i;
224
225         list_push_back(&gtr->mappings, &map->list_node);
226     }
227 }
228
229 /* Copies the value of field 'mf' from 'tnl' (which must be in non-UDPIF format) * into 'value'.
230  *
231  * 'mf' must be an MFF_TUN_METADATA* field.
232  *
233  * This uses the global tunnel metadata mapping table created by
234  * tun_metadata_init().  If no such table has been created or if 'mf' hasn't
235  * been allocated in it yet, this just zeros 'value'. */
236 void
237 tun_metadata_read(const struct flow_tnl *tnl,
238                   const struct mf_field *mf, union mf_value *value)
239 {
240     struct tun_table *map = ovsrcu_get(struct tun_table *, &metadata_tab);
241     unsigned int idx = mf->id - MFF_TUN_METADATA0;
242     struct tun_metadata_loc *loc;
243
244     if (!map) {
245         memset(value->tun_metadata, 0, mf->n_bytes);
246         return;
247     }
248
249     loc = &map->entries[idx].loc;
250
251     memset(value->tun_metadata, 0, mf->n_bytes - loc->len);
252     memcpy_from_metadata(value->tun_metadata + mf->n_bytes - loc->len,
253                          &tnl->metadata, loc);
254 }
255
256 /* Copies 'value' into field 'mf' in 'tnl' (in non-UDPIF format).
257  *
258  * 'mf' must be an MFF_TUN_METADATA* field.
259  *
260  * This uses the global tunnel metadata mapping table created by
261  * tun_metadata_init().  If no such table has been created or if 'mf' hasn't
262  * been allocated in it yet, this function does nothing. */
263 void
264 tun_metadata_write(struct flow_tnl *tnl,
265                    const struct mf_field *mf, const union mf_value *value)
266 {
267     struct tun_table *map = ovsrcu_get(struct tun_table *, &metadata_tab);
268     unsigned int idx = mf->id - MFF_TUN_METADATA0;
269     struct tun_metadata_loc *loc;
270
271     if (!map || !map->entries[idx].valid) {
272         return;
273     }
274
275     loc = &map->entries[idx].loc;
276
277     ULLONG_SET1(tnl->metadata.present.map, idx);
278     memcpy_to_metadata(&tnl->metadata,
279                        value->tun_metadata + mf->n_bytes - loc->len, loc);
280 }
281
282 static const struct tun_metadata_loc *
283 metadata_loc_from_match(struct tun_table *map, struct match *match,
284                         unsigned int idx, unsigned int field_len)
285 {
286     ovs_assert(idx < TUN_METADATA_NUM_OPTS);
287
288     if (map) {
289         if (map->entries[idx].valid) {
290             return &map->entries[idx].loc;
291         } else {
292             return NULL;
293         }
294     }
295
296     if (match->tun_md.alloc_offset + field_len >= TUN_METADATA_TOT_OPT_SIZE ||
297         match->tun_md.loc[idx].len) {
298         return NULL;
299     }
300
301     match->tun_md.loc[idx].len = field_len;
302     match->tun_md.loc[idx].c.offset = match->tun_md.alloc_offset;
303     match->tun_md.loc[idx].c.len = field_len;
304     match->tun_md.loc[idx].c.next = NULL;
305     match->tun_md.alloc_offset += field_len;
306     match->tun_md.valid = true;
307
308     return &match->tun_md.loc[idx];
309 }
310
311 /* Makes 'match' match 'value'/'mask' on field 'mf'.
312  *
313  * 'mf' must be an MFF_TUN_METADATA* field. 'match' must be in non-UDPIF format.
314  *
315  * If there is global tunnel metadata matching table, this function is
316  * effective only if there is already a mapping for 'mf'.  Otherwise, the
317  * metadata mapping table integrated into 'match' is used, adding 'mf' to its
318  * mapping table if it isn't already mapped (and if there is room).  If 'mf'
319  * isn't or can't be mapped, this function returns without modifying 'match'.
320  *
321  * 'value' may be NULL; if so, then 'mf' is made to match on an all-zeros
322  * value.
323  *
324  * 'mask' may be NULL; if so, then 'mf' is made exact-match.
325  */
326 void
327 tun_metadata_set_match(const struct mf_field *mf, const union mf_value *value,
328                        const union mf_value *mask, struct match *match)
329 {
330     struct tun_table *map = ovsrcu_get(struct tun_table *, &metadata_tab);
331     const struct tun_metadata_loc *loc;
332     unsigned int idx = mf->id - MFF_TUN_METADATA0;
333     unsigned int field_len;
334     unsigned int data_offset;
335     union mf_value data;
336
337     ovs_assert(!(match->flow.tunnel.flags & FLOW_TNL_F_UDPIF));
338
339     field_len = mf_field_len(mf, value, mask);
340     loc = metadata_loc_from_match(map, match, idx, field_len);
341     if (!loc) {
342         return;
343     }
344
345     data_offset = mf->n_bytes - loc->len;
346
347     if (!value) {
348         memset(data.tun_metadata, 0, loc->len);
349     } else if (!mask) {
350         memcpy(data.tun_metadata, value->tun_metadata + data_offset, loc->len);
351     } else {
352         int i;
353         for (i = 0; i < loc->len; i++) {
354             data.tun_metadata[i] = value->tun_metadata[data_offset + i] &
355                                    mask->tun_metadata[data_offset + i];
356         }
357     }
358     ULLONG_SET1(match->flow.tunnel.metadata.present.map, idx);
359     memcpy_to_metadata(&match->flow.tunnel.metadata, data.tun_metadata, loc);
360
361     if (!value) {
362         memset(data.tun_metadata, 0, loc->len);
363     } else if (!mask) {
364         memset(data.tun_metadata, 0xff, loc->len);
365     } else {
366         memcpy(data.tun_metadata, mask->tun_metadata + data_offset, loc->len);
367     }
368     ULLONG_SET1(match->wc.masks.tunnel.metadata.present.map, idx);
369     memcpy_to_metadata(&match->wc.masks.tunnel.metadata, data.tun_metadata, loc);
370 }
371
372 static bool
373 udpif_to_parsed(const struct flow_tnl *flow, const struct flow_tnl *mask,
374                 struct flow_tnl *flow_xlate, struct flow_tnl *mask_xlate)
375 {
376     if (flow->flags & FLOW_TNL_F_UDPIF) {
377         int err;
378
379         err = tun_metadata_from_geneve_udpif(flow, flow, flow_xlate);
380         if (err) {
381             return false;
382         }
383
384         if (mask) {
385             tun_metadata_from_geneve_udpif(flow, mask, mask_xlate);
386             if (err) {
387                 return false;
388             }
389         }
390     } else {
391         if (flow->metadata.present.map == 0) {
392             /* There is no tunnel metadata, don't bother copying. */
393             return false;
394         }
395
396         memcpy(flow_xlate, flow, sizeof *flow_xlate);
397         if (mask) {
398             memcpy(mask_xlate, mask, sizeof *mask_xlate);
399         }
400
401         if (!flow_xlate->metadata.tab) {
402             flow_xlate->metadata.tab = ovsrcu_get(struct tun_table *,
403                                                   &metadata_tab);
404         }
405     }
406
407     return true;
408 }
409
410 /* Copies all MFF_TUN_METADATA* fields from 'tnl' to 'flow_metadata'. */
411 void
412 tun_metadata_get_fmd(const struct flow_tnl *tnl, struct match *flow_metadata)
413 {
414     struct flow_tnl flow;
415     int i;
416
417     if (!udpif_to_parsed(tnl, NULL, &flow, NULL)) {
418         return;
419     }
420
421     ULLONG_FOR_EACH_1 (i, flow.metadata.present.map) {
422         union mf_value opts;
423         const struct tun_metadata_loc *old_loc = &flow.metadata.tab->entries[i].loc;
424         const struct tun_metadata_loc *new_loc;
425
426         new_loc = metadata_loc_from_match(NULL, flow_metadata, i, old_loc->len);
427
428         memcpy_from_metadata(opts.tun_metadata, &flow.metadata, old_loc);
429         memcpy_to_metadata(&flow_metadata->flow.tunnel.metadata,
430                            opts.tun_metadata, new_loc);
431
432         memset(opts.tun_metadata, 0xff, old_loc->len);
433         memcpy_to_metadata(&flow_metadata->wc.masks.tunnel.metadata,
434                            opts.tun_metadata, new_loc);
435     }
436 }
437
438 static uint32_t
439 tun_meta_hash(uint32_t key)
440 {
441     return hash_int(key, 0);
442 }
443
444 static struct tun_meta_entry *
445 tun_meta_find_key(const struct hmap *hmap, uint32_t key)
446 {
447     struct tun_meta_entry *entry;
448
449     HMAP_FOR_EACH_IN_BUCKET (entry, node, tun_meta_hash(key), hmap) {
450         if (entry->key == key) {
451             return entry;
452         }
453     }
454     return NULL;
455 }
456
457 static void
458 memcpy_to_metadata(struct tun_metadata *dst, const void *src,
459                    const struct tun_metadata_loc *loc)
460 {
461     const struct tun_metadata_loc_chain *chain = &loc->c;
462     int addr = 0;
463
464     while (chain) {
465         memcpy(dst->opts.u8 + loc->c.offset + addr, (uint8_t *)src + addr,
466                chain->len);
467         addr += chain->len;
468         chain = chain->next;
469     }
470 }
471
472 static void
473 memcpy_from_metadata(void *dst, const struct tun_metadata *src,
474                      const struct tun_metadata_loc *loc)
475 {
476     const struct tun_metadata_loc_chain *chain = &loc->c;
477     int addr = 0;
478
479     while (chain) {
480         memcpy((uint8_t *)dst + addr, src->opts.u8 + loc->c.offset + addr,
481                chain->len);
482         addr += chain->len;
483         chain = chain->next;
484     }
485 }
486
487 static int
488 tun_metadata_alloc_chain(struct tun_table *map, uint8_t len,
489                          struct tun_metadata_loc_chain *loc)
490                          OVS_REQUIRES(tab_mutex)
491 {
492     int alloc_len = len / 4;
493     int scan_start = 0;
494     int scan_end = TUN_METADATA_TOT_OPT_SIZE / 4;
495     int pos_start, pos_end, pos_len;
496     int best_start = 0, best_len = 0;
497
498     while (true) {
499         pos_start = bitmap_scan(map->alloc_map, 0, scan_start, scan_end);
500         if (pos_start == scan_end) {
501             break;
502         }
503
504         pos_end = bitmap_scan(map->alloc_map, 1, pos_start,
505                               MIN(pos_start + alloc_len, scan_end));
506         pos_len = pos_end - pos_start;
507         if (pos_len == alloc_len) {
508             goto found;
509         }
510
511         if (pos_len > best_len) {
512             best_start = pos_start;
513             best_len = pos_len;
514         }
515         scan_start = pos_end + 1;
516     }
517
518     if (best_len == 0) {
519         return ENOSPC;
520     }
521
522     pos_start = best_start;
523     pos_len = best_len;
524
525 found:
526     bitmap_set_multiple(map->alloc_map, pos_start, pos_len, 1);
527     loc->offset = pos_start * 4;
528     loc->len = pos_len * 4;
529
530     return 0;
531 }
532
533 static enum ofperr
534 tun_metadata_add_entry(struct tun_table *map, uint8_t idx, uint16_t opt_class,
535                        uint8_t type, uint8_t len) OVS_REQUIRES(tab_mutex)
536 {
537     struct tun_meta_entry *entry;
538     struct tun_metadata_loc_chain *cur_chain, *prev_chain;
539
540     ovs_assert(idx < TUN_METADATA_NUM_OPTS);
541
542     entry = &map->entries[idx];
543     if (entry->valid) {
544         return OFPERR_NXGTMFC_ALREADY_MAPPED;
545     }
546
547     entry->key = tun_meta_key(htons(opt_class), type);
548     if (tun_meta_find_key(&map->key_hmap, entry->key)) {
549         return OFPERR_NXGTMFC_DUP_ENTRY;
550     }
551
552     entry->valid = true;
553     hmap_insert(&map->key_hmap, &entry->node,
554                 tun_meta_hash(entry->key));
555
556     entry->loc.len = len;
557     cur_chain = &entry->loc.c;
558     memset(cur_chain, 0, sizeof *cur_chain);
559     prev_chain = NULL;
560
561     while (len) {
562         int err;
563
564         if (!cur_chain) {
565             cur_chain = xzalloc(sizeof *cur_chain);
566         }
567
568         err = tun_metadata_alloc_chain(map, len, cur_chain);
569         if (err) {
570             tun_metadata_del_entry(map, idx);
571             return OFPERR_NXGTMFC_TABLE_FULL;
572         }
573
574         len -= cur_chain->len;
575
576         if (prev_chain) {
577             prev_chain->next = cur_chain;
578         }
579         prev_chain = cur_chain;
580         cur_chain = NULL;
581     }
582
583     return 0;
584 }
585
586 static void
587 tun_metadata_del_entry(struct tun_table *map, uint8_t idx)
588                        OVS_REQUIRES(tab_mutex)
589 {
590     struct tun_meta_entry *entry;
591     struct tun_metadata_loc_chain *chain;
592
593     if (idx >= TUN_METADATA_NUM_OPTS) {
594         return;
595     }
596
597     entry = &map->entries[idx];
598     if (!entry->valid) {
599         return;
600     }
601
602     chain = &entry->loc.c;
603     while (chain) {
604         struct tun_metadata_loc_chain *next = chain->next;
605
606         bitmap_set_multiple(map->alloc_map, chain->offset / 4,
607                             chain->len / 4, 0);
608         if (chain != &entry->loc.c) {
609             free(chain);
610         }
611         chain = next;
612     }
613
614     entry->valid = false;
615     hmap_remove(&map->key_hmap, &entry->node);
616     memset(&entry->loc, 0, sizeof entry->loc);
617 }
618
619 static int
620 tun_metadata_from_geneve__(const struct tun_metadata *flow_metadata,
621                            const struct geneve_opt *opt,
622                            const struct geneve_opt *flow_opt, int opts_len,
623                            struct tun_metadata *metadata)
624 {
625     struct tun_table *map;
626     bool is_mask = flow_opt != opt;
627
628     if (!is_mask) {
629         map = ovsrcu_get(struct tun_table *, &metadata_tab);
630         metadata->tab = map;
631     } else {
632         map = flow_metadata->tab;
633     }
634
635     if (!map) {
636         return 0;
637     }
638
639     while (opts_len > 0) {
640         int len;
641         struct tun_meta_entry *entry;
642
643         if (opts_len < sizeof(*opt)) {
644             return EINVAL;
645         }
646
647         len = sizeof(*opt) + flow_opt->length * 4;
648         if (len > opts_len) {
649             return EINVAL;
650         }
651
652         entry = tun_meta_find_key(&map->key_hmap,
653                                   tun_meta_key(flow_opt->opt_class,
654                                                flow_opt->type));
655         if (entry) {
656             if (entry->loc.len == flow_opt->length * 4) {
657                 memcpy_to_metadata(metadata, opt + 1, &entry->loc);
658                 ULLONG_SET1(metadata->present.map, entry - map->entries);
659             } else {
660                 return EINVAL;
661             }
662         } else if (flow_opt->type & GENEVE_CRIT_OPT_TYPE) {
663             return EINVAL;
664         }
665
666         opt = opt + len / sizeof(*opt);
667         flow_opt = flow_opt + len / sizeof(*opt);
668         opts_len -= len;
669     }
670
671     return 0;
672 }
673
674 static const struct nlattr *
675 tun_metadata_find_geneve_key(const struct nlattr *key, uint32_t key_len)
676 {
677     const struct nlattr *tnl_key;
678
679     tnl_key = nl_attr_find__(key, key_len, OVS_KEY_ATTR_TUNNEL);
680     if (!tnl_key) {
681         return NULL;
682     }
683
684     return nl_attr_find_nested(tnl_key, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS);
685 }
686
687 /* Converts from Geneve netlink attributes in 'attr' to tunnel metadata
688  * in 'tun'. The result may either in be UDPIF format or not, as determined
689  * by 'udpif'.
690  *
691  * In the event that a mask is being converted, it is also necessary to
692  * pass in flow information. This includes the full set of netlink attributes
693  * (i.e. not just the Geneve attribute) in 'flow_attrs'/'flow_attr_len' and
694  * the previously converted tunnel metadata 'flow_tun'.
695  *
696  * If a flow rather than mask is being converted, 'flow_attrs' must be NULL. */
697 int
698 tun_metadata_from_geneve_nlattr(const struct nlattr *attr,
699                                 const struct nlattr *flow_attrs,
700                                 size_t flow_attr_len,
701                                 const struct flow_tnl *flow_tun, bool udpif,
702                                 struct flow_tnl *tun)
703 {
704     bool is_mask = !!flow_attrs;
705     int attr_len = nl_attr_get_size(attr);
706     const struct nlattr *flow;
707
708     /* No need for real translation, just copy things over. */
709     if (udpif) {
710         memcpy(tun->metadata.opts.gnv, nl_attr_get(attr), attr_len);
711
712         if (!is_mask) {
713             tun->metadata.present.len = attr_len;
714             tun->flags |= FLOW_TNL_F_UDPIF;
715         } else {
716             /* We need to exact match on the length so we don't
717              * accidentally match on sets of options that are the same
718              * at the beginning but with additional options after. */
719             tun->metadata.present.len = 0xff;
720         }
721
722         return 0;
723     }
724
725     if (is_mask) {
726         flow = tun_metadata_find_geneve_key(flow_attrs, flow_attr_len);
727         if (!flow) {
728             return attr_len ? EINVAL : 0;
729         }
730
731         if (attr_len != nl_attr_get_size(flow)) {
732             return EINVAL;
733         }
734     } else {
735         flow = attr;
736     }
737
738     return tun_metadata_from_geneve__(&flow_tun->metadata, nl_attr_get(attr),
739                                       nl_attr_get(flow), nl_attr_get_size(flow),
740                                       &tun->metadata);
741 }
742
743 /* Converts from the flat Geneve options representation extracted directly
744  * from the tunnel header to the representation that maps options to
745  * pre-allocated locations. The original version (in UDPIF form) is passed
746  * in 'src' and the translated form in stored in 'dst'.  To handle masks, the
747  * flow must also be passed in through 'flow' (in the original, raw form). */
748 int
749 tun_metadata_from_geneve_udpif(const struct flow_tnl *flow,
750                                const struct flow_tnl *src,
751                                struct flow_tnl *dst)
752 {
753     ovs_assert(flow->flags & FLOW_TNL_F_UDPIF);
754
755     if (flow == src) {
756         dst->flags = flow->flags & ~FLOW_TNL_F_UDPIF;
757     } else {
758         dst->metadata.tab = NULL;
759     }
760     dst->metadata.present.map = 0;
761     return tun_metadata_from_geneve__(&flow->metadata, src->metadata.opts.gnv,
762                                       flow->metadata.opts.gnv,
763                                       flow->metadata.present.len,
764                                       &dst->metadata);
765 }
766
767 static void
768 tun_metadata_to_geneve__(const struct tun_metadata *flow, struct ofpbuf *b,
769                          bool *crit_opt)
770 {
771     struct tun_table *map;
772     int i;
773
774     map = flow->tab;
775     if (!map) {
776         map = ovsrcu_get(struct tun_table *, &metadata_tab);
777     }
778
779     *crit_opt = false;
780
781     ULLONG_FOR_EACH_1 (i, flow->present.map) {
782         struct tun_meta_entry *entry = &map->entries[i];
783         struct geneve_opt *opt;
784
785         opt = ofpbuf_put_uninit(b, sizeof *opt + entry->loc.len);
786
787         opt->opt_class = tun_key_class(entry->key);
788         opt->type = tun_key_type(entry->key);
789         opt->length = entry->loc.len / 4;
790         opt->r1 = 0;
791         opt->r2 = 0;
792         opt->r3 = 0;
793
794         memcpy_from_metadata(opt + 1, flow, &entry->loc);
795         *crit_opt |= !!(opt->type & GENEVE_CRIT_OPT_TYPE);
796     }
797 }
798
799 static void
800 tun_metadata_to_geneve_nlattr_flow(const struct flow_tnl *flow,
801                                    struct ofpbuf *b)
802 {
803     size_t nlattr_offset;
804     bool crit_opt;
805
806     if (!flow->metadata.present.map) {
807         return;
808     }
809
810     /* For all intents and purposes, the Geneve options are nested
811      * attributes even if this doesn't show up directly to netlink. It's
812      * similar enough that we can use the same mechanism. */
813     nlattr_offset = nl_msg_start_nested(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS);
814
815     tun_metadata_to_geneve__(&flow->metadata, b, &crit_opt);
816
817     nl_msg_end_nested(b, nlattr_offset);
818 }
819
820 /* Converts from processed tunnel metadata information (in non-udpif
821  * format) in 'flow' to a stream of Geneve options suitable for
822  * transmission in 'opts'. Additionally returns whether there were
823  * any critical options in 'crit_opt' as well as the total length of
824  * data. */
825 int
826 tun_metadata_to_geneve_header(const struct flow_tnl *flow,
827                               struct geneve_opt *opts, bool *crit_opt)
828 {
829     struct ofpbuf b;
830
831     ovs_assert(!(flow->flags & FLOW_TNL_F_UDPIF));
832
833     ofpbuf_use_stack(&b, opts, GENEVE_TOT_OPT_SIZE);
834     tun_metadata_to_geneve__(&flow->metadata, &b, crit_opt);
835
836     return b.size;
837 }
838
839 static void
840 tun_metadata_to_geneve_mask__(const struct tun_metadata *flow,
841                               const struct tun_metadata *mask,
842                               struct geneve_opt *opt, int opts_len)
843 {
844     struct tun_table *map = flow->tab;
845
846     if (!map) {
847         return;
848     }
849
850     /* All of these options have already been validated, so no need
851      * for sanity checking. */
852     while (opts_len > 0) {
853         struct tun_meta_entry *entry;
854         int len = sizeof(*opt) + opt->length * 4;
855
856         entry = tun_meta_find_key(&map->key_hmap,
857                                   tun_meta_key(opt->opt_class, opt->type));
858         if (entry) {
859             memcpy_from_metadata(opt + 1, mask, &entry->loc);
860         } else {
861             memset(opt + 1, 0, opt->length * 4);
862         }
863
864         opt->opt_class = htons(0xffff);
865         opt->type = 0xff;
866         opt->length = 0x1f;
867         opt->r1 = 0;
868         opt->r2 = 0;
869         opt->r3 = 0;
870
871         opt = opt + len / sizeof(*opt);
872         opts_len -= len;
873     }
874 }
875
876 static void
877 tun_metadata_to_geneve_nlattr_mask(const struct ofpbuf *key,
878                                    const struct flow_tnl *mask,
879                                    const struct flow_tnl *flow,
880                                    struct ofpbuf *b)
881 {
882     const struct nlattr *geneve_key;
883     struct nlattr *geneve_mask;
884     struct geneve_opt *opt;
885     int opts_len;
886
887     if (!key) {
888         return;
889     }
890
891     geneve_key = tun_metadata_find_geneve_key(key->data, key->size);
892     if (!geneve_key) {
893         return;
894     }
895
896     geneve_mask = ofpbuf_tail(b);
897     nl_msg_put(b, geneve_key, geneve_key->nla_len);
898
899     opt = CONST_CAST(struct geneve_opt *, nl_attr_get(geneve_mask));
900     opts_len = nl_attr_get_size(geneve_mask);
901
902     tun_metadata_to_geneve_mask__(&flow->metadata, &mask->metadata,
903                                   opt, opts_len);
904 }
905
906 /* Convert from the tunnel metadata in 'tun' to netlink attributes stored
907  * in 'b'. Either UDPIF or non-UDPIF input forms are accepted.
908  *
909  * To assist with parsing, it is necessary to also pass in the tunnel metadata
910  * from the flow in 'flow' as well in the original netlink form of the flow in
911  * 'key'. */
912 void
913 tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
914                               const struct flow_tnl *flow,
915                               const struct ofpbuf *key,
916                               struct ofpbuf *b)
917 {
918     bool is_mask = tun != flow;
919
920     if (!(flow->flags & FLOW_TNL_F_UDPIF)) {
921         if (!is_mask) {
922             tun_metadata_to_geneve_nlattr_flow(tun, b);
923         } else {
924             tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
925         }
926     } else if (flow->metadata.present.len || is_mask) {
927         nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
928                           tun->metadata.opts.gnv,
929                           flow->metadata.present.len);
930     }
931 }
932
933 /* Converts 'mask_src' (in non-UDPIF format) to a series of masked options in
934  * 'dst'. 'flow_src' (also in non-UDPIF format) and the  original set of
935  * options 'flow_src_opt'/'opts_len' are needed as a guide to interpret the
936  * mask data. */
937 void
938 tun_metadata_to_geneve_udpif_mask(const struct flow_tnl *flow_src,
939                                   const struct flow_tnl *mask_src,
940                                   const struct geneve_opt *flow_src_opt,
941                                   int opts_len, struct geneve_opt *dst)
942 {
943     ovs_assert(!(flow_src->flags & FLOW_TNL_F_UDPIF));
944
945     memcpy(dst, flow_src_opt, opts_len);
946     tun_metadata_to_geneve_mask__(&flow_src->metadata,
947                                   &mask_src->metadata, dst, opts_len);
948 }
949
950 static const struct tun_metadata_loc *
951 metadata_loc_from_match_read(struct tun_table *map, const struct match *match,
952                              unsigned int idx)
953 {
954     if (match->tun_md.valid) {
955         return &match->tun_md.loc[idx];
956     }
957
958     return &map->entries[idx].loc;
959 }
960
961 void
962 tun_metadata_to_nx_match(struct ofpbuf *b, enum ofp_version oxm,
963                          const struct match *match)
964 {
965     struct flow_tnl flow, mask;
966     int i;
967
968     if (!udpif_to_parsed(&match->flow.tunnel, &match->wc.masks.tunnel,
969                          &flow, &mask)) {
970         return;
971     }
972
973     ULLONG_FOR_EACH_1 (i, mask.metadata.present.map) {
974         const struct tun_metadata_loc *loc;
975         union mf_value opts;
976         union mf_value mask_opts;
977
978         loc = metadata_loc_from_match_read(flow.metadata.tab, match, i);
979         memcpy_from_metadata(opts.tun_metadata, &flow.metadata, loc);
980         memcpy_from_metadata(mask_opts.tun_metadata, &mask.metadata, loc);
981         nxm_put(b, MFF_TUN_METADATA0 + i, oxm, opts.tun_metadata,
982                 mask_opts.tun_metadata, loc->len);
983     }
984 }
985
986 void
987 tun_metadata_match_format(struct ds *s, const struct match *match)
988 {
989     struct flow_tnl flow, mask;
990     unsigned int i;
991
992     if (!udpif_to_parsed(&match->flow.tunnel, &match->wc.masks.tunnel,
993                          &flow, &mask)) {
994         return;
995     }
996
997     ULLONG_FOR_EACH_1 (i, mask.metadata.present.map) {
998         const struct tun_metadata_loc *loc;
999         union mf_value opts;
1000
1001         loc = metadata_loc_from_match_read(flow.metadata.tab, match, i);
1002
1003         ds_put_format(s, "tun_metadata%u=", i);
1004         memcpy_from_metadata(opts.tun_metadata, &flow.metadata, loc);
1005         ds_put_hex(s, opts.tun_metadata, loc->len);
1006
1007         memcpy_from_metadata(opts.tun_metadata, &mask.metadata, loc);
1008         if (!is_all_ones(opts.tun_metadata, loc->len)) {
1009             ds_put_char(s, '/');
1010             ds_put_hex(s, opts.tun_metadata, loc->len);
1011         }
1012         ds_put_char(s, ',');
1013     }
1014 }