acaacff94edcbb00fc6a58a961a2947afb348c52
[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)
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         match->tun_md.loc[idx].len) {
297         return NULL;
298     }
299
300     match->tun_md.loc[idx].len = field_len;
301     match->tun_md.loc[idx].c.offset = match->tun_md.alloc_offset;
302     match->tun_md.loc[idx].c.len = field_len;
303     match->tun_md.loc[idx].c.next = NULL;
304     match->tun_md.alloc_offset += field_len;
305     match->tun_md.valid = true;
306
307     return &match->tun_md.loc[idx];
308 }
309
310 /* Makes 'match' match 'value'/'mask' on field 'mf'.
311  *
312  * 'mf' must be an MFF_TUN_METADATA* field. 'match' must be in non-UDPIF format.
313  *
314  * If there is global tunnel metadata matching table, this function is
315  * effective only if there is already a mapping for 'mf'.  Otherwise, the
316  * metadata mapping table integrated into 'match' is used, adding 'mf' to its
317  * mapping table if it isn't already mapped (and if there is room).  If 'mf'
318  * isn't or can't be mapped, this function returns without modifying 'match'.
319  *
320  * 'value' may be NULL; if so, then 'mf' is made to match on an all-zeros
321  * value.
322  *
323  * 'mask' may be NULL; if so, then 'mf' is made exact-match.
324  */
325 void
326 tun_metadata_set_match(const struct mf_field *mf, const union mf_value *value,
327                        const union mf_value *mask, struct match *match)
328 {
329     struct tun_table *map = ovsrcu_get(struct tun_table *, &metadata_tab);
330     const struct tun_metadata_loc *loc;
331     unsigned int idx = mf->id - MFF_TUN_METADATA0;
332     unsigned int field_len;
333     unsigned int data_offset;
334     union mf_value data;
335
336     ovs_assert(!(match->flow.tunnel.flags & FLOW_TNL_F_UDPIF));
337
338     field_len = mf_field_len(mf, value, mask);
339     loc = metadata_loc_from_match(map, match, idx, field_len);
340     if (!loc) {
341         return;
342     }
343
344     data_offset = mf->n_bytes - loc->len;
345
346     if (!value) {
347         memset(data.tun_metadata, 0, loc->len);
348     } else if (!mask) {
349         memcpy(data.tun_metadata, value->tun_metadata + data_offset, loc->len);
350     } else {
351         int i;
352         for (i = 0; i < loc->len; i++) {
353             data.tun_metadata[i] = value->tun_metadata[data_offset + i] &
354                                    mask->tun_metadata[data_offset + i];
355         }
356     }
357     memcpy_to_metadata(&match->flow.tunnel.metadata, data.tun_metadata,
358                        loc, idx);
359
360     if (!value) {
361         memset(data.tun_metadata, 0, loc->len);
362     } else if (!mask) {
363         memset(data.tun_metadata, 0xff, loc->len);
364     } else {
365         memcpy(data.tun_metadata, mask->tun_metadata + data_offset, loc->len);
366     }
367     memcpy_to_metadata(&match->wc.masks.tunnel.metadata, data.tun_metadata,
368                        loc, idx);
369 }
370
371 static bool
372 udpif_to_parsed(const struct flow_tnl *flow, const struct flow_tnl *mask,
373                 struct flow_tnl *flow_xlate, struct flow_tnl *mask_xlate)
374 {
375     if (flow->flags & FLOW_TNL_F_UDPIF) {
376         int err;
377
378         err = tun_metadata_from_geneve_udpif(flow, flow, flow_xlate);
379         if (err) {
380             return false;
381         }
382
383         if (mask) {
384             tun_metadata_from_geneve_udpif(flow, mask, mask_xlate);
385             if (err) {
386                 return false;
387             }
388         }
389     } else {
390         if (flow->metadata.present.map == 0) {
391             /* There is no tunnel metadata, don't bother copying. */
392             return false;
393         }
394
395         memcpy(flow_xlate, flow, sizeof *flow_xlate);
396         if (mask) {
397             memcpy(mask_xlate, mask, sizeof *mask_xlate);
398         }
399
400         if (!flow_xlate->metadata.tab) {
401             flow_xlate->metadata.tab = ovsrcu_get(struct tun_table *,
402                                                   &metadata_tab);
403         }
404     }
405
406     return true;
407 }
408
409 /* Copies all MFF_TUN_METADATA* fields from 'tnl' to 'flow_metadata'. */
410 void
411 tun_metadata_get_fmd(const struct flow_tnl *tnl, struct match *flow_metadata)
412 {
413     struct flow_tnl flow;
414     int i;
415
416     if (!udpif_to_parsed(tnl, NULL, &flow, NULL)) {
417         return;
418     }
419
420     ULLONG_FOR_EACH_1 (i, flow.metadata.present.map) {
421         union mf_value opts;
422         const struct tun_metadata_loc *old_loc = &flow.metadata.tab->entries[i].loc;
423         const struct tun_metadata_loc *new_loc;
424
425         new_loc = metadata_loc_from_match(NULL, flow_metadata, i, old_loc->len);
426
427         memcpy_from_metadata(opts.tun_metadata, &flow.metadata, old_loc);
428         memcpy_to_metadata(&flow_metadata->flow.tunnel.metadata,
429                            opts.tun_metadata, new_loc, i);
430
431         memset(opts.tun_metadata, 0xff, old_loc->len);
432         memcpy_to_metadata(&flow_metadata->wc.masks.tunnel.metadata,
433                            opts.tun_metadata, new_loc, i);
434     }
435 }
436
437 static uint32_t
438 tun_meta_hash(uint32_t key)
439 {
440     return hash_int(key, 0);
441 }
442
443 static struct tun_meta_entry *
444 tun_meta_find_key(const struct hmap *hmap, uint32_t key)
445 {
446     struct tun_meta_entry *entry;
447
448     HMAP_FOR_EACH_IN_BUCKET (entry, node, tun_meta_hash(key), hmap) {
449         if (entry->key == key) {
450             return entry;
451         }
452     }
453     return NULL;
454 }
455
456 static void
457 memcpy_to_metadata(struct tun_metadata *dst, const void *src,
458                    const struct tun_metadata_loc *loc, unsigned int idx)
459 {
460     const struct tun_metadata_loc_chain *chain = &loc->c;
461     int addr = 0;
462
463     while (chain) {
464         memcpy(dst->opts.u8 + loc->c.offset + addr, (uint8_t *)src + addr,
465                chain->len);
466         addr += chain->len;
467         chain = chain->next;
468     }
469
470     ULLONG_SET1(dst->present.map, idx);
471 }
472
473 static void
474 memcpy_from_metadata(void *dst, const struct tun_metadata *src,
475                      const struct tun_metadata_loc *loc)
476 {
477     const struct tun_metadata_loc_chain *chain = &loc->c;
478     int addr = 0;
479
480     while (chain) {
481         memcpy((uint8_t *)dst + addr, src->opts.u8 + loc->c.offset + addr,
482                chain->len);
483         addr += chain->len;
484         chain = chain->next;
485     }
486 }
487
488 static int
489 tun_metadata_alloc_chain(struct tun_table *map, uint8_t len,
490                          struct tun_metadata_loc_chain *loc)
491                          OVS_REQUIRES(tab_mutex)
492 {
493     int alloc_len = len / 4;
494     int scan_start = 0;
495     int scan_end = TUN_METADATA_TOT_OPT_SIZE / 4;
496     int pos_start, pos_end, pos_len;
497     int best_start = 0, best_len = 0;
498
499     while (true) {
500         pos_start = bitmap_scan(map->alloc_map, 0, scan_start, scan_end);
501         if (pos_start == scan_end) {
502             break;
503         }
504
505         pos_end = bitmap_scan(map->alloc_map, 1, pos_start,
506                               MIN(pos_start + alloc_len, scan_end));
507         pos_len = pos_end - pos_start;
508         if (pos_len == alloc_len) {
509             goto found;
510         }
511
512         if (pos_len > best_len) {
513             best_start = pos_start;
514             best_len = pos_len;
515         }
516         scan_start = pos_end + 1;
517     }
518
519     if (best_len == 0) {
520         return ENOSPC;
521     }
522
523     pos_start = best_start;
524     pos_len = best_len;
525
526 found:
527     bitmap_set_multiple(map->alloc_map, pos_start, pos_len, 1);
528     loc->offset = pos_start * 4;
529     loc->len = pos_len * 4;
530
531     return 0;
532 }
533
534 static enum ofperr
535 tun_metadata_add_entry(struct tun_table *map, uint8_t idx, uint16_t opt_class,
536                        uint8_t type, uint8_t len) OVS_REQUIRES(tab_mutex)
537 {
538     struct tun_meta_entry *entry;
539     struct tun_metadata_loc_chain *cur_chain, *prev_chain;
540
541     ovs_assert(idx < TUN_METADATA_NUM_OPTS);
542
543     entry = &map->entries[idx];
544     if (entry->valid) {
545         return OFPERR_NXGTMFC_ALREADY_MAPPED;
546     }
547
548     entry->key = tun_meta_key(htons(opt_class), type);
549     if (tun_meta_find_key(&map->key_hmap, entry->key)) {
550         return OFPERR_NXGTMFC_DUP_ENTRY;
551     }
552
553     entry->valid = true;
554     hmap_insert(&map->key_hmap, &entry->node,
555                 tun_meta_hash(entry->key));
556
557     entry->loc.len = len;
558     cur_chain = &entry->loc.c;
559     memset(cur_chain, 0, sizeof *cur_chain);
560     prev_chain = NULL;
561
562     while (len) {
563         int err;
564
565         if (!cur_chain) {
566             cur_chain = xzalloc(sizeof *cur_chain);
567         }
568
569         err = tun_metadata_alloc_chain(map, len, cur_chain);
570         if (err) {
571             tun_metadata_del_entry(map, idx);
572             return OFPERR_NXGTMFC_TABLE_FULL;
573         }
574
575         len -= cur_chain->len;
576
577         if (prev_chain) {
578             prev_chain->next = cur_chain;
579         }
580         prev_chain = cur_chain;
581         cur_chain = NULL;
582     }
583
584     return 0;
585 }
586
587 static void
588 tun_metadata_del_entry(struct tun_table *map, uint8_t idx)
589                        OVS_REQUIRES(tab_mutex)
590 {
591     struct tun_meta_entry *entry;
592     struct tun_metadata_loc_chain *chain;
593
594     if (idx >= TUN_METADATA_NUM_OPTS) {
595         return;
596     }
597
598     entry = &map->entries[idx];
599     if (!entry->valid) {
600         return;
601     }
602
603     chain = &entry->loc.c;
604     while (chain) {
605         struct tun_metadata_loc_chain *next = chain->next;
606
607         bitmap_set_multiple(map->alloc_map, chain->offset / 4,
608                             chain->len / 4, 0);
609         if (chain != &entry->loc.c) {
610             free(chain);
611         }
612         chain = next;
613     }
614
615     entry->valid = false;
616     hmap_remove(&map->key_hmap, &entry->node);
617     memset(&entry->loc, 0, sizeof entry->loc);
618 }
619
620 static int
621 tun_metadata_from_geneve__(const struct tun_metadata *flow_metadata,
622                            const struct geneve_opt *opt,
623                            const struct geneve_opt *flow_opt, int opts_len,
624                            struct tun_metadata *metadata)
625 {
626     struct tun_table *map;
627     bool is_mask = flow_opt != opt;
628
629     if (!is_mask) {
630         map = ovsrcu_get(struct tun_table *, &metadata_tab);
631         metadata->tab = map;
632     } else {
633         map = flow_metadata->tab;
634     }
635
636     if (!map) {
637         return 0;
638     }
639
640     while (opts_len > 0) {
641         int len;
642         struct tun_meta_entry *entry;
643
644         if (opts_len < sizeof(*opt)) {
645             return EINVAL;
646         }
647
648         len = sizeof(*opt) + flow_opt->length * 4;
649         if (len > opts_len) {
650             return EINVAL;
651         }
652
653         entry = tun_meta_find_key(&map->key_hmap,
654                                   tun_meta_key(flow_opt->opt_class,
655                                                flow_opt->type));
656         if (entry) {
657             if (entry->loc.len == flow_opt->length * 4) {
658                 memcpy_to_metadata(metadata, opt + 1, &entry->loc,
659                                    entry - map->entries);
660             } else {
661                 return EINVAL;
662             }
663         } else if (flow_opt->type & GENEVE_CRIT_OPT_TYPE) {
664             return EINVAL;
665         }
666
667         opt = opt + len / sizeof(*opt);
668         flow_opt = flow_opt + len / sizeof(*opt);
669         opts_len -= len;
670     }
671
672     return 0;
673 }
674
675 static const struct nlattr *
676 tun_metadata_find_geneve_key(const struct nlattr *key, uint32_t key_len)
677 {
678     const struct nlattr *tnl_key;
679
680     tnl_key = nl_attr_find__(key, key_len, OVS_KEY_ATTR_TUNNEL);
681     if (!tnl_key) {
682         return NULL;
683     }
684
685     return nl_attr_find_nested(tnl_key, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS);
686 }
687
688 /* Converts from Geneve netlink attributes in 'attr' to tunnel metadata
689  * in 'tun'. The result may either in be UDPIF format or not, as determined
690  * by 'udpif'.
691  *
692  * In the event that a mask is being converted, it is also necessary to
693  * pass in flow information. This includes the full set of netlink attributes
694  * (i.e. not just the Geneve attribute) in 'flow_attrs'/'flow_attr_len' and
695  * the previously converted tunnel metadata 'flow_tun'.
696  *
697  * If a flow rather than mask is being converted, 'flow_attrs' must be NULL. */
698 int
699 tun_metadata_from_geneve_nlattr(const struct nlattr *attr,
700                                 const struct nlattr *flow_attrs,
701                                 size_t flow_attr_len,
702                                 const struct flow_tnl *flow_tun, bool udpif,
703                                 struct flow_tnl *tun)
704 {
705     bool is_mask = !!flow_attrs;
706     int attr_len = nl_attr_get_size(attr);
707     const struct nlattr *flow;
708
709     /* No need for real translation, just copy things over. */
710     if (udpif) {
711         memcpy(tun->metadata.opts.gnv, nl_attr_get(attr), attr_len);
712
713         if (!is_mask) {
714             tun->metadata.present.len = attr_len;
715             tun->flags |= FLOW_TNL_F_UDPIF;
716         } else {
717             /* We need to exact match on the length so we don't
718              * accidentally match on sets of options that are the same
719              * at the beginning but with additional options after. */
720             tun->metadata.present.len = 0xff;
721         }
722
723         return 0;
724     }
725
726     if (is_mask) {
727         flow = tun_metadata_find_geneve_key(flow_attrs, flow_attr_len);
728         if (!flow) {
729             return attr_len ? EINVAL : 0;
730         }
731
732         if (attr_len != nl_attr_get_size(flow)) {
733             return EINVAL;
734         }
735     } else {
736         flow = attr;
737     }
738
739     return tun_metadata_from_geneve__(&flow_tun->metadata, nl_attr_get(attr),
740                                       nl_attr_get(flow), nl_attr_get_size(flow),
741                                       &tun->metadata);
742 }
743
744 /* Converts from the flat Geneve options representation extracted directly
745  * from the tunnel header to the representation that maps options to
746  * pre-allocated locations. The original version (in UDPIF form) is passed
747  * in 'src' and the translated form in stored in 'dst'.  To handle masks, the
748  * flow must also be passed in through 'flow' (in the original, raw form). */
749 int
750 tun_metadata_from_geneve_udpif(const struct flow_tnl *flow,
751                                const struct flow_tnl *src,
752                                struct flow_tnl *dst)
753 {
754     ovs_assert(flow->flags & FLOW_TNL_F_UDPIF);
755
756     if (flow == src) {
757         dst->flags = flow->flags & ~FLOW_TNL_F_UDPIF;
758     } else {
759         dst->metadata.tab = NULL;
760     }
761     dst->metadata.present.map = 0;
762     return tun_metadata_from_geneve__(&flow->metadata, src->metadata.opts.gnv,
763                                       flow->metadata.opts.gnv,
764                                       flow->metadata.present.len,
765                                       &dst->metadata);
766 }
767
768 static void
769 tun_metadata_to_geneve__(const struct tun_metadata *flow, struct ofpbuf *b,
770                          bool *crit_opt)
771 {
772     struct tun_table *map;
773     int i;
774
775     map = flow->tab;
776     if (!map) {
777         map = ovsrcu_get(struct tun_table *, &metadata_tab);
778     }
779
780     *crit_opt = false;
781
782     ULLONG_FOR_EACH_1 (i, flow->present.map) {
783         struct tun_meta_entry *entry = &map->entries[i];
784         struct geneve_opt *opt;
785
786         opt = ofpbuf_put_uninit(b, sizeof *opt + entry->loc.len);
787
788         opt->opt_class = tun_key_class(entry->key);
789         opt->type = tun_key_type(entry->key);
790         opt->length = entry->loc.len / 4;
791         opt->r1 = 0;
792         opt->r2 = 0;
793         opt->r3 = 0;
794
795         memcpy_from_metadata(opt + 1, flow, &entry->loc);
796         *crit_opt |= !!(opt->type & GENEVE_CRIT_OPT_TYPE);
797     }
798 }
799
800 static void
801 tun_metadata_to_geneve_nlattr_flow(const struct flow_tnl *flow,
802                                    struct ofpbuf *b)
803 {
804     size_t nlattr_offset;
805     bool crit_opt;
806
807     if (!flow->metadata.present.map) {
808         return;
809     }
810
811     /* For all intents and purposes, the Geneve options are nested
812      * attributes even if this doesn't show up directly to netlink. It's
813      * similar enough that we can use the same mechanism. */
814     nlattr_offset = nl_msg_start_nested(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS);
815
816     tun_metadata_to_geneve__(&flow->metadata, b, &crit_opt);
817
818     nl_msg_end_nested(b, nlattr_offset);
819 }
820
821 /* Converts from processed tunnel metadata information (in non-udpif
822  * format) in 'flow' to a stream of Geneve options suitable for
823  * transmission in 'opts'. Additionally returns whether there were
824  * any critical options in 'crit_opt' as well as the total length of
825  * data. */
826 int
827 tun_metadata_to_geneve_header(const struct flow_tnl *flow,
828                               struct geneve_opt *opts, bool *crit_opt)
829 {
830     struct ofpbuf b;
831
832     ovs_assert(!(flow->flags & FLOW_TNL_F_UDPIF));
833
834     ofpbuf_use_stack(&b, opts, GENEVE_TOT_OPT_SIZE);
835     tun_metadata_to_geneve__(&flow->metadata, &b, crit_opt);
836
837     return b.size;
838 }
839
840 static void
841 tun_metadata_to_geneve_mask__(const struct tun_metadata *flow,
842                               const struct tun_metadata *mask,
843                               struct geneve_opt *opt, int opts_len)
844 {
845     struct tun_table *map = flow->tab;
846
847     if (!map) {
848         return;
849     }
850
851     /* All of these options have already been validated, so no need
852      * for sanity checking. */
853     while (opts_len > 0) {
854         struct tun_meta_entry *entry;
855         int len = sizeof(*opt) + opt->length * 4;
856
857         entry = tun_meta_find_key(&map->key_hmap,
858                                   tun_meta_key(opt->opt_class, opt->type));
859         if (entry) {
860             memcpy_from_metadata(opt + 1, mask, &entry->loc);
861         } else {
862             memset(opt + 1, 0, opt->length * 4);
863         }
864
865         opt->opt_class = htons(0xffff);
866         opt->type = 0xff;
867         opt->length = 0x1f;
868         opt->r1 = 0;
869         opt->r2 = 0;
870         opt->r3 = 0;
871
872         opt = opt + len / sizeof(*opt);
873         opts_len -= len;
874     }
875 }
876
877 static void
878 tun_metadata_to_geneve_nlattr_mask(const struct ofpbuf *key,
879                                    const struct flow_tnl *mask,
880                                    const struct flow_tnl *flow,
881                                    struct ofpbuf *b)
882 {
883     const struct nlattr *geneve_key;
884     struct nlattr *geneve_mask;
885     struct geneve_opt *opt;
886     int opts_len;
887
888     if (!key) {
889         return;
890     }
891
892     geneve_key = tun_metadata_find_geneve_key(key->data, key->size);
893     if (!geneve_key) {
894         return;
895     }
896
897     geneve_mask = ofpbuf_tail(b);
898     nl_msg_put(b, geneve_key, geneve_key->nla_len);
899
900     opt = CONST_CAST(struct geneve_opt *, nl_attr_get(geneve_mask));
901     opts_len = nl_attr_get_size(geneve_mask);
902
903     tun_metadata_to_geneve_mask__(&flow->metadata, &mask->metadata,
904                                   opt, opts_len);
905 }
906
907 /* Convert from the tunnel metadata in 'tun' to netlink attributes stored
908  * in 'b'. Either UDPIF or non-UDPIF input forms are accepted.
909  *
910  * To assist with parsing, it is necessary to also pass in the tunnel metadata
911  * from the flow in 'flow' as well in the original netlink form of the flow in
912  * 'key'. */
913 void
914 tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
915                               const struct flow_tnl *flow,
916                               const struct ofpbuf *key,
917                               struct ofpbuf *b)
918 {
919     bool is_mask = tun != flow;
920
921     if (!(flow->flags & FLOW_TNL_F_UDPIF)) {
922         if (!is_mask) {
923             tun_metadata_to_geneve_nlattr_flow(tun, b);
924         } else {
925             tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
926         }
927     } else if (flow->metadata.present.len || is_mask) {
928         nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
929                           tun->metadata.opts.gnv,
930                           flow->metadata.present.len);
931     }
932 }
933
934 /* Converts 'mask_src' (in non-UDPIF format) to a series of masked options in
935  * 'dst'. 'flow_src' (also in non-UDPIF format) and the  original set of
936  * options 'flow_src_opt'/'opts_len' are needed as a guide to interpret the
937  * mask data. */
938 void
939 tun_metadata_to_geneve_udpif_mask(const struct flow_tnl *flow_src,
940                                   const struct flow_tnl *mask_src,
941                                   const struct geneve_opt *flow_src_opt,
942                                   int opts_len, struct geneve_opt *dst)
943 {
944     ovs_assert(!(flow_src->flags & FLOW_TNL_F_UDPIF));
945
946     memcpy(dst, flow_src_opt, opts_len);
947     tun_metadata_to_geneve_mask__(&flow_src->metadata,
948                                   &mask_src->metadata, dst, opts_len);
949 }
950
951 static const struct tun_metadata_loc *
952 metadata_loc_from_match_read(struct tun_table *map, const struct match *match,
953                              unsigned int idx)
954 {
955     if (match->tun_md.valid) {
956         return &match->tun_md.loc[idx];
957     }
958
959     return &map->entries[idx].loc;
960 }
961
962 void
963 tun_metadata_to_nx_match(struct ofpbuf *b, enum ofp_version oxm,
964                          const struct match *match)
965 {
966     struct flow_tnl flow, mask;
967     int i;
968
969     if (!udpif_to_parsed(&match->flow.tunnel, &match->wc.masks.tunnel,
970                          &flow, &mask)) {
971         return;
972     }
973
974     ULLONG_FOR_EACH_1 (i, mask.metadata.present.map) {
975         const struct tun_metadata_loc *loc;
976         union mf_value opts;
977         union mf_value mask_opts;
978
979         loc = metadata_loc_from_match_read(flow.metadata.tab, match, i);
980         memcpy_from_metadata(opts.tun_metadata, &flow.metadata, loc);
981         memcpy_from_metadata(mask_opts.tun_metadata, &mask.metadata, loc);
982         nxm_put(b, MFF_TUN_METADATA0 + i, oxm, opts.tun_metadata,
983                 mask_opts.tun_metadata, loc->len);
984     }
985 }
986
987 void
988 tun_metadata_match_format(struct ds *s, const struct match *match)
989 {
990     struct flow_tnl flow, mask;
991     unsigned int i;
992
993     if (!udpif_to_parsed(&match->flow.tunnel, &match->wc.masks.tunnel,
994                          &flow, &mask)) {
995         return;
996     }
997
998     ULLONG_FOR_EACH_1 (i, mask.metadata.present.map) {
999         const struct tun_metadata_loc *loc;
1000         union mf_value opts;
1001
1002         loc = metadata_loc_from_match_read(flow.metadata.tab, match, i);
1003
1004         ds_put_format(s, "tun_metadata%u=", i);
1005         memcpy_from_metadata(opts.tun_metadata, &flow.metadata, loc);
1006         ds_put_hex(s, opts.tun_metadata, loc->len);
1007
1008         memcpy_from_metadata(opts.tun_metadata, &mask.metadata, loc);
1009         if (!is_all_ones(opts.tun_metadata, loc->len)) {
1010             ds_put_char(s, '/');
1011             ds_put_hex(s, opts.tun_metadata, loc->len);
1012         }
1013         ds_put_char(s, ',');
1014     }
1015 }