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