forked from openvswitch/ovs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtun-metadata.h
149 lines (131 loc) · 6.57 KB
/
tun-metadata.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* Copyright (c) 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TUN_METADATA_H
#define TUN_METADATA_H 1
#include <stdint.h>
#include "dynamic-string.h"
#include "geneve.h"
#include "netlink.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
struct flow_tnl;
struct match;
struct mf_field;
union mf_value;
struct ofputil_geneve_table_mod;
struct ofputil_geneve_table_reply;
struct tun_table;
#define TUN_METADATA_NUM_OPTS 64
#define TUN_METADATA_TOT_OPT_SIZE 256
/* Tunnel option data, plus metadata to aid in their interpretation.
*
* The option data exists in two forms and is interpreted differently depending
* on whether FLOW_TNL_F_UDPIF is set in struct flow_tnl flags:
*
* When FLOW_TNL_F_UDPIF is set, the tunnel metadata is in "userspace datapath
* format". This is typically used for fast-path packet processing to avoid
* the cost of translating options and in situations where we need to maintain
* tunnel metadata exactly as it came in. In this case 'opts.gnv' is raw
* packet data from the tunnel header and 'present.len' indicates the length
* of the data stored there. In these situations, 'tab' is NULL.
*
* In all other cases, we are doing flow-based processing (such as during
* upcalls). FLOW_TNL_F_UDPIF is not set and options are reordered into
* pre-allocated locations. 'present.map' is indexed by type, that is, by the
* <i> in TUN_METADATA<i>, so that e.g. TUN_METADATA5 is present if
* 'present.map & (1ULL << 5)' is nonzero. The actual data for TUN_METADATA5,
* if present, might be anywhere in 'opts.u8' (not necessarily even contiguous),
* and finding it requires referring to 'tab', if set, or the global metadata
* table. */
struct tun_metadata {
union { /* Valid members of 'opts'. When 'opts' is sorted into known types,
* 'map' is used. When 'opts' is raw packet data, 'len' is used. */
uint64_t map; /* 1-bit for each present TLV. */
uint8_t len; /* Length of data in 'opts'. */
} present;
struct tun_table *tab; /* Types & lengths for 'opts' and 'opt_map'. */
uint8_t pad[sizeof(uint64_t) - sizeof(struct tun_table *)]; /* Make 8 bytes */
union {
uint8_t u8[TUN_METADATA_TOT_OPT_SIZE]; /* Values from tunnel TLVs. */
struct geneve_opt gnv[GENEVE_TOT_OPT_SIZE / sizeof(struct geneve_opt)];
} opts;
};
BUILD_ASSERT_DECL(sizeof(((struct tun_metadata *)0)->present.map) * 8 >=
TUN_METADATA_NUM_OPTS);
/* The location of an option can be stored either as a single offset/len
* pair (hopefully) or if the address space is fragmented then it is a
* linked list of these blocks. */
struct tun_metadata_loc_chain {
struct tun_metadata_loc_chain *next;
int offset; /* In bytes, from start of 'opts', multiple of 4. */
int len; /* In bytes, multiple of 4. */
};
struct tun_metadata_loc {
int len; /* Sum of 'len' over elements in chain. */
struct tun_metadata_loc_chain c;
};
/* Bookkeeping information to keep track of an option that was allocated
* inside struct match. */
struct tun_metadata_match_entry {
struct tun_metadata_loc loc; /* Allocated position. */
bool masked; /* Source value had a mask. Otherwise we can't tell if the
* entire field was exact matched or only the portion that
* is the same size as the value. */
};
/* Allocation of options inside struct match. This is important if we don't
* have access to a global allocation table - either because there isn't one
* (ovs-ofctl) or if we need to keep the allocation outside of packet
* processing context (Packet-In). These structures never have dynamically
* allocated memory because the address space is never fragmented. */
struct tun_metadata_allocation {
struct tun_metadata_match_entry entry[TUN_METADATA_NUM_OPTS];
int alloc_offset; /* Byte offset into 'opts', multiple of 4. */
bool valid; /* Set to true after any allocation occurs. */
};
void tun_metadata_init(void);
enum ofperr tun_metadata_table_mod(struct ofputil_geneve_table_mod *);
void tun_metadata_table_request(struct ofputil_geneve_table_reply *);
void tun_metadata_read(const struct flow_tnl *,
const struct mf_field *, union mf_value *);
void tun_metadata_write(struct flow_tnl *,
const struct mf_field *, const union mf_value *);
void tun_metadata_set_match(const struct mf_field *,
const union mf_value *value,
const union mf_value *mask, struct match *,
char **err_str);
void tun_metadata_get_fmd(const struct flow_tnl *, struct match *flow_metadata);
int tun_metadata_from_geneve_nlattr(const struct nlattr *attr,
const struct nlattr *flow_attrs,
size_t flow_attr_len,
const struct flow_tnl *flow_tun,
bool udpif, struct flow_tnl *tun);
void tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
const struct flow_tnl *flow,
const struct ofpbuf *key,
struct ofpbuf *);
int tun_metadata_from_geneve_udpif(const struct flow_tnl *flow,
const struct flow_tnl *src,
struct flow_tnl *dst);
void tun_metadata_to_geneve_udpif_mask(const struct flow_tnl *flow_src,
const struct flow_tnl *mask_src,
const struct geneve_opt *flow_src_opt,
int opts_len, struct geneve_opt *dst);
int tun_metadata_to_geneve_header(const struct flow_tnl *flow,
struct geneve_opt *, bool *crit_opt);
void tun_metadata_to_nx_match(struct ofpbuf *b, enum ofp_version oxm,
const struct match *);
void tun_metadata_match_format(struct ds *, const struct match *);
#endif /* tun-metadata.h */