Blame view

net/openvswitch/flow_netlink.c 96.4 KB
c94229992   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
e64457191   Pravin B Shelar   openvswitch: Rest...
2
  /*
798c16617   andy zhou   openvswitch: Opti...
3
   * Copyright (c) 2007-2017 Nicira, Inc.
e64457191   Pravin B Shelar   openvswitch: Rest...
4
   */
2235ad1c3   Joe Perches   openvswitch: flow...
5
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
e64457191   Pravin B Shelar   openvswitch: Rest...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  #include "flow.h"
  #include "datapath.h"
  #include <linux/uaccess.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/if_ether.h>
  #include <linux/if_vlan.h>
  #include <net/llc_pdu.h>
  #include <linux/kernel.h>
  #include <linux/jhash.h>
  #include <linux/jiffies.h>
  #include <linux/llc.h>
  #include <linux/module.h>
  #include <linux/in.h>
  #include <linux/rcupdate.h>
  #include <linux/if_arp.h>
  #include <linux/ip.h>
  #include <linux/ipv6.h>
  #include <linux/sctp.h>
  #include <linux/tcp.h>
  #include <linux/udp.h>
  #include <linux/icmp.h>
  #include <linux/icmpv6.h>
  #include <linux/rculist.h>
f57966840   Jesse Gross   openvswitch: Add ...
30
  #include <net/geneve.h>
e64457191   Pravin B Shelar   openvswitch: Rest...
31
32
33
  #include <net/ip.h>
  #include <net/ipv6.h>
  #include <net/ndisc.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
34
  #include <net/mpls.h>
614732eaa   Thomas Graf   openvswitch: Use ...
35
  #include <net/vxlan.h>
b2d0f5d5d   Yi Yang   openvswitch: enab...
36
  #include <net/tun_proto.h>
fc1372f89   William Tu   openvswitch: add ...
37
  #include <net/erspan.h>
e64457191   Pravin B Shelar   openvswitch: Rest...
38
39
  
  #include "flow_netlink.h"
81bfe3c3c   Thomas Graf   openvswitch: Allo...
40
41
42
43
44
45
  struct ovs_len_tbl {
  	int len;
  	const struct ovs_len_tbl *next;
  };
  
  #define OVS_ATTR_NESTED -1
982b52700   Jesse Gross   openvswitch: Fix ...
46
  #define OVS_ATTR_VARIABLE -2
81bfe3c3c   Thomas Graf   openvswitch: Allo...
47

798c16617   andy zhou   openvswitch: Opti...
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  static bool actions_may_change_flow(const struct nlattr *actions)
  {
  	struct nlattr *nla;
  	int rem;
  
  	nla_for_each_nested(nla, actions, rem) {
  		u16 action = nla_type(nla);
  
  		switch (action) {
  		case OVS_ACTION_ATTR_OUTPUT:
  		case OVS_ACTION_ATTR_RECIRC:
  		case OVS_ACTION_ATTR_TRUNC:
  		case OVS_ACTION_ATTR_USERSPACE:
  			break;
  
  		case OVS_ACTION_ATTR_CT:
b8226962b   Eric Garver   openvswitch: add ...
64
  		case OVS_ACTION_ATTR_CT_CLEAR:
798c16617   andy zhou   openvswitch: Opti...
65
66
67
  		case OVS_ACTION_ATTR_HASH:
  		case OVS_ACTION_ATTR_POP_ETH:
  		case OVS_ACTION_ATTR_POP_MPLS:
b2d0f5d5d   Yi Yang   openvswitch: enab...
68
  		case OVS_ACTION_ATTR_POP_NSH:
798c16617   andy zhou   openvswitch: Opti...
69
70
71
  		case OVS_ACTION_ATTR_POP_VLAN:
  		case OVS_ACTION_ATTR_PUSH_ETH:
  		case OVS_ACTION_ATTR_PUSH_MPLS:
b2d0f5d5d   Yi Yang   openvswitch: enab...
72
  		case OVS_ACTION_ATTR_PUSH_NSH:
798c16617   andy zhou   openvswitch: Opti...
73
74
75
76
  		case OVS_ACTION_ATTR_PUSH_VLAN:
  		case OVS_ACTION_ATTR_SAMPLE:
  		case OVS_ACTION_ATTR_SET:
  		case OVS_ACTION_ATTR_SET_MASKED:
cd8a6c336   Andy Zhou   openvswitch: Add ...
77
  		case OVS_ACTION_ATTR_METER:
4d5ec89fc   Numan Siddique   net: openvswitch:...
78
  		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
f66b53fdb   Martin Varghese   openvswitch: New ...
79
  		case OVS_ACTION_ATTR_ADD_MPLS:
744676e77   Matteo Croce   openvswitch: add ...
80
  		case OVS_ACTION_ATTR_DEC_TTL:
798c16617   andy zhou   openvswitch: Opti...
81
82
83
84
85
86
  		default:
  			return true;
  		}
  	}
  	return false;
  }
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
87
88
  static void update_range(struct sw_flow_match *match,
  			 size_t offset, size_t size, bool is_mask)
e64457191   Pravin B Shelar   openvswitch: Rest...
89
  {
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
90
  	struct sw_flow_key_range *range;
e64457191   Pravin B Shelar   openvswitch: Rest...
91
92
93
94
95
  	size_t start = rounddown(offset, sizeof(long));
  	size_t end = roundup(offset + size, sizeof(long));
  
  	if (!is_mask)
  		range = &match->range;
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
96
  	else
e64457191   Pravin B Shelar   openvswitch: Rest...
97
  		range = &match->mask->range;
e64457191   Pravin B Shelar   openvswitch: Rest...
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	if (range->start == range->end) {
  		range->start = start;
  		range->end = end;
  		return;
  	}
  
  	if (range->start > start)
  		range->start = start;
  
  	if (range->end < end)
  		range->end = end;
  }
  
  #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
  	do { \
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
113
114
115
116
117
  		update_range(match, offsetof(struct sw_flow_key, field),    \
  			     sizeof((match)->key->field), is_mask);	    \
  		if (is_mask)						    \
  			(match)->mask->key.field = value;		    \
  		else							    \
e64457191   Pravin B Shelar   openvswitch: Rest...
118
  			(match)->key->field = value;		            \
e64457191   Pravin B Shelar   openvswitch: Rest...
119
  	} while (0)
f57966840   Jesse Gross   openvswitch: Add ...
120
121
  #define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask)	    \
  	do {								    \
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
122
  		update_range(match, offset, len, is_mask);		    \
f57966840   Jesse Gross   openvswitch: Add ...
123
124
  		if (is_mask)						    \
  			memcpy((u8 *)&(match)->mask->key + offset, value_p, \
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
125
  			       len);					   \
f57966840   Jesse Gross   openvswitch: Add ...
126
127
  		else							    \
  			memcpy((u8 *)(match)->key + offset, value_p, len);  \
e64457191   Pravin B Shelar   openvswitch: Rest...
128
  	} while (0)
f57966840   Jesse Gross   openvswitch: Add ...
129
130
131
  #define SW_FLOW_KEY_MEMCPY(match, field, value_p, len, is_mask)		      \
  	SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \
  				  value_p, len, is_mask)
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
132
133
134
135
136
137
138
139
  #define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask)		    \
  	do {								    \
  		update_range(match, offsetof(struct sw_flow_key, field),    \
  			     sizeof((match)->key->field), is_mask);	    \
  		if (is_mask)						    \
  			memset((u8 *)&(match)->mask->key.field, value,      \
  			       sizeof((match)->mask->key.field));	    \
  		else							    \
f47de068f   Pravin B Shelar   openvswitch: Crea...
140
141
  			memset((u8 *)&(match)->key->field, value,           \
  			       sizeof((match)->key->field));                \
f47de068f   Pravin B Shelar   openvswitch: Crea...
142
  	} while (0)
e64457191   Pravin B Shelar   openvswitch: Rest...
143
144
  
  static bool match_validate(const struct sw_flow_match *match,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
145
  			   u64 key_attrs, u64 mask_attrs, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
146
  {
0a6410fbd   Jiri Benc   openvswitch: netl...
147
  	u64 key_expected = 0;
e64457191   Pravin B Shelar   openvswitch: Rest...
148
149
150
151
152
  	u64 mask_allowed = key_attrs;  /* At most allow all key attributes */
  
  	/* The following mask attributes allowed only if they
  	 * pass the validation tests. */
  	mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4)
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
153
  			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)
e64457191   Pravin B Shelar   openvswitch: Rest...
154
  			| (1 << OVS_KEY_ATTR_IPV6)
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
155
  			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)
e64457191   Pravin B Shelar   openvswitch: Rest...
156
  			| (1 << OVS_KEY_ATTR_TCP)
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
157
  			| (1 << OVS_KEY_ATTR_TCP_FLAGS)
e64457191   Pravin B Shelar   openvswitch: Rest...
158
159
160
161
162
  			| (1 << OVS_KEY_ATTR_UDP)
  			| (1 << OVS_KEY_ATTR_SCTP)
  			| (1 << OVS_KEY_ATTR_ICMP)
  			| (1 << OVS_KEY_ATTR_ICMPV6)
  			| (1 << OVS_KEY_ATTR_ARP)
25cd9ba0a   Simon Horman   openvswitch: Add ...
163
  			| (1 << OVS_KEY_ATTR_ND)
b2d0f5d5d   Yi Yang   openvswitch: enab...
164
165
  			| (1 << OVS_KEY_ATTR_MPLS)
  			| (1 << OVS_KEY_ATTR_NSH));
e64457191   Pravin B Shelar   openvswitch: Rest...
166
167
168
169
170
171
172
173
174
175
  
  	/* Always allowed mask fields. */
  	mask_allowed |= ((1 << OVS_KEY_ATTR_TUNNEL)
  		       | (1 << OVS_KEY_ATTR_IN_PORT)
  		       | (1 << OVS_KEY_ATTR_ETHERTYPE));
  
  	/* Check key attributes. */
  	if (match->key->eth.type == htons(ETH_P_ARP)
  			|| match->key->eth.type == htons(ETH_P_RARP)) {
  		key_expected |= 1 << OVS_KEY_ATTR_ARP;
f2a01517f   Pravin B Shelar   openvswitch: Fix ...
176
  		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
e64457191   Pravin B Shelar   openvswitch: Rest...
177
178
  			mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
  	}
25cd9ba0a   Simon Horman   openvswitch: Add ...
179
180
181
182
183
  	if (eth_p_mpls(match->key->eth.type)) {
  		key_expected |= 1 << OVS_KEY_ATTR_MPLS;
  		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
  			mask_allowed |= 1 << OVS_KEY_ATTR_MPLS;
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
184
185
  	if (match->key->eth.type == htons(ETH_P_IP)) {
  		key_expected |= 1 << OVS_KEY_ATTR_IPV4;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
186
  		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {
e64457191   Pravin B Shelar   openvswitch: Rest...
187
  			mask_allowed |= 1 << OVS_KEY_ATTR_IPV4;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
188
189
  			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  
  		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
  			if (match->key->ip.proto == IPPROTO_UDP) {
  				key_expected |= 1 << OVS_KEY_ATTR_UDP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
  			}
  
  			if (match->key->ip.proto == IPPROTO_SCTP) {
  				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
  			}
  
  			if (match->key->ip.proto == IPPROTO_TCP) {
  				key_expected |= 1 << OVS_KEY_ATTR_TCP;
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
206
207
  				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
  				if (match->mask && (match->mask->key.ip.proto == 0xff)) {
e64457191   Pravin B Shelar   openvswitch: Rest...
208
  					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
209
210
  					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
  				}
e64457191   Pravin B Shelar   openvswitch: Rest...
211
212
213
214
215
216
217
218
219
220
221
222
  			}
  
  			if (match->key->ip.proto == IPPROTO_ICMP) {
  				key_expected |= 1 << OVS_KEY_ATTR_ICMP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_ICMP;
  			}
  		}
  	}
  
  	if (match->key->eth.type == htons(ETH_P_IPV6)) {
  		key_expected |= 1 << OVS_KEY_ATTR_IPV6;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
223
  		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {
e64457191   Pravin B Shelar   openvswitch: Rest...
224
  			mask_allowed |= 1 << OVS_KEY_ATTR_IPV6;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
225
226
  			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  
  		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
  			if (match->key->ip.proto == IPPROTO_UDP) {
  				key_expected |= 1 << OVS_KEY_ATTR_UDP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
  			}
  
  			if (match->key->ip.proto == IPPROTO_SCTP) {
  				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
  			}
  
  			if (match->key->ip.proto == IPPROTO_TCP) {
  				key_expected |= 1 << OVS_KEY_ATTR_TCP;
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
243
244
  				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
  				if (match->mask && (match->mask->key.ip.proto == 0xff)) {
e64457191   Pravin B Shelar   openvswitch: Rest...
245
  					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
246
247
  					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
  				}
e64457191   Pravin B Shelar   openvswitch: Rest...
248
249
250
251
252
253
  			}
  
  			if (match->key->ip.proto == IPPROTO_ICMPV6) {
  				key_expected |= 1 << OVS_KEY_ATTR_ICMPV6;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6;
1139e241e   Jarno Rajahalme   openvswitch: Comp...
254
  				if (match->key->tp.src ==
e64457191   Pravin B Shelar   openvswitch: Rest...
255
  						htons(NDISC_NEIGHBOUR_SOLICITATION) ||
1139e241e   Jarno Rajahalme   openvswitch: Comp...
256
  				    match->key->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
e64457191   Pravin B Shelar   openvswitch: Rest...
257
  					key_expected |= 1 << OVS_KEY_ATTR_ND;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
258
259
260
261
262
263
  					/* Original direction conntrack tuple
  					 * uses the same space as the ND fields
  					 * in the key, so both are not allowed
  					 * at the same time.
  					 */
  					mask_allowed &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
f2a01517f   Pravin B Shelar   openvswitch: Fix ...
264
  					if (match->mask && (match->mask->key.tp.src == htons(0xff)))
e64457191   Pravin B Shelar   openvswitch: Rest...
265
266
267
268
269
  						mask_allowed |= 1 << OVS_KEY_ATTR_ND;
  				}
  			}
  		}
  	}
b2d0f5d5d   Yi Yang   openvswitch: enab...
270
271
272
273
274
275
276
  	if (match->key->eth.type == htons(ETH_P_NSH)) {
  		key_expected |= 1 << OVS_KEY_ATTR_NSH;
  		if (match->mask &&
  		    match->mask->key.eth.type == htons(0xffff)) {
  			mask_allowed |= 1 << OVS_KEY_ATTR_NSH;
  		}
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
277
278
  	if ((key_attrs & key_expected) != key_expected) {
  		/* Key attributes check failed. */
05da5898a   Jarno Rajahalme   openvswitch: Add ...
279
280
281
  		OVS_NLERR(log, "Missing key (keys=%llx, expected=%llx)",
  			  (unsigned long long)key_attrs,
  			  (unsigned long long)key_expected);
e64457191   Pravin B Shelar   openvswitch: Rest...
282
283
284
285
286
  		return false;
  	}
  
  	if ((mask_attrs & mask_allowed) != mask_attrs) {
  		/* Mask attributes check failed. */
05da5898a   Jarno Rajahalme   openvswitch: Add ...
287
288
289
  		OVS_NLERR(log, "Unexpected mask (mask=%llx, allowed=%llx)",
  			  (unsigned long long)mask_attrs,
  			  (unsigned long long)mask_allowed);
e64457191   Pravin B Shelar   openvswitch: Rest...
290
291
292
293
294
  		return false;
  	}
  
  	return true;
  }
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
295
296
297
298
299
  size_t ovs_tun_key_attr_size(void)
  {
  	/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
  	 * updating this function.
  	 */
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
300
  	return    nla_total_size_64bit(8) /* OVS_TUNNEL_KEY_ATTR_ID */
6b26ba3a7   Jiri Benc   openvswitch: netl...
301
302
  		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */
  		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
303
304
305
306
307
308
  		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */
  		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TTL */
  		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
  		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_CSUM */
  		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_OAM */
  		+ nla_total_size(256)  /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
fc1372f89   William Tu   openvswitch: add ...
309
310
  		/* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and
  		 * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with
1dd144cf5   Thomas Graf   openvswitch: Supp...
311
312
  		 * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.
  		 */
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
313
  		+ nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
95a332088   William Tu   Revert "openvswit...
314
  		+ nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
315
  }
06c2351fd   Wei Yongjun   openvswitch: Make...
316
  static size_t ovs_nsh_key_attr_size(void)
b2d0f5d5d   Yi Yang   openvswitch: enab...
317
318
319
320
321
322
323
324
325
326
327
  {
  	/* Whenever adding new OVS_NSH_KEY_ FIELDS, we should consider
  	 * updating this function.
  	 */
  	return  nla_total_size(NSH_BASE_HDR_LEN) /* OVS_NSH_KEY_ATTR_BASE */
  		/* OVS_NSH_KEY_ATTR_MD1 and OVS_NSH_KEY_ATTR_MD2 are
  		 * mutually exclusive, so the bigger one can cover
  		 * the small one.
  		 */
  		+ nla_total_size(NSH_CTX_HDRS_MAX_LEN);
  }
41af73e9c   Joe Stringer   openvswitch: Move...
328
329
330
331
332
  size_t ovs_key_attr_size(void)
  {
  	/* Whenever adding new OVS_KEY_ FIELDS, we should consider
  	 * updating this function.
  	 */
b2d0f5d5d   Yi Yang   openvswitch: enab...
333
  	BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 29);
41af73e9c   Joe Stringer   openvswitch: Move...
334
335
336
  
  	return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */
  		+ nla_total_size(0)   /* OVS_KEY_ATTR_TUNNEL */
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
337
  		  + ovs_tun_key_attr_size()
41af73e9c   Joe Stringer   openvswitch: Move...
338
339
340
341
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_IN_PORT */
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */
fbccce596   Joe Stringer   openvswitch: Exte...
342
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_STATE */
7f8a436ea   Joe Stringer   openvswitch: Add ...
343
  		+ nla_total_size(2)   /* OVS_KEY_ATTR_CT_ZONE */
182e3042e   Joe Stringer   openvswitch: Allo...
344
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_MARK */
33db4125e   Joe Stringer   openvswitch: Rena...
345
  		+ nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABELS */
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
346
  		+ nla_total_size(40)  /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */
b2d0f5d5d   Yi Yang   openvswitch: enab...
347
348
  		+ nla_total_size(0)   /* OVS_KEY_ATTR_NSH */
  		  + ovs_nsh_key_attr_size()
41af73e9c   Joe Stringer   openvswitch: Move...
349
350
351
352
353
354
355
356
357
  		+ nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
  		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
  		+ nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
  		+ nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */
  		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
  		+ nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */
  		+ nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */
  		+ nla_total_size(28); /* OVS_KEY_ATTR_ND */
  }
982b52700   Jesse Gross   openvswitch: Fix ...
358
359
360
  static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
  	[OVS_VXLAN_EXT_GBP]	    = { .len = sizeof(u32) },
  };
81bfe3c3c   Thomas Graf   openvswitch: Allo...
361
362
363
364
365
366
367
368
369
370
371
  static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
  	[OVS_TUNNEL_KEY_ATTR_ID]	    = { .len = sizeof(u64) },
  	[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]	    = { .len = sizeof(u32) },
  	[OVS_TUNNEL_KEY_ATTR_IPV4_DST]	    = { .len = sizeof(u32) },
  	[OVS_TUNNEL_KEY_ATTR_TOS]	    = { .len = 1 },
  	[OVS_TUNNEL_KEY_ATTR_TTL]	    = { .len = 1 },
  	[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = { .len = 0 },
  	[OVS_TUNNEL_KEY_ATTR_CSUM]	    = { .len = 0 },
  	[OVS_TUNNEL_KEY_ATTR_TP_SRC]	    = { .len = sizeof(u16) },
  	[OVS_TUNNEL_KEY_ATTR_TP_DST]	    = { .len = sizeof(u16) },
  	[OVS_TUNNEL_KEY_ATTR_OAM]	    = { .len = 0 },
982b52700   Jesse Gross   openvswitch: Fix ...
372
373
374
  	[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = OVS_ATTR_VARIABLE },
  	[OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = OVS_ATTR_NESTED,
  						.next = ovs_vxlan_ext_key_lens },
6b26ba3a7   Jiri Benc   openvswitch: netl...
375
376
  	[OVS_TUNNEL_KEY_ATTR_IPV6_SRC]      = { .len = sizeof(struct in6_addr) },
  	[OVS_TUNNEL_KEY_ATTR_IPV6_DST]      = { .len = sizeof(struct in6_addr) },
fc1372f89   William Tu   openvswitch: add ...
377
  	[OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS]   = { .len = OVS_ATTR_VARIABLE },
18b6f7174   wenxu   openvswitch: Make...
378
  	[OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE]   = { .len = 0 },
81bfe3c3c   Thomas Graf   openvswitch: Allo...
379
  };
b2d0f5d5d   Yi Yang   openvswitch: enab...
380
381
382
383
384
385
  static const struct ovs_len_tbl
  ovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
  	[OVS_NSH_KEY_ATTR_BASE] = { .len = sizeof(struct ovs_nsh_key_base) },
  	[OVS_NSH_KEY_ATTR_MD1]  = { .len = sizeof(struct ovs_nsh_key_md1) },
  	[OVS_NSH_KEY_ATTR_MD2]  = { .len = OVS_ATTR_VARIABLE },
  };
e64457191   Pravin B Shelar   openvswitch: Rest...
386
  /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
81bfe3c3c   Thomas Graf   openvswitch: Allo...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
  	[OVS_KEY_ATTR_ENCAP]	 = { .len = OVS_ATTR_NESTED },
  	[OVS_KEY_ATTR_PRIORITY]	 = { .len = sizeof(u32) },
  	[OVS_KEY_ATTR_IN_PORT]	 = { .len = sizeof(u32) },
  	[OVS_KEY_ATTR_SKB_MARK]	 = { .len = sizeof(u32) },
  	[OVS_KEY_ATTR_ETHERNET]	 = { .len = sizeof(struct ovs_key_ethernet) },
  	[OVS_KEY_ATTR_VLAN]	 = { .len = sizeof(__be16) },
  	[OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
  	[OVS_KEY_ATTR_IPV4]	 = { .len = sizeof(struct ovs_key_ipv4) },
  	[OVS_KEY_ATTR_IPV6]	 = { .len = sizeof(struct ovs_key_ipv6) },
  	[OVS_KEY_ATTR_TCP]	 = { .len = sizeof(struct ovs_key_tcp) },
  	[OVS_KEY_ATTR_TCP_FLAGS] = { .len = sizeof(__be16) },
  	[OVS_KEY_ATTR_UDP]	 = { .len = sizeof(struct ovs_key_udp) },
  	[OVS_KEY_ATTR_SCTP]	 = { .len = sizeof(struct ovs_key_sctp) },
  	[OVS_KEY_ATTR_ICMP]	 = { .len = sizeof(struct ovs_key_icmp) },
  	[OVS_KEY_ATTR_ICMPV6]	 = { .len = sizeof(struct ovs_key_icmpv6) },
  	[OVS_KEY_ATTR_ARP]	 = { .len = sizeof(struct ovs_key_arp) },
  	[OVS_KEY_ATTR_ND]	 = { .len = sizeof(struct ovs_key_nd) },
  	[OVS_KEY_ATTR_RECIRC_ID] = { .len = sizeof(u32) },
  	[OVS_KEY_ATTR_DP_HASH]	 = { .len = sizeof(u32) },
  	[OVS_KEY_ATTR_TUNNEL]	 = { .len = OVS_ATTR_NESTED,
  				     .next = ovs_tunnel_key_lens, },
fbdcdd78d   Martin Varghese   Change in Openvsw...
409
  	[OVS_KEY_ATTR_MPLS]	 = { .len = OVS_ATTR_VARIABLE },
fbccce596   Joe Stringer   openvswitch: Exte...
410
  	[OVS_KEY_ATTR_CT_STATE]	 = { .len = sizeof(u32) },
7f8a436ea   Joe Stringer   openvswitch: Add ...
411
  	[OVS_KEY_ATTR_CT_ZONE]	 = { .len = sizeof(u16) },
182e3042e   Joe Stringer   openvswitch: Allo...
412
  	[OVS_KEY_ATTR_CT_MARK]	 = { .len = sizeof(u32) },
33db4125e   Joe Stringer   openvswitch: Rena...
413
  	[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
414
415
416
417
  	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4] = {
  		.len = sizeof(struct ovs_key_ct_tuple_ipv4) },
  	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {
  		.len = sizeof(struct ovs_key_ct_tuple_ipv6) },
b2d0f5d5d   Yi Yang   openvswitch: enab...
418
419
  	[OVS_KEY_ATTR_NSH]       = { .len = OVS_ATTR_NESTED,
  				     .next = ovs_nsh_key_attr_lens, },
e64457191   Pravin B Shelar   openvswitch: Rest...
420
  };
982b52700   Jesse Gross   openvswitch: Fix ...
421
422
423
424
425
426
  static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
  {
  	return expected_len == attr_len ||
  	       expected_len == OVS_ATTR_NESTED ||
  	       expected_len == OVS_ATTR_VARIABLE;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
  static bool is_all_zero(const u8 *fp, size_t size)
  {
  	int i;
  
  	if (!fp)
  		return false;
  
  	for (i = 0; i < size; i++)
  		if (fp[i])
  			return false;
  
  	return true;
  }
  
  static int __parse_flow_nlattrs(const struct nlattr *attr,
  				const struct nlattr *a[],
05da5898a   Jarno Rajahalme   openvswitch: Add ...
443
  				u64 *attrsp, bool log, bool nz)
e64457191   Pravin B Shelar   openvswitch: Rest...
444
445
446
447
448
449
450
451
452
453
454
  {
  	const struct nlattr *nla;
  	u64 attrs;
  	int rem;
  
  	attrs = *attrsp;
  	nla_for_each_nested(nla, attr, rem) {
  		u16 type = nla_type(nla);
  		int expected_len;
  
  		if (type > OVS_KEY_ATTR_MAX) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
455
  			OVS_NLERR(log, "Key type %d is out of range max %d",
e64457191   Pravin B Shelar   openvswitch: Rest...
456
457
458
459
460
  				  type, OVS_KEY_ATTR_MAX);
  			return -EINVAL;
  		}
  
  		if (attrs & (1 << type)) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
461
  			OVS_NLERR(log, "Duplicate key (type %d).", type);
e64457191   Pravin B Shelar   openvswitch: Rest...
462
463
  			return -EINVAL;
  		}
81bfe3c3c   Thomas Graf   openvswitch: Allo...
464
  		expected_len = ovs_key_lens[type].len;
982b52700   Jesse Gross   openvswitch: Fix ...
465
  		if (!check_attr_len(nla_len(nla), expected_len)) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
466
467
  			OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
  				  type, nla_len(nla), expected_len);
e64457191   Pravin B Shelar   openvswitch: Rest...
468
469
  			return -EINVAL;
  		}
04a4af334   Ross Lagerwall   openvswitch: Avoi...
470
  		if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
e64457191   Pravin B Shelar   openvswitch: Rest...
471
472
473
474
475
  			attrs |= 1 << type;
  			a[type] = nla;
  		}
  	}
  	if (rem) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
476
  		OVS_NLERR(log, "Message has %d unknown bytes.", rem);
e64457191   Pravin B Shelar   openvswitch: Rest...
477
478
479
480
481
482
483
484
  		return -EINVAL;
  	}
  
  	*attrsp = attrs;
  	return 0;
  }
  
  static int parse_flow_mask_nlattrs(const struct nlattr *attr,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
485
486
  				   const struct nlattr *a[], u64 *attrsp,
  				   bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
487
  {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
488
  	return __parse_flow_nlattrs(attr, a, attrsp, log, true);
e64457191   Pravin B Shelar   openvswitch: Rest...
489
  }
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
490
491
  int parse_flow_nlattrs(const struct nlattr *attr, const struct nlattr *a[],
  		       u64 *attrsp, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
492
  {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
  	return __parse_flow_nlattrs(attr, a, attrsp, log, false);
  }
  
  static int genev_tun_opt_from_nlattr(const struct nlattr *a,
  				     struct sw_flow_match *match, bool is_mask,
  				     bool log)
  {
  	unsigned long opt_key_offset;
  
  	if (nla_len(a) > sizeof(match->key->tun_opts)) {
  		OVS_NLERR(log, "Geneve option length err (len %d, max %zu).",
  			  nla_len(a), sizeof(match->key->tun_opts));
  		return -EINVAL;
  	}
  
  	if (nla_len(a) % 4 != 0) {
  		OVS_NLERR(log, "Geneve opt len %d is not a multiple of 4.",
  			  nla_len(a));
  		return -EINVAL;
  	}
  
  	/* We need to record the length of the options passed
  	 * down, otherwise packets with the same format but
  	 * additional options will be silently matched.
  	 */
  	if (!is_mask) {
  		SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
  				false);
  	} else {
  		/* This is somewhat unusual because it looks at
  		 * both the key and mask while parsing the
  		 * attributes (and by extension assumes the key
  		 * is parsed first). Normally, we would verify
  		 * that each is the correct length and that the
  		 * attributes line up in the validate function.
  		 * However, that is difficult because this is
  		 * variable length and we won't have the
  		 * information later.
  		 */
  		if (match->key->tun_opts_len != nla_len(a)) {
  			OVS_NLERR(log, "Geneve option len %d != mask len %d",
  				  match->key->tun_opts_len, nla_len(a));
  			return -EINVAL;
  		}
  
  		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
  	}
d91641d9b   Thomas Graf   openvswitch: Rena...
540
  	opt_key_offset = TUN_METADATA_OFFSET(nla_len(a));
05da5898a   Jarno Rajahalme   openvswitch: Add ...
541
542
543
  	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
  				  nla_len(a), is_mask);
  	return 0;
e64457191   Pravin B Shelar   openvswitch: Rest...
544
  }
982b52700   Jesse Gross   openvswitch: Fix ...
545
  static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
1dd144cf5   Thomas Graf   openvswitch: Supp...
546
547
548
  				     struct sw_flow_match *match, bool is_mask,
  				     bool log)
  {
982b52700   Jesse Gross   openvswitch: Fix ...
549
550
  	struct nlattr *a;
  	int rem;
1dd144cf5   Thomas Graf   openvswitch: Supp...
551
  	unsigned long opt_key_offset;
614732eaa   Thomas Graf   openvswitch: Use ...
552
  	struct vxlan_metadata opts;
1dd144cf5   Thomas Graf   openvswitch: Supp...
553
554
  
  	BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
1dd144cf5   Thomas Graf   openvswitch: Supp...
555
  	memset(&opts, 0, sizeof(opts));
982b52700   Jesse Gross   openvswitch: Fix ...
556
557
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
1dd144cf5   Thomas Graf   openvswitch: Supp...
558

982b52700   Jesse Gross   openvswitch: Fix ...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  		if (type > OVS_VXLAN_EXT_MAX) {
  			OVS_NLERR(log, "VXLAN extension %d out of range max %d",
  				  type, OVS_VXLAN_EXT_MAX);
  			return -EINVAL;
  		}
  
  		if (!check_attr_len(nla_len(a),
  				    ovs_vxlan_ext_key_lens[type].len)) {
  			OVS_NLERR(log, "VXLAN extension %d has unexpected len %d expected %d",
  				  type, nla_len(a),
  				  ovs_vxlan_ext_key_lens[type].len);
  			return -EINVAL;
  		}
  
  		switch (type) {
  		case OVS_VXLAN_EXT_GBP:
  			opts.gbp = nla_get_u32(a);
  			break;
  		default:
  			OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
  				  type);
  			return -EINVAL;
  		}
  	}
  	if (rem) {
  		OVS_NLERR(log, "VXLAN extension message has %d unknown bytes.",
  			  rem);
  		return -EINVAL;
  	}
1dd144cf5   Thomas Graf   openvswitch: Supp...
588
589
590
591
592
593
594
595
596
597
598
  
  	if (!is_mask)
  		SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), false);
  	else
  		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
  
  	opt_key_offset = TUN_METADATA_OFFSET(sizeof(opts));
  	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, &opts, sizeof(opts),
  				  is_mask);
  	return 0;
  }
fc1372f89   William Tu   openvswitch: add ...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  static int erspan_tun_opt_from_nlattr(const struct nlattr *a,
  				      struct sw_flow_match *match, bool is_mask,
  				      bool log)
  {
  	unsigned long opt_key_offset;
  
  	BUILD_BUG_ON(sizeof(struct erspan_metadata) >
  		     sizeof(match->key->tun_opts));
  
  	if (nla_len(a) > sizeof(match->key->tun_opts)) {
  		OVS_NLERR(log, "ERSPAN option length err (len %d, max %zu).",
  			  nla_len(a), sizeof(match->key->tun_opts));
  		return -EINVAL;
  	}
  
  	if (!is_mask)
  		SW_FLOW_KEY_PUT(match, tun_opts_len,
  				sizeof(struct erspan_metadata), false);
  	else
  		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
  
  	opt_key_offset = TUN_METADATA_OFFSET(nla_len(a));
  	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
  				  nla_len(a), is_mask);
  	return 0;
  }
6b26ba3a7   Jiri Benc   openvswitch: netl...
625
626
627
  static int ip_tun_from_nlattr(const struct nlattr *attr,
  			      struct sw_flow_match *match, bool is_mask,
  			      bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
628
  {
99e28f18e   Pravin B Shelar   openvswitch: Fix ...
629
  	bool ttl = false, ipv4 = false, ipv6 = false;
18b6f7174   wenxu   openvswitch: Make...
630
  	bool info_bridge_mode = false;
99e28f18e   Pravin B Shelar   openvswitch: Fix ...
631
632
  	__be16 tun_flags = 0;
  	int opts_type = 0;
e64457191   Pravin B Shelar   openvswitch: Rest...
633
634
  	struct nlattr *a;
  	int rem;
e64457191   Pravin B Shelar   openvswitch: Rest...
635
636
637
  
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
05da5898a   Jarno Rajahalme   openvswitch: Add ...
638
  		int err;
e64457191   Pravin B Shelar   openvswitch: Rest...
639
  		if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
640
641
  			OVS_NLERR(log, "Tunnel attr %d out of range max %d",
  				  type, OVS_TUNNEL_KEY_ATTR_MAX);
e64457191   Pravin B Shelar   openvswitch: Rest...
642
643
  			return -EINVAL;
  		}
982b52700   Jesse Gross   openvswitch: Fix ...
644
645
  		if (!check_attr_len(nla_len(a),
  				    ovs_tunnel_key_lens[type].len)) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
646
  			OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
81bfe3c3c   Thomas Graf   openvswitch: Allo...
647
  				  type, nla_len(a), ovs_tunnel_key_lens[type].len);
e64457191   Pravin B Shelar   openvswitch: Rest...
648
649
650
651
652
653
654
655
656
657
  			return -EINVAL;
  		}
  
  		switch (type) {
  		case OVS_TUNNEL_KEY_ATTR_ID:
  			SW_FLOW_KEY_PUT(match, tun_key.tun_id,
  					nla_get_be64(a), is_mask);
  			tun_flags |= TUNNEL_KEY;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
c1ea5d672   Jiri Benc   ip_tunnels: add I...
658
  			SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src,
67b61f6c1   Jiri Benc   netlink: implemen...
659
  					nla_get_in_addr(a), is_mask);
6b26ba3a7   Jiri Benc   openvswitch: netl...
660
  			ipv4 = true;
e64457191   Pravin B Shelar   openvswitch: Rest...
661
662
  			break;
  		case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
c1ea5d672   Jiri Benc   ip_tunnels: add I...
663
  			SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst,
67b61f6c1   Jiri Benc   netlink: implemen...
664
  					nla_get_in_addr(a), is_mask);
6b26ba3a7   Jiri Benc   openvswitch: netl...
665
666
667
  			ipv4 = true;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
3d20f1f7b   Or Gerlitz   net/openvswitch: ...
668
  			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src,
6b26ba3a7   Jiri Benc   openvswitch: netl...
669
670
671
672
673
674
675
  					nla_get_in6_addr(a), is_mask);
  			ipv6 = true;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_IPV6_DST:
  			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
  					nla_get_in6_addr(a), is_mask);
  			ipv6 = true;
e64457191   Pravin B Shelar   openvswitch: Rest...
676
677
  			break;
  		case OVS_TUNNEL_KEY_ATTR_TOS:
7c383fb22   Jiri Benc   ip_tunnels: use t...
678
  			SW_FLOW_KEY_PUT(match, tun_key.tos,
e64457191   Pravin B Shelar   openvswitch: Rest...
679
680
681
  					nla_get_u8(a), is_mask);
  			break;
  		case OVS_TUNNEL_KEY_ATTR_TTL:
7c383fb22   Jiri Benc   ip_tunnels: use t...
682
  			SW_FLOW_KEY_PUT(match, tun_key.ttl,
e64457191   Pravin B Shelar   openvswitch: Rest...
683
684
685
686
687
688
689
690
691
  					nla_get_u8(a), is_mask);
  			ttl = true;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
  			tun_flags |= TUNNEL_DONT_FRAGMENT;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_CSUM:
  			tun_flags |= TUNNEL_CSUM;
  			break;
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
692
693
694
695
696
697
698
699
  		case OVS_TUNNEL_KEY_ATTR_TP_SRC:
  			SW_FLOW_KEY_PUT(match, tun_key.tp_src,
  					nla_get_be16(a), is_mask);
  			break;
  		case OVS_TUNNEL_KEY_ATTR_TP_DST:
  			SW_FLOW_KEY_PUT(match, tun_key.tp_dst,
  					nla_get_be16(a), is_mask);
  			break;
67fa03419   Jesse Gross   openvswitch: Add ...
700
701
702
  		case OVS_TUNNEL_KEY_ATTR_OAM:
  			tun_flags |= TUNNEL_OAM;
  			break;
f57966840   Jesse Gross   openvswitch: Add ...
703
  		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
1dd144cf5   Thomas Graf   openvswitch: Supp...
704
705
706
707
  			if (opts_type) {
  				OVS_NLERR(log, "Multiple metadata blocks provided");
  				return -EINVAL;
  			}
05da5898a   Jarno Rajahalme   openvswitch: Add ...
708
709
710
  			err = genev_tun_opt_from_nlattr(a, match, is_mask, log);
  			if (err)
  				return err;
f57966840   Jesse Gross   openvswitch: Add ...
711

1dd144cf5   Thomas Graf   openvswitch: Supp...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
  			tun_flags |= TUNNEL_GENEVE_OPT;
  			opts_type = type;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
  			if (opts_type) {
  				OVS_NLERR(log, "Multiple metadata blocks provided");
  				return -EINVAL;
  			}
  
  			err = vxlan_tun_opt_from_nlattr(a, match, is_mask, log);
  			if (err)
  				return err;
  
  			tun_flags |= TUNNEL_VXLAN_OPT;
  			opts_type = type;
f57966840   Jesse Gross   openvswitch: Add ...
727
  			break;
8f3dbfd79   Kris Murphy   openvswitch: Add ...
728
729
  		case OVS_TUNNEL_KEY_ATTR_PAD:
  			break;
fc1372f89   William Tu   openvswitch: add ...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
  			if (opts_type) {
  				OVS_NLERR(log, "Multiple metadata blocks provided");
  				return -EINVAL;
  			}
  
  			err = erspan_tun_opt_from_nlattr(a, match, is_mask,
  							 log);
  			if (err)
  				return err;
  
  			tun_flags |= TUNNEL_ERSPAN_OPT;
  			opts_type = type;
  			break;
18b6f7174   wenxu   openvswitch: Make...
744
745
746
747
  		case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE:
  			info_bridge_mode = true;
  			ipv4 = true;
  			break;
e64457191   Pravin B Shelar   openvswitch: Rest...
748
  		default:
6b26ba3a7   Jiri Benc   openvswitch: netl...
749
  			OVS_NLERR(log, "Unknown IP tunnel attribute %d",
f57966840   Jesse Gross   openvswitch: Add ...
750
  				  type);
e64457191   Pravin B Shelar   openvswitch: Rest...
751
752
753
754
755
  			return -EINVAL;
  		}
  	}
  
  	SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
00a93babd   Jiri Benc   openvswitch: add ...
756
757
758
  	if (is_mask)
  		SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true);
  	else
6b26ba3a7   Jiri Benc   openvswitch: netl...
759
760
  		SW_FLOW_KEY_PUT(match, tun_proto, ipv6 ? AF_INET6 : AF_INET,
  				false);
e64457191   Pravin B Shelar   openvswitch: Rest...
761
762
  
  	if (rem > 0) {
6b26ba3a7   Jiri Benc   openvswitch: netl...
763
  		OVS_NLERR(log, "IP tunnel attribute has %d unknown bytes.",
05da5898a   Jarno Rajahalme   openvswitch: Add ...
764
  			  rem);
e64457191   Pravin B Shelar   openvswitch: Rest...
765
766
  		return -EINVAL;
  	}
6b26ba3a7   Jiri Benc   openvswitch: netl...
767
768
769
770
  	if (ipv4 && ipv6) {
  		OVS_NLERR(log, "Mixed IPv4 and IPv6 tunnel attributes");
  		return -EINVAL;
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
771
  	if (!is_mask) {
6b26ba3a7   Jiri Benc   openvswitch: netl...
772
773
774
775
  		if (!ipv4 && !ipv6) {
  			OVS_NLERR(log, "IP tunnel dst address not specified");
  			return -EINVAL;
  		}
18b6f7174   wenxu   openvswitch: Make...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
  		if (ipv4) {
  			if (info_bridge_mode) {
  				if (match->key->tun_key.u.ipv4.src ||
  				    match->key->tun_key.u.ipv4.dst ||
  				    match->key->tun_key.tp_src ||
  				    match->key->tun_key.tp_dst ||
  				    match->key->tun_key.ttl ||
  				    match->key->tun_key.tos ||
  				    tun_flags & ~TUNNEL_KEY) {
  					OVS_NLERR(log, "IPv4 tun info is not correct");
  					return -EINVAL;
  				}
  			} else if (!match->key->tun_key.u.ipv4.dst) {
  				OVS_NLERR(log, "IPv4 tunnel dst address is zero");
  				return -EINVAL;
  			}
e64457191   Pravin B Shelar   openvswitch: Rest...
792
  		}
6b26ba3a7   Jiri Benc   openvswitch: netl...
793
794
795
796
  		if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) {
  			OVS_NLERR(log, "IPv6 tunnel dst address is zero");
  			return -EINVAL;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
797

18b6f7174   wenxu   openvswitch: Make...
798
  		if (!ttl && !info_bridge_mode) {
6b26ba3a7   Jiri Benc   openvswitch: netl...
799
  			OVS_NLERR(log, "IP tunnel TTL not specified.");
e64457191   Pravin B Shelar   openvswitch: Rest...
800
801
802
  			return -EINVAL;
  		}
  	}
1dd144cf5   Thomas Graf   openvswitch: Supp...
803
804
805
806
807
808
  	return opts_type;
  }
  
  static int vxlan_opt_to_nlattr(struct sk_buff *skb,
  			       const void *tun_opts, int swkey_tun_opts_len)
  {
614732eaa   Thomas Graf   openvswitch: Use ...
809
  	const struct vxlan_metadata *opts = tun_opts;
1dd144cf5   Thomas Graf   openvswitch: Supp...
810
  	struct nlattr *nla;
ae0be8de9   Michal Kubecek   netlink: make nla...
811
  	nla = nla_nest_start_noflag(skb, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
1dd144cf5   Thomas Graf   openvswitch: Supp...
812
813
814
815
816
817
818
  	if (!nla)
  		return -EMSGSIZE;
  
  	if (nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
  		return -EMSGSIZE;
  
  	nla_nest_end(skb, nla);
e64457191   Pravin B Shelar   openvswitch: Rest...
819
820
  	return 0;
  }
6b26ba3a7   Jiri Benc   openvswitch: netl...
821
822
823
  static int __ip_tun_to_nlattr(struct sk_buff *skb,
  			      const struct ip_tunnel_key *output,
  			      const void *tun_opts, int swkey_tun_opts_len,
18b6f7174   wenxu   openvswitch: Make...
824
  			      unsigned short tun_proto, u8 mode)
e64457191   Pravin B Shelar   openvswitch: Rest...
825
  {
e64457191   Pravin B Shelar   openvswitch: Rest...
826
  	if (output->tun_flags & TUNNEL_KEY &&
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
827
828
  	    nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id,
  			 OVS_TUNNEL_KEY_ATTR_PAD))
e64457191   Pravin B Shelar   openvswitch: Rest...
829
  		return -EMSGSIZE;
18b6f7174   wenxu   openvswitch: Make...
830
831
832
833
  
  	if (mode & IP_TUNNEL_INFO_BRIDGE)
  		return nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE)
  		       ? -EMSGSIZE : 0;
6b26ba3a7   Jiri Benc   openvswitch: netl...
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
  	switch (tun_proto) {
  	case AF_INET:
  		if (output->u.ipv4.src &&
  		    nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
  				    output->u.ipv4.src))
  			return -EMSGSIZE;
  		if (output->u.ipv4.dst &&
  		    nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
  				    output->u.ipv4.dst))
  			return -EMSGSIZE;
  		break;
  	case AF_INET6:
  		if (!ipv6_addr_any(&output->u.ipv6.src) &&
  		    nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,
  				     &output->u.ipv6.src))
  			return -EMSGSIZE;
  		if (!ipv6_addr_any(&output->u.ipv6.dst) &&
  		    nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_DST,
  				     &output->u.ipv6.dst))
  			return -EMSGSIZE;
  		break;
  	}
7c383fb22   Jiri Benc   ip_tunnels: use t...
856
857
  	if (output->tos &&
  	    nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos))
e64457191   Pravin B Shelar   openvswitch: Rest...
858
  		return -EMSGSIZE;
7c383fb22   Jiri Benc   ip_tunnels: use t...
859
  	if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, output->ttl))
e64457191   Pravin B Shelar   openvswitch: Rest...
860
861
  		return -EMSGSIZE;
  	if ((output->tun_flags & TUNNEL_DONT_FRAGMENT) &&
67fa03419   Jesse Gross   openvswitch: Add ...
862
  	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
e64457191   Pravin B Shelar   openvswitch: Rest...
863
864
  		return -EMSGSIZE;
  	if ((output->tun_flags & TUNNEL_CSUM) &&
67fa03419   Jesse Gross   openvswitch: Add ...
865
866
  	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
  		return -EMSGSIZE;
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
867
868
869
870
871
872
  	if (output->tp_src &&
  	    nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
  		return -EMSGSIZE;
  	if (output->tp_dst &&
  	    nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
  		return -EMSGSIZE;
67fa03419   Jesse Gross   openvswitch: Add ...
873
874
  	if ((output->tun_flags & TUNNEL_OAM) &&
  	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
e64457191   Pravin B Shelar   openvswitch: Rest...
875
  		return -EMSGSIZE;
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
876
  	if (swkey_tun_opts_len) {
1dd144cf5   Thomas Graf   openvswitch: Supp...
877
878
879
880
881
882
883
  		if (output->tun_flags & TUNNEL_GENEVE_OPT &&
  		    nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
  			    swkey_tun_opts_len, tun_opts))
  			return -EMSGSIZE;
  		else if (output->tun_flags & TUNNEL_VXLAN_OPT &&
  			 vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len))
  			return -EMSGSIZE;
fc1372f89   William Tu   openvswitch: add ...
884
885
886
887
  		else if (output->tun_flags & TUNNEL_ERSPAN_OPT &&
  			 nla_put(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
  				 swkey_tun_opts_len, tun_opts))
  			return -EMSGSIZE;
1dd144cf5   Thomas Graf   openvswitch: Supp...
888
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
889

e64457191   Pravin B Shelar   openvswitch: Rest...
890
891
  	return 0;
  }
6b26ba3a7   Jiri Benc   openvswitch: netl...
892
893
894
  static int ip_tun_to_nlattr(struct sk_buff *skb,
  			    const struct ip_tunnel_key *output,
  			    const void *tun_opts, int swkey_tun_opts_len,
18b6f7174   wenxu   openvswitch: Make...
895
  			    unsigned short tun_proto, u8 mode)
f57966840   Jesse Gross   openvswitch: Add ...
896
897
898
  {
  	struct nlattr *nla;
  	int err;
ae0be8de9   Michal Kubecek   netlink: make nla...
899
  	nla = nla_nest_start_noflag(skb, OVS_KEY_ATTR_TUNNEL);
f57966840   Jesse Gross   openvswitch: Add ...
900
901
  	if (!nla)
  		return -EMSGSIZE;
6b26ba3a7   Jiri Benc   openvswitch: netl...
902
  	err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len,
18b6f7174   wenxu   openvswitch: Make...
903
  				 tun_proto, mode);
f57966840   Jesse Gross   openvswitch: Add ...
904
905
906
907
908
909
  	if (err)
  		return err;
  
  	nla_nest_end(skb, nla);
  	return 0;
  }
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
910
911
  int ovs_nla_put_tunnel_info(struct sk_buff *skb,
  			    struct ip_tunnel_info *tun_info)
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
912
  {
ba3e2084f   David S. Miller   Merge git://git.k...
913
914
915
  	return __ip_tun_to_nlattr(skb, &tun_info->key,
  				  ip_tunnel_info_opts(tun_info),
  				  tun_info->options_len,
18b6f7174   wenxu   openvswitch: Make...
916
  				  ip_tunnel_info_af(tun_info), tun_info->mode);
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
917
  }
018c1dda5   Eric Garver   openvswitch: 802....
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
  static int encode_vlan_from_nlattrs(struct sw_flow_match *match,
  				    const struct nlattr *a[],
  				    bool is_mask, bool inner)
  {
  	__be16 tci = 0;
  	__be16 tpid = 0;
  
  	if (a[OVS_KEY_ATTR_VLAN])
  		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
  
  	if (a[OVS_KEY_ATTR_ETHERTYPE])
  		tpid = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
  
  	if (likely(!inner)) {
  		SW_FLOW_KEY_PUT(match, eth.vlan.tpid, tpid, is_mask);
  		SW_FLOW_KEY_PUT(match, eth.vlan.tci, tci, is_mask);
  	} else {
  		SW_FLOW_KEY_PUT(match, eth.cvlan.tpid, tpid, is_mask);
  		SW_FLOW_KEY_PUT(match, eth.cvlan.tci, tci, is_mask);
  	}
  	return 0;
  }
  
  static int validate_vlan_from_nlattrs(const struct sw_flow_match *match,
  				      u64 key_attrs, bool inner,
  				      const struct nlattr **a, bool log)
  {
  	__be16 tci = 0;
  
  	if (!((key_attrs & (1 << OVS_KEY_ATTR_ETHERNET)) &&
  	      (key_attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) &&
  	       eth_type_vlan(nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE])))) {
  		/* Not a VLAN. */
  		return 0;
  	}
  
  	if (!((key_attrs & (1 << OVS_KEY_ATTR_VLAN)) &&
  	      (key_attrs & (1 << OVS_KEY_ATTR_ENCAP)))) {
  		OVS_NLERR(log, "Invalid %s frame", (inner) ? "C-VLAN" : "VLAN");
  		return -EINVAL;
  	}
  
  	if (a[OVS_KEY_ATTR_VLAN])
  		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
962
  	if (!(tci & htons(VLAN_CFI_MASK))) {
018c1dda5   Eric Garver   openvswitch: 802....
963
  		if (tci) {
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
964
  			OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit set.",
018c1dda5   Eric Garver   openvswitch: 802....
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
  				  (inner) ? "C-VLAN" : "VLAN");
  			return -EINVAL;
  		} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
  			/* Corner case for truncated VLAN header. */
  			OVS_NLERR(log, "Truncated %s header has non-zero encap attribute.",
  				  (inner) ? "C-VLAN" : "VLAN");
  			return -EINVAL;
  		}
  	}
  
  	return 1;
  }
  
  static int validate_vlan_mask_from_nlattrs(const struct sw_flow_match *match,
  					   u64 key_attrs, bool inner,
  					   const struct nlattr **a, bool log)
  {
  	__be16 tci = 0;
  	__be16 tpid = 0;
  	bool encap_valid = !!(match->key->eth.vlan.tci &
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
985
  			      htons(VLAN_CFI_MASK));
018c1dda5   Eric Garver   openvswitch: 802....
986
  	bool i_encap_valid = !!(match->key->eth.cvlan.tci &
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
987
  				htons(VLAN_CFI_MASK));
018c1dda5   Eric Garver   openvswitch: 802....
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
  
  	if (!(key_attrs & (1 << OVS_KEY_ATTR_ENCAP))) {
  		/* Not a VLAN. */
  		return 0;
  	}
  
  	if ((!inner && !encap_valid) || (inner && !i_encap_valid)) {
  		OVS_NLERR(log, "Encap mask attribute is set for non-%s frame.",
  			  (inner) ? "C-VLAN" : "VLAN");
  		return -EINVAL;
  	}
  
  	if (a[OVS_KEY_ATTR_VLAN])
  		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
  
  	if (a[OVS_KEY_ATTR_ETHERTYPE])
  		tpid = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
  
  	if (tpid != htons(0xffff)) {
  		OVS_NLERR(log, "Must have an exact match on %s TPID (mask=%x).",
  			  (inner) ? "C-VLAN" : "VLAN", ntohs(tpid));
  		return -EINVAL;
  	}
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
1011
1012
  	if (!(tci & htons(VLAN_CFI_MASK))) {
  		OVS_NLERR(log, "%s TCI mask does not have exact match for VLAN_CFI_MASK bit.",
018c1dda5   Eric Garver   openvswitch: 802....
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
  			  (inner) ? "C-VLAN" : "VLAN");
  		return -EINVAL;
  	}
  
  	return 1;
  }
  
  static int __parse_vlan_from_nlattrs(struct sw_flow_match *match,
  				     u64 *key_attrs, bool inner,
  				     const struct nlattr **a, bool is_mask,
  				     bool log)
  {
  	int err;
  	const struct nlattr *encap;
  
  	if (!is_mask)
  		err = validate_vlan_from_nlattrs(match, *key_attrs, inner,
  						 a, log);
  	else
  		err = validate_vlan_mask_from_nlattrs(match, *key_attrs, inner,
  						      a, log);
  	if (err <= 0)
  		return err;
  
  	err = encode_vlan_from_nlattrs(match, a, is_mask, inner);
  	if (err)
  		return err;
  
  	*key_attrs &= ~(1 << OVS_KEY_ATTR_ENCAP);
  	*key_attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
  	*key_attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
  
  	encap = a[OVS_KEY_ATTR_ENCAP];
  
  	if (!is_mask)
  		err = parse_flow_nlattrs(encap, a, key_attrs, log);
  	else
  		err = parse_flow_mask_nlattrs(encap, a, key_attrs, log);
  
  	return err;
  }
  
  static int parse_vlan_from_nlattrs(struct sw_flow_match *match,
  				   u64 *key_attrs, const struct nlattr **a,
  				   bool is_mask, bool log)
  {
  	int err;
  	bool encap_valid = false;
  
  	err = __parse_vlan_from_nlattrs(match, key_attrs, false, a,
  					is_mask, log);
  	if (err)
  		return err;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
1066
  	encap_valid = !!(match->key->eth.vlan.tci & htons(VLAN_CFI_MASK));
018c1dda5   Eric Garver   openvswitch: 802....
1067
1068
1069
1070
1071
1072
1073
1074
1075
  	if (encap_valid) {
  		err = __parse_vlan_from_nlattrs(match, key_attrs, true, a,
  						is_mask, log);
  		if (err)
  			return err;
  	}
  
  	return 0;
  }
0a6410fbd   Jiri Benc   openvswitch: netl...
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
  static int parse_eth_type_from_nlattrs(struct sw_flow_match *match,
  				       u64 *attrs, const struct nlattr **a,
  				       bool is_mask, bool log)
  {
  	__be16 eth_type;
  
  	eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
  	if (is_mask) {
  		/* Always exact match EtherType. */
  		eth_type = htons(0xffff);
  	} else if (!eth_proto_is_802_3(eth_type)) {
  		OVS_NLERR(log, "EtherType %x is less than min %x",
  				ntohs(eth_type), ETH_P_802_3_MIN);
  		return -EINVAL;
  	}
  
  	SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
  	*attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
  	return 0;
  }
c2ac66735   Joe Stringer   openvswitch: Allo...
1096
1097
1098
  static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
  				 u64 *attrs, const struct nlattr **a,
  				 bool is_mask, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
1099
  {
0a6410fbd   Jiri Benc   openvswitch: netl...
1100
  	u8 mac_proto = MAC_PROTO_ETHERNET;
971427f35   Andy Zhou   openvswitch: Add ...
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  	if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
  		u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
  
  		SW_FLOW_KEY_PUT(match, ovs_flow_hash, hash_val, is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_DP_HASH);
  	}
  
  	if (*attrs & (1 << OVS_KEY_ATTR_RECIRC_ID)) {
  		u32 recirc_id = nla_get_u32(a[OVS_KEY_ATTR_RECIRC_ID]);
  
  		SW_FLOW_KEY_PUT(match, recirc_id, recirc_id, is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_RECIRC_ID);
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
1114
1115
1116
1117
1118
1119
1120
1121
  	if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
  		SW_FLOW_KEY_PUT(match, phy.priority,
  			  nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_PRIORITY);
  	}
  
  	if (*attrs & (1 << OVS_KEY_ATTR_IN_PORT)) {
  		u32 in_port = nla_get_u32(a[OVS_KEY_ATTR_IN_PORT]);
426cda5cc   Jesse Gross   openvswitch: Addi...
1122
  		if (is_mask) {
e64457191   Pravin B Shelar   openvswitch: Rest...
1123
  			in_port = 0xffffffff; /* Always exact match in_port. */
426cda5cc   Jesse Gross   openvswitch: Addi...
1124
  		} else if (in_port >= DP_MAX_PORTS) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1125
  			OVS_NLERR(log, "Port %d exceeds max allowable %d",
426cda5cc   Jesse Gross   openvswitch: Addi...
1126
  				  in_port, DP_MAX_PORTS);
e64457191   Pravin B Shelar   openvswitch: Rest...
1127
  			return -EINVAL;
426cda5cc   Jesse Gross   openvswitch: Addi...
1128
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
  
  		SW_FLOW_KEY_PUT(match, phy.in_port, in_port, is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_IN_PORT);
  	} else if (!is_mask) {
  		SW_FLOW_KEY_PUT(match, phy.in_port, DP_MAX_PORTS, is_mask);
  	}
  
  	if (*attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
  		uint32_t mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
  
  		SW_FLOW_KEY_PUT(match, phy.skb_mark, mark, is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
  	}
  	if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
6b26ba3a7   Jiri Benc   openvswitch: netl...
1143
1144
  		if (ip_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
  				       is_mask, log) < 0)
e64457191   Pravin B Shelar   openvswitch: Rest...
1145
1146
1147
  			return -EINVAL;
  		*attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
  	}
7f8a436ea   Joe Stringer   openvswitch: Add ...
1148
1149
  
  	if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
c2ac66735   Joe Stringer   openvswitch: Allo...
1150
  	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
fbccce596   Joe Stringer   openvswitch: Exte...
1151
  		u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
7f8a436ea   Joe Stringer   openvswitch: Add ...
1152

9e384715e   Joe Stringer   openvswitch: Reje...
1153
  		if (ct_state & ~CT_SUPPORTED_MASK) {
fbccce596   Joe Stringer   openvswitch: Exte...
1154
  			OVS_NLERR(log, "ct_state flags %08x unsupported",
6f2259524   Joe Stringer   openvswitch: Reje...
1155
1156
1157
  				  ct_state);
  			return -EINVAL;
  		}
7f8a436ea   Joe Stringer   openvswitch: Add ...
1158

316d4d78c   Jarno Rajahalme   openvswitch: Pack...
1159
  		SW_FLOW_KEY_PUT(match, ct_state, ct_state, is_mask);
7f8a436ea   Joe Stringer   openvswitch: Add ...
1160
1161
1162
  		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
  	}
  	if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) &&
c2ac66735   Joe Stringer   openvswitch: Allo...
1163
  	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_ZONE)) {
7f8a436ea   Joe Stringer   openvswitch: Add ...
1164
  		u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]);
316d4d78c   Jarno Rajahalme   openvswitch: Pack...
1165
  		SW_FLOW_KEY_PUT(match, ct_zone, ct_zone, is_mask);
7f8a436ea   Joe Stringer   openvswitch: Add ...
1166
1167
  		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE);
  	}
182e3042e   Joe Stringer   openvswitch: Allo...
1168
  	if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) &&
c2ac66735   Joe Stringer   openvswitch: Allo...
1169
  	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_MARK)) {
182e3042e   Joe Stringer   openvswitch: Allo...
1170
1171
1172
1173
1174
  		u32 mark = nla_get_u32(a[OVS_KEY_ATTR_CT_MARK]);
  
  		SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
  		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
  	}
33db4125e   Joe Stringer   openvswitch: Rena...
1175
1176
1177
  	if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
  	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
  		const struct ovs_key_ct_labels *cl;
c2ac66735   Joe Stringer   openvswitch: Allo...
1178

33db4125e   Joe Stringer   openvswitch: Rena...
1179
1180
  		cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
  		SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
c2ac66735   Joe Stringer   openvswitch: Allo...
1181
  				   sizeof(*cl), is_mask);
33db4125e   Joe Stringer   openvswitch: Rena...
1182
  		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
c2ac66735   Joe Stringer   openvswitch: Allo...
1183
  	}
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1184
1185
1186
1187
1188
1189
1190
1191
1192
  	if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)) {
  		const struct ovs_key_ct_tuple_ipv4 *ct;
  
  		ct = nla_data(a[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]);
  
  		SW_FLOW_KEY_PUT(match, ipv4.ct_orig.src, ct->ipv4_src, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.ct_orig.dst, ct->ipv4_dst, is_mask);
  		SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
  		SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
316d4d78c   Jarno Rajahalme   openvswitch: Pack...
1193
  		SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv4_proto, is_mask);
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
  		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4);
  	}
  	if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)) {
  		const struct ovs_key_ct_tuple_ipv6 *ct;
  
  		ct = nla_data(a[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);
  
  		SW_FLOW_KEY_MEMCPY(match, ipv6.ct_orig.src, &ct->ipv6_src,
  				   sizeof(match->key->ipv6.ct_orig.src),
  				   is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.ct_orig.dst, &ct->ipv6_dst,
  				   sizeof(match->key->ipv6.ct_orig.dst),
  				   is_mask);
  		SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
  		SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
316d4d78c   Jarno Rajahalme   openvswitch: Pack...
1209
  		SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv6_proto, is_mask);
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1210
1211
  		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
  	}
329f45bc4   Jiri Benc   openvswitch: add ...
1212

0a6410fbd   Jiri Benc   openvswitch: netl...
1213
1214
1215
1216
1217
1218
  	/* For layer 3 packets the Ethernet type is provided
  	 * and treated as metadata but no MAC addresses are provided.
  	 */
  	if (!(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) &&
  	    (*attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE)))
  		mac_proto = MAC_PROTO_NONE;
329f45bc4   Jiri Benc   openvswitch: add ...
1219
  	/* Always exact match mac_proto */
0a6410fbd   Jiri Benc   openvswitch: netl...
1220
1221
1222
1223
1224
  	SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : mac_proto, is_mask);
  
  	if (mac_proto == MAC_PROTO_NONE)
  		return parse_eth_type_from_nlattrs(match, attrs, a, is_mask,
  						   log);
329f45bc4   Jiri Benc   openvswitch: add ...
1225

e64457191   Pravin B Shelar   openvswitch: Rest...
1226
1227
  	return 0;
  }
b2d0f5d5d   Yi Yang   openvswitch: enab...
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
  int nsh_hdr_from_nlattr(const struct nlattr *attr,
  			struct nshhdr *nh, size_t size)
  {
  	struct nlattr *a;
  	int rem;
  	u8 flags = 0;
  	u8 ttl = 0;
  	int mdlen = 0;
  
  	/* validate_nsh has check this, so we needn't do duplicate check here
  	 */
  	if (size < NSH_BASE_HDR_LEN)
  		return -ENOBUFS;
  
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
  
  		switch (type) {
  		case OVS_NSH_KEY_ATTR_BASE: {
  			const struct ovs_nsh_key_base *base = nla_data(a);
  
  			flags = base->flags;
  			ttl = base->ttl;
  			nh->np = base->np;
  			nh->mdtype = base->mdtype;
  			nh->path_hdr = base->path_hdr;
  			break;
  		}
  		case OVS_NSH_KEY_ATTR_MD1:
  			mdlen = nla_len(a);
  			if (mdlen > size - NSH_BASE_HDR_LEN)
  				return -ENOBUFS;
  			memcpy(&nh->md1, nla_data(a), mdlen);
  			break;
  
  		case OVS_NSH_KEY_ATTR_MD2:
  			mdlen = nla_len(a);
  			if (mdlen > size - NSH_BASE_HDR_LEN)
  				return -ENOBUFS;
  			memcpy(&nh->md2, nla_data(a), mdlen);
  			break;
  
  		default:
  			return -EINVAL;
  		}
  	}
  
  	/* nsh header length  = NSH_BASE_HDR_LEN + mdlen */
  	nh->ver_flags_ttl_len = 0;
  	nsh_set_flags_ttl_len(nh, flags, ttl, NSH_BASE_HDR_LEN + mdlen);
  
  	return 0;
  }
  
  int nsh_key_from_nlattr(const struct nlattr *attr,
  			struct ovs_key_nsh *nsh, struct ovs_key_nsh *nsh_mask)
  {
  	struct nlattr *a;
  	int rem;
  
  	/* validate_nsh has check this, so we needn't do duplicate check here
  	 */
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
  
  		switch (type) {
  		case OVS_NSH_KEY_ATTR_BASE: {
  			const struct ovs_nsh_key_base *base = nla_data(a);
  			const struct ovs_nsh_key_base *base_mask = base + 1;
  
  			nsh->base = *base;
  			nsh_mask->base = *base_mask;
  			break;
  		}
  		case OVS_NSH_KEY_ATTR_MD1: {
  			const struct ovs_nsh_key_md1 *md1 = nla_data(a);
  			const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
  
  			memcpy(nsh->context, md1->context, sizeof(*md1));
  			memcpy(nsh_mask->context, md1_mask->context,
  			       sizeof(*md1_mask));
  			break;
  		}
  		case OVS_NSH_KEY_ATTR_MD2:
  			/* Not supported yet */
  			return -ENOTSUPP;
  		default:
  			return -EINVAL;
  		}
  	}
  
  	return 0;
  }
  
  static int nsh_key_put_from_nlattr(const struct nlattr *attr,
  				   struct sw_flow_match *match, bool is_mask,
  				   bool is_push_nsh, bool log)
  {
  	struct nlattr *a;
  	int rem;
  	bool has_base = false;
  	bool has_md1 = false;
  	bool has_md2 = false;
  	u8 mdtype = 0;
  	int mdlen = 0;
  
  	if (WARN_ON(is_push_nsh && is_mask))
  		return -EINVAL;
  
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
  		int i;
  
  		if (type > OVS_NSH_KEY_ATTR_MAX) {
  			OVS_NLERR(log, "nsh attr %d is out of range max %d",
  				  type, OVS_NSH_KEY_ATTR_MAX);
  			return -EINVAL;
  		}
  
  		if (!check_attr_len(nla_len(a),
  				    ovs_nsh_key_attr_lens[type].len)) {
  			OVS_NLERR(
  			    log,
  			    "nsh attr %d has unexpected len %d expected %d",
  			    type,
  			    nla_len(a),
  			    ovs_nsh_key_attr_lens[type].len
  			);
  			return -EINVAL;
  		}
  
  		switch (type) {
  		case OVS_NSH_KEY_ATTR_BASE: {
  			const struct ovs_nsh_key_base *base = nla_data(a);
  
  			has_base = true;
  			mdtype = base->mdtype;
  			SW_FLOW_KEY_PUT(match, nsh.base.flags,
  					base->flags, is_mask);
  			SW_FLOW_KEY_PUT(match, nsh.base.ttl,
  					base->ttl, is_mask);
  			SW_FLOW_KEY_PUT(match, nsh.base.mdtype,
  					base->mdtype, is_mask);
  			SW_FLOW_KEY_PUT(match, nsh.base.np,
  					base->np, is_mask);
  			SW_FLOW_KEY_PUT(match, nsh.base.path_hdr,
  					base->path_hdr, is_mask);
  			break;
  		}
  		case OVS_NSH_KEY_ATTR_MD1: {
  			const struct ovs_nsh_key_md1 *md1 = nla_data(a);
  
  			has_md1 = true;
  			for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)
  				SW_FLOW_KEY_PUT(match, nsh.context[i],
  						md1->context[i], is_mask);
  			break;
  		}
  		case OVS_NSH_KEY_ATTR_MD2:
  			if (!is_push_nsh) /* Not supported MD type 2 yet */
  				return -ENOTSUPP;
  
  			has_md2 = true;
  			mdlen = nla_len(a);
  			if (mdlen > NSH_CTX_HDRS_MAX_LEN || mdlen <= 0) {
  				OVS_NLERR(
  				    log,
  				    "Invalid MD length %d for MD type %d",
  				    mdlen,
  				    mdtype
  				);
  				return -EINVAL;
  			}
  			break;
  		default:
  			OVS_NLERR(log, "Unknown nsh attribute %d",
  				  type);
  			return -EINVAL;
  		}
  	}
  
  	if (rem > 0) {
  		OVS_NLERR(log, "nsh attribute has %d unknown bytes.", rem);
  		return -EINVAL;
  	}
  
  	if (has_md1 && has_md2) {
  		OVS_NLERR(
  		    1,
  		    "invalid nsh attribute: md1 and md2 are exclusive."
  		);
  		return -EINVAL;
  	}
  
  	if (!is_mask) {
  		if ((has_md1 && mdtype != NSH_M_TYPE1) ||
  		    (has_md2 && mdtype != NSH_M_TYPE2)) {
  			OVS_NLERR(1, "nsh attribute has unmatched MD type %d.",
  				  mdtype);
  			return -EINVAL;
  		}
  
  		if (is_push_nsh &&
  		    (!has_base || (!has_md1 && !has_md2))) {
  			OVS_NLERR(
  			    1,
  			    "push_nsh: missing base or metadata attributes"
  			);
  			return -EINVAL;
  		}
  	}
  
  	return 0;
  }
c2ac66735   Joe Stringer   openvswitch: Allo...
1442
1443
1444
  static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
  				u64 attrs, const struct nlattr **a,
  				bool is_mask, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
1445
1446
  {
  	int err;
e64457191   Pravin B Shelar   openvswitch: Rest...
1447

c2ac66735   Joe Stringer   openvswitch: Allo...
1448
  	err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
  	if (err)
  		return err;
  
  	if (attrs & (1 << OVS_KEY_ATTR_ETHERNET)) {
  		const struct ovs_key_ethernet *eth_key;
  
  		eth_key = nla_data(a[OVS_KEY_ATTR_ETHERNET]);
  		SW_FLOW_KEY_MEMCPY(match, eth.src,
  				eth_key->eth_src, ETH_ALEN, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, eth.dst,
  				eth_key->eth_dst, ETH_ALEN, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
e64457191   Pravin B Shelar   openvswitch: Rest...
1461

0a6410fbd   Jiri Benc   openvswitch: netl...
1462
1463
1464
1465
1466
  		if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
  			/* VLAN attribute is always parsed before getting here since it
  			 * may occur multiple times.
  			 */
  			OVS_NLERR(log, "VLAN attribute unexpected.");
e64457191   Pravin B Shelar   openvswitch: Rest...
1467
1468
  			return -EINVAL;
  		}
0a6410fbd   Jiri Benc   openvswitch: netl...
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
  		if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
  			err = parse_eth_type_from_nlattrs(match, &attrs, a, is_mask,
  							  log);
  			if (err)
  				return err;
  		} else if (!is_mask) {
  			SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
  		}
  	} else if (!match->key->eth.type) {
  		OVS_NLERR(log, "Either Ethernet header or EtherType is required.");
  		return -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
1480
1481
1482
1483
1484
1485
1486
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
  		const struct ovs_key_ipv4 *ipv4_key;
  
  		ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
  		if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1487
1488
  			OVS_NLERR(log, "IPv4 frag type %d is out of range max %d",
  				  ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
e64457191   Pravin B Shelar   openvswitch: Rest...
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
  			return -EINVAL;
  		}
  		SW_FLOW_KEY_PUT(match, ip.proto,
  				ipv4_key->ipv4_proto, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.tos,
  				ipv4_key->ipv4_tos, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.ttl,
  				ipv4_key->ipv4_ttl, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.frag,
  				ipv4_key->ipv4_frag, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
  				ipv4_key->ipv4_src, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
  				ipv4_key->ipv4_dst, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
  		const struct ovs_key_ipv6 *ipv6_key;
  
  		ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
  		if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1511
1512
  			OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
  				  ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
e64457191   Pravin B Shelar   openvswitch: Rest...
1513
1514
  			return -EINVAL;
  		}
fecaef85f   Jarno Rajahalme   openvswitch: Vali...
1515

d3052bb5d   Joe Stringer   openvswitch: Don'...
1516
  		if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
0ed80da51   Joe Perches   openvswitch: Remo...
1517
  			OVS_NLERR(log, "IPv6 flow label %x is out of range (max=%x)",
fecaef85f   Jarno Rajahalme   openvswitch: Vali...
1518
1519
1520
  				  ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
  			return -EINVAL;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
  		SW_FLOW_KEY_PUT(match, ipv6.label,
  				ipv6_key->ipv6_label, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.proto,
  				ipv6_key->ipv6_proto, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.tos,
  				ipv6_key->ipv6_tclass, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.ttl,
  				ipv6_key->ipv6_hlimit, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.frag,
  				ipv6_key->ipv6_frag, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.src,
  				ipv6_key->ipv6_src,
  				sizeof(match->key->ipv6.addr.src),
  				is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.dst,
  				ipv6_key->ipv6_dst,
  				sizeof(match->key->ipv6.addr.dst),
  				is_mask);
  
  		attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
  		const struct ovs_key_arp *arp_key;
  
  		arp_key = nla_data(a[OVS_KEY_ATTR_ARP]);
  		if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1548
  			OVS_NLERR(log, "Unknown ARP opcode (opcode=%d).",
e64457191   Pravin B Shelar   openvswitch: Rest...
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
  				  arp_key->arp_op);
  			return -EINVAL;
  		}
  
  		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
  				arp_key->arp_sip, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
  			arp_key->arp_tip, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.proto,
  				ntohs(arp_key->arp_op), is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.sha,
  				arp_key->arp_sha, ETH_ALEN, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.tha,
  				arp_key->arp_tha, ETH_ALEN, is_mask);
  
  		attrs &= ~(1 << OVS_KEY_ATTR_ARP);
  	}
b2d0f5d5d   Yi Yang   openvswitch: enab...
1566
1567
1568
1569
1570
1571
  	if (attrs & (1 << OVS_KEY_ATTR_NSH)) {
  		if (nsh_key_put_from_nlattr(a[OVS_KEY_ATTR_NSH], match,
  					    is_mask, false, log) < 0)
  			return -EINVAL;
  		attrs &= ~(1 << OVS_KEY_ATTR_NSH);
  	}
25cd9ba0a   Simon Horman   openvswitch: Add ...
1572
1573
  	if (attrs & (1 << OVS_KEY_ATTR_MPLS)) {
  		const struct ovs_key_mpls *mpls_key;
fbdcdd78d   Martin Varghese   Change in Openvsw...
1574
1575
  		u32 hdr_len;
  		u32 label_count, label_count_mask, i;
25cd9ba0a   Simon Horman   openvswitch: Add ...
1576
1577
  
  		mpls_key = nla_data(a[OVS_KEY_ATTR_MPLS]);
fbdcdd78d   Martin Varghese   Change in Openvsw...
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
  		hdr_len = nla_len(a[OVS_KEY_ATTR_MPLS]);
  		label_count = hdr_len / sizeof(struct ovs_key_mpls);
  
  		if (label_count == 0 || label_count > MPLS_LABEL_DEPTH ||
  		    hdr_len % sizeof(struct ovs_key_mpls))
  			return -EINVAL;
  
  		label_count_mask =  GENMASK(label_count - 1, 0);
  
  		for (i = 0 ; i < label_count; i++)
  			SW_FLOW_KEY_PUT(match, mpls.lse[i],
  					mpls_key[i].mpls_lse, is_mask);
  
  		SW_FLOW_KEY_PUT(match, mpls.num_labels_mask,
  				label_count_mask, is_mask);
25cd9ba0a   Simon Horman   openvswitch: Add ...
1593
1594
1595
  
  		attrs &= ~(1 << OVS_KEY_ATTR_MPLS);
  	 }
e64457191   Pravin B Shelar   openvswitch: Rest...
1596
1597
1598
1599
  	if (attrs & (1 << OVS_KEY_ATTR_TCP)) {
  		const struct ovs_key_tcp *tcp_key;
  
  		tcp_key = nla_data(a[OVS_KEY_ATTR_TCP]);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1600
1601
  		SW_FLOW_KEY_PUT(match, tp.src, tcp_key->tcp_src, is_mask);
  		SW_FLOW_KEY_PUT(match, tp.dst, tcp_key->tcp_dst, is_mask);
e64457191   Pravin B Shelar   openvswitch: Rest...
1602
1603
  		attrs &= ~(1 << OVS_KEY_ATTR_TCP);
  	}
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
1604
  	if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
1b760fb9a   Joe Stringer   openvswitch: Remo...
1605
1606
1607
  		SW_FLOW_KEY_PUT(match, tp.flags,
  				nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
  				is_mask);
5eb26b156   Jarno Rajahalme   openvswitch: TCP ...
1608
1609
  		attrs &= ~(1 << OVS_KEY_ATTR_TCP_FLAGS);
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
1610
1611
1612
1613
  	if (attrs & (1 << OVS_KEY_ATTR_UDP)) {
  		const struct ovs_key_udp *udp_key;
  
  		udp_key = nla_data(a[OVS_KEY_ATTR_UDP]);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1614
1615
  		SW_FLOW_KEY_PUT(match, tp.src, udp_key->udp_src, is_mask);
  		SW_FLOW_KEY_PUT(match, tp.dst, udp_key->udp_dst, is_mask);
e64457191   Pravin B Shelar   openvswitch: Rest...
1616
1617
1618
1619
1620
1621
1622
  		attrs &= ~(1 << OVS_KEY_ATTR_UDP);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
  		const struct ovs_key_sctp *sctp_key;
  
  		sctp_key = nla_data(a[OVS_KEY_ATTR_SCTP]);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1623
1624
  		SW_FLOW_KEY_PUT(match, tp.src, sctp_key->sctp_src, is_mask);
  		SW_FLOW_KEY_PUT(match, tp.dst, sctp_key->sctp_dst, is_mask);
e64457191   Pravin B Shelar   openvswitch: Rest...
1625
1626
1627
1628
1629
1630
1631
  		attrs &= ~(1 << OVS_KEY_ATTR_SCTP);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ICMP)) {
  		const struct ovs_key_icmp *icmp_key;
  
  		icmp_key = nla_data(a[OVS_KEY_ATTR_ICMP]);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1632
  		SW_FLOW_KEY_PUT(match, tp.src,
e64457191   Pravin B Shelar   openvswitch: Rest...
1633
  				htons(icmp_key->icmp_type), is_mask);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1634
  		SW_FLOW_KEY_PUT(match, tp.dst,
e64457191   Pravin B Shelar   openvswitch: Rest...
1635
1636
1637
1638
1639
1640
1641
1642
  				htons(icmp_key->icmp_code), is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ICMP);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ICMPV6)) {
  		const struct ovs_key_icmpv6 *icmpv6_key;
  
  		icmpv6_key = nla_data(a[OVS_KEY_ATTR_ICMPV6]);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1643
  		SW_FLOW_KEY_PUT(match, tp.src,
e64457191   Pravin B Shelar   openvswitch: Rest...
1644
  				htons(icmpv6_key->icmpv6_type), is_mask);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
1645
  		SW_FLOW_KEY_PUT(match, tp.dst,
e64457191   Pravin B Shelar   openvswitch: Rest...
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
  				htons(icmpv6_key->icmpv6_code), is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ICMPV6);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ND)) {
  		const struct ovs_key_nd *nd_key;
  
  		nd_key = nla_data(a[OVS_KEY_ATTR_ND]);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.target,
  			nd_key->nd_target,
  			sizeof(match->key->ipv6.nd.target),
  			is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.sll,
  			nd_key->nd_sll, ETH_ALEN, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.tll,
  				nd_key->nd_tll, ETH_ALEN, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ND);
  	}
426cda5cc   Jesse Gross   openvswitch: Addi...
1664
  	if (attrs != 0) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1665
  		OVS_NLERR(log, "Unknown key attributes %llx",
426cda5cc   Jesse Gross   openvswitch: Addi...
1666
  			  (unsigned long long)attrs);
e64457191   Pravin B Shelar   openvswitch: Rest...
1667
  		return -EINVAL;
426cda5cc   Jesse Gross   openvswitch: Addi...
1668
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
1669
1670
1671
  
  	return 0;
  }
81bfe3c3c   Thomas Graf   openvswitch: Allo...
1672
1673
  static void nlattr_set(struct nlattr *attr, u8 val,
  		       const struct ovs_len_tbl *tbl)
e64457191   Pravin B Shelar   openvswitch: Rest...
1674
  {
f47de068f   Pravin B Shelar   openvswitch: Crea...
1675
1676
  	struct nlattr *nla;
  	int rem;
e64457191   Pravin B Shelar   openvswitch: Rest...
1677

f47de068f   Pravin B Shelar   openvswitch: Crea...
1678
1679
  	/* The nlattr stream should already have been validated */
  	nla_for_each_nested(nla, attr, rem) {
72f17baf2   Stefano Brivio   openvswitch: Don'...
1680
1681
1682
  		if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
  			nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl);
  		else
f47de068f   Pravin B Shelar   openvswitch: Crea...
1683
  			memset(nla_data(nla), val, nla_len(nla));
9e384715e   Joe Stringer   openvswitch: Reje...
1684
1685
1686
  
  		if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
  			*(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
f47de068f   Pravin B Shelar   openvswitch: Crea...
1687
1688
1689
1690
1691
  	}
  }
  
  static void mask_set_nlattr(struct nlattr *attr, u8 val)
  {
81bfe3c3c   Thomas Graf   openvswitch: Allo...
1692
  	nlattr_set(attr, val, ovs_key_lens);
e64457191   Pravin B Shelar   openvswitch: Rest...
1693
1694
1695
1696
1697
1698
1699
  }
  
  /**
   * ovs_nla_get_match - parses Netlink attributes into a flow key and
   * mask. In case the 'mask' is NULL, the flow is treated as exact match
   * flow. Otherwise, it is treated as a wildcarded flow, except the mask
   * does not include any don't care bit.
c2ac66735   Joe Stringer   openvswitch: Allo...
1700
   * @net: Used to determine per-namespace field support.
e64457191   Pravin B Shelar   openvswitch: Rest...
1701
   * @match: receives the extracted flow match information.
966785142   Andrew Lunn   net: openvswitch:...
1702
   * @nla_key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
e64457191   Pravin B Shelar   openvswitch: Rest...
1703
1704
   * sequence. The fields should of the packet that triggered the creation
   * of this flow.
966785142   Andrew Lunn   net: openvswitch:...
1705
1706
   * @nla_mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_*
   * Netlink attribute specifies the mask field of the wildcarded flow.
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1707
1708
1709
   * @log: Boolean to allow kernel error logging.  Normally true, but when
   * probing for feature compatibility this should be passed in as false to
   * suppress unnecessary error logging.
e64457191   Pravin B Shelar   openvswitch: Rest...
1710
   */
c2ac66735   Joe Stringer   openvswitch: Allo...
1711
  int ovs_nla_get_match(struct net *net, struct sw_flow_match *match,
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1712
  		      const struct nlattr *nla_key,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1713
1714
  		      const struct nlattr *nla_mask,
  		      bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
1715
1716
  {
  	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
f47de068f   Pravin B Shelar   openvswitch: Crea...
1717
  	struct nlattr *newmask = NULL;
e64457191   Pravin B Shelar   openvswitch: Rest...
1718
1719
  	u64 key_attrs = 0;
  	u64 mask_attrs = 0;
e64457191   Pravin B Shelar   openvswitch: Rest...
1720
  	int err;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1721
  	err = parse_flow_nlattrs(nla_key, a, &key_attrs, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
1722
1723
  	if (err)
  		return err;
018c1dda5   Eric Garver   openvswitch: 802....
1724
1725
1726
  	err = parse_vlan_from_nlattrs(match, &key_attrs, a, false, log);
  	if (err)
  		return err;
e64457191   Pravin B Shelar   openvswitch: Rest...
1727

c2ac66735   Joe Stringer   openvswitch: Allo...
1728
  	err = ovs_key_from_nlattrs(net, match, key_attrs, a, false, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
1729
1730
  	if (err)
  		return err;
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
  	if (match->mask) {
  		if (!nla_mask) {
  			/* Create an exact match mask. We need to set to 0xff
  			 * all the 'match->mask' fields that have been touched
  			 * in 'match->key'. We cannot simply memset
  			 * 'match->mask', because padding bytes and fields not
  			 * specified in 'match->key' should be left to 0.
  			 * Instead, we use a stream of netlink attributes,
  			 * copied from 'key' and set to 0xff.
  			 * ovs_key_from_nlattrs() will take care of filling
  			 * 'match->mask' appropriately.
  			 */
  			newmask = kmemdup(nla_key,
  					  nla_total_size(nla_len(nla_key)),
  					  GFP_KERNEL);
  			if (!newmask)
  				return -ENOMEM;
f47de068f   Pravin B Shelar   openvswitch: Crea...
1748

a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1749
  			mask_set_nlattr(newmask, 0xff);
f47de068f   Pravin B Shelar   openvswitch: Crea...
1750

a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1751
1752
1753
  			/* The userspace does not send tunnel attributes that
  			 * are 0, but we should not wildcard them nonetheless.
  			 */
00a93babd   Jiri Benc   openvswitch: add ...
1754
  			if (match->key->tun_proto)
a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1755
1756
  				SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
  							 0xff, true);
f47de068f   Pravin B Shelar   openvswitch: Crea...
1757

a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1758
1759
  			nla_mask = newmask;
  		}
f47de068f   Pravin B Shelar   openvswitch: Crea...
1760

05da5898a   Jarno Rajahalme   openvswitch: Add ...
1761
  		err = parse_flow_mask_nlattrs(nla_mask, a, &mask_attrs, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
1762
  		if (err)
f47de068f   Pravin B Shelar   openvswitch: Crea...
1763
  			goto free_newmask;
e64457191   Pravin B Shelar   openvswitch: Rest...
1764

a85311bf1   Pravin B Shelar   openvswitch: Avoi...
1765
  		/* Always match on tci. */
018c1dda5   Eric Garver   openvswitch: 802....
1766
1767
  		SW_FLOW_KEY_PUT(match, eth.vlan.tci, htons(0xffff), true);
  		SW_FLOW_KEY_PUT(match, eth.cvlan.tci, htons(0xffff), true);
e64457191   Pravin B Shelar   openvswitch: Rest...
1768

018c1dda5   Eric Garver   openvswitch: 802....
1769
1770
1771
  		err = parse_vlan_from_nlattrs(match, &mask_attrs, a, true, log);
  		if (err)
  			goto free_newmask;
e64457191   Pravin B Shelar   openvswitch: Rest...
1772

c2ac66735   Joe Stringer   openvswitch: Allo...
1773
1774
  		err = ovs_key_from_nlattrs(net, match, mask_attrs, a, true,
  					   log);
e64457191   Pravin B Shelar   openvswitch: Rest...
1775
  		if (err)
f47de068f   Pravin B Shelar   openvswitch: Crea...
1776
  			goto free_newmask;
e64457191   Pravin B Shelar   openvswitch: Rest...
1777
  	}
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1778
  	if (!match_validate(match, key_attrs, mask_attrs, log))
f47de068f   Pravin B Shelar   openvswitch: Crea...
1779
  		err = -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
1780

f47de068f   Pravin B Shelar   openvswitch: Crea...
1781
1782
1783
  free_newmask:
  	kfree(newmask);
  	return err;
e64457191   Pravin B Shelar   openvswitch: Rest...
1784
  }
74ed7ab92   Joe Stringer   openvswitch: Add ...
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
  static size_t get_ufid_len(const struct nlattr *attr, bool log)
  {
  	size_t len;
  
  	if (!attr)
  		return 0;
  
  	len = nla_len(attr);
  	if (len < 1 || len > MAX_UFID_LENGTH) {
  		OVS_NLERR(log, "ufid size %u bytes exceeds the range (1, %d)",
  			  nla_len(attr), MAX_UFID_LENGTH);
  		return 0;
  	}
  
  	return len;
  }
  
  /* Initializes 'flow->ufid', returning true if 'attr' contains a valid UFID,
   * or false otherwise.
   */
  bool ovs_nla_get_ufid(struct sw_flow_id *sfid, const struct nlattr *attr,
  		      bool log)
  {
  	sfid->ufid_len = get_ufid_len(attr, log);
  	if (sfid->ufid_len)
  		memcpy(sfid->ufid, nla_data(attr), sfid->ufid_len);
  
  	return sfid->ufid_len;
  }
  
  int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
  			   const struct sw_flow_key *key, bool log)
  {
  	struct sw_flow_key *new_key;
  
  	if (ovs_nla_get_ufid(sfid, ufid, log))
  		return 0;
  
  	/* If UFID was not provided, use unmasked key. */
  	new_key = kmalloc(sizeof(*new_key), GFP_KERNEL);
  	if (!new_key)
  		return -ENOMEM;
  	memcpy(new_key, key, sizeof(*key));
  	sfid->unmasked_key = new_key;
  
  	return 0;
  }
  
  u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
  {
  	return attr ? nla_get_u32(attr) : 0;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
1837
1838
  /**
   * ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1839
1840
1841
1842
1843
1844
   * @net: Network namespace.
   * @key: Receives extracted in_port, priority, tun_key, skb_mark and conntrack
   * metadata.
   * @a: Array of netlink attributes holding parsed %OVS_KEY_ATTR_* Netlink
   * attributes.
   * @attrs: Bit mask for the netlink attributes included in @a.
05da5898a   Jarno Rajahalme   openvswitch: Add ...
1845
1846
1847
   * @log: Boolean to allow kernel error logging.  Normally true, but when
   * probing for feature compatibility this should be passed in as false to
   * suppress unnecessary error logging.
e64457191   Pravin B Shelar   openvswitch: Rest...
1848
1849
1850
1851
1852
   *
   * This parses a series of Netlink attributes that form a flow key, which must
   * take the same form accepted by flow_from_nlattrs(), but only enough of it to
   * get the metadata, that is, the parts of the flow key that cannot be
   * extracted from the packet itself.
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1853
1854
   *
   * This must be called before the packet key fields are filled in 'key'.
e64457191   Pravin B Shelar   openvswitch: Rest...
1855
   */
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1856
1857
1858
  int ovs_nla_get_flow_metadata(struct net *net,
  			      const struct nlattr *a[OVS_KEY_ATTR_MAX + 1],
  			      u64 attrs, struct sw_flow_key *key, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
1859
  {
83c8df26a   Pravin B Shelar   openvswitch: refa...
1860
  	struct sw_flow_match match;
e64457191   Pravin B Shelar   openvswitch: Rest...
1861
1862
  
  	memset(&match, 0, sizeof(match));
83c8df26a   Pravin B Shelar   openvswitch: refa...
1863
  	match.key = key;
e64457191   Pravin B Shelar   openvswitch: Rest...
1864

316d4d78c   Jarno Rajahalme   openvswitch: Pack...
1865
1866
1867
  	key->ct_state = 0;
  	key->ct_zone = 0;
  	key->ct_orig_proto = 0;
7f8a436ea   Joe Stringer   openvswitch: Add ...
1868
  	memset(&key->ct, 0, sizeof(key->ct));
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1869
1870
  	memset(&key->ipv4.ct_orig, 0, sizeof(key->ipv4.ct_orig));
  	memset(&key->ipv6.ct_orig, 0, sizeof(key->ipv6.ct_orig));
83c8df26a   Pravin B Shelar   openvswitch: refa...
1871
  	key->phy.in_port = DP_MAX_PORTS;
e64457191   Pravin B Shelar   openvswitch: Rest...
1872

c2ac66735   Joe Stringer   openvswitch: Allo...
1873
  	return metadata_from_nlattrs(net, &match, &attrs, a, false, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
1874
  }
018c1dda5   Eric Garver   openvswitch: 802....
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
  static int ovs_nla_put_vlan(struct sk_buff *skb, const struct vlan_head *vh,
  			    bool is_mask)
  {
  	__be16 eth_type = !is_mask ? vh->tpid : htons(0xffff);
  
  	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
  	    nla_put_be16(skb, OVS_KEY_ATTR_VLAN, vh->tci))
  		return -EMSGSIZE;
  	return 0;
  }
b2d0f5d5d   Yi Yang   openvswitch: enab...
1885
1886
1887
1888
  static int nsh_key_to_nlattr(const struct ovs_key_nsh *nsh, bool is_mask,
  			     struct sk_buff *skb)
  {
  	struct nlattr *start;
ae0be8de9   Michal Kubecek   netlink: make nla...
1889
  	start = nla_nest_start_noflag(skb, OVS_KEY_ATTR_NSH);
b2d0f5d5d   Yi Yang   openvswitch: enab...
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
  	if (!start)
  		return -EMSGSIZE;
  
  	if (nla_put(skb, OVS_NSH_KEY_ATTR_BASE, sizeof(nsh->base), &nsh->base))
  		goto nla_put_failure;
  
  	if (is_mask || nsh->base.mdtype == NSH_M_TYPE1) {
  		if (nla_put(skb, OVS_NSH_KEY_ATTR_MD1,
  			    sizeof(nsh->context), nsh->context))
  			goto nla_put_failure;
  	}
  
  	/* Don't support MD type 2 yet */
  
  	nla_nest_end(skb, start);
  
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
5b4237bbc   Joe Stringer   openvswitch: Refa...
1911
1912
1913
  static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
  			     const struct sw_flow_key *output, bool is_mask,
  			     struct sk_buff *skb)
e64457191   Pravin B Shelar   openvswitch: Rest...
1914
1915
  {
  	struct ovs_key_ethernet *eth_key;
018c1dda5   Eric Garver   openvswitch: 802....
1916
1917
1918
  	struct nlattr *nla;
  	struct nlattr *encap = NULL;
  	struct nlattr *in_encap = NULL;
e64457191   Pravin B Shelar   openvswitch: Rest...
1919

971427f35   Andy Zhou   openvswitch: Add ...
1920
1921
1922
1923
1924
  	if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
  		goto nla_put_failure;
  
  	if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash))
  		goto nla_put_failure;
e64457191   Pravin B Shelar   openvswitch: Rest...
1925
1926
  	if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
  		goto nla_put_failure;
00a93babd   Jiri Benc   openvswitch: add ...
1927
  	if ((swkey->tun_proto || is_mask)) {
d91641d9b   Thomas Graf   openvswitch: Rena...
1928
  		const void *opts = NULL;
f57966840   Jesse Gross   openvswitch: Add ...
1929
1930
  
  		if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT)
d91641d9b   Thomas Graf   openvswitch: Rena...
1931
  			opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len);
f57966840   Jesse Gross   openvswitch: Add ...
1932

6b26ba3a7   Jiri Benc   openvswitch: netl...
1933
  		if (ip_tun_to_nlattr(skb, &output->tun_key, opts,
18b6f7174   wenxu   openvswitch: Make...
1934
  				     swkey->tun_opts_len, swkey->tun_proto, 0))
f57966840   Jesse Gross   openvswitch: Add ...
1935
1936
  			goto nla_put_failure;
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
  
  	if (swkey->phy.in_port == DP_MAX_PORTS) {
  		if (is_mask && (output->phy.in_port == 0xffff))
  			if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, 0xffffffff))
  				goto nla_put_failure;
  	} else {
  		u16 upper_u16;
  		upper_u16 = !is_mask ? 0 : 0xffff;
  
  		if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT,
  				(upper_u16 << 16) | output->phy.in_port))
  			goto nla_put_failure;
  	}
  
  	if (nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark))
  		goto nla_put_failure;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1953
  	if (ovs_ct_put_key(swkey, output, skb))
7f8a436ea   Joe Stringer   openvswitch: Add ...
1954
  		goto nla_put_failure;
0a6410fbd   Jiri Benc   openvswitch: netl...
1955
1956
1957
  	if (ovs_key_mac_proto(swkey) == MAC_PROTO_ETHERNET) {
  		nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
  		if (!nla)
e64457191   Pravin B Shelar   openvswitch: Rest...
1958
  			goto nla_put_failure;
018c1dda5   Eric Garver   openvswitch: 802....
1959

0a6410fbd   Jiri Benc   openvswitch: netl...
1960
1961
1962
1963
1964
1965
  		eth_key = nla_data(nla);
  		ether_addr_copy(eth_key->eth_src, output->eth.src);
  		ether_addr_copy(eth_key->eth_dst, output->eth.dst);
  
  		if (swkey->eth.vlan.tci || eth_type_vlan(swkey->eth.type)) {
  			if (ovs_nla_put_vlan(skb, &output->eth.vlan, is_mask))
018c1dda5   Eric Garver   openvswitch: 802....
1966
  				goto nla_put_failure;
ae0be8de9   Michal Kubecek   netlink: make nla...
1967
  			encap = nla_nest_start_noflag(skb, OVS_KEY_ATTR_ENCAP);
0a6410fbd   Jiri Benc   openvswitch: netl...
1968
  			if (!swkey->eth.vlan.tci)
018c1dda5   Eric Garver   openvswitch: 802....
1969
  				goto unencap;
0a6410fbd   Jiri Benc   openvswitch: netl...
1970
1971
1972
1973
  
  			if (swkey->eth.cvlan.tci || eth_type_vlan(swkey->eth.type)) {
  				if (ovs_nla_put_vlan(skb, &output->eth.cvlan, is_mask))
  					goto nla_put_failure;
ae0be8de9   Michal Kubecek   netlink: make nla...
1974
1975
  				in_encap = nla_nest_start_noflag(skb,
  								 OVS_KEY_ATTR_ENCAP);
0a6410fbd   Jiri Benc   openvswitch: netl...
1976
1977
1978
  				if (!swkey->eth.cvlan.tci)
  					goto unencap;
  			}
018c1dda5   Eric Garver   openvswitch: 802....
1979
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
1980

0a6410fbd   Jiri Benc   openvswitch: netl...
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
  		if (swkey->eth.type == htons(ETH_P_802_2)) {
  			/*
  			* Ethertype 802.2 is represented in the netlink with omitted
  			* OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
  			* 0xffff in the mask attribute.  Ethertype can also
  			* be wildcarded.
  			*/
  			if (is_mask && output->eth.type)
  				if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
  							output->eth.type))
  					goto nla_put_failure;
  			goto unencap;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
1994
1995
1996
1997
  	}
  
  	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
  		goto nla_put_failure;
018c1dda5   Eric Garver   openvswitch: 802....
1998
1999
2000
2001
2002
2003
2004
  	if (eth_type_vlan(swkey->eth.type)) {
  		/* There are 3 VLAN tags, we don't know anything about the rest
  		 * of the packet, so truncate here.
  		 */
  		WARN_ON_ONCE(!(encap && in_encap));
  		goto unencap;
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
  	if (swkey->eth.type == htons(ETH_P_IP)) {
  		struct ovs_key_ipv4 *ipv4_key;
  
  		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV4, sizeof(*ipv4_key));
  		if (!nla)
  			goto nla_put_failure;
  		ipv4_key = nla_data(nla);
  		ipv4_key->ipv4_src = output->ipv4.addr.src;
  		ipv4_key->ipv4_dst = output->ipv4.addr.dst;
  		ipv4_key->ipv4_proto = output->ip.proto;
  		ipv4_key->ipv4_tos = output->ip.tos;
  		ipv4_key->ipv4_ttl = output->ip.ttl;
  		ipv4_key->ipv4_frag = output->ip.frag;
  	} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
  		struct ovs_key_ipv6 *ipv6_key;
  
  		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6, sizeof(*ipv6_key));
  		if (!nla)
  			goto nla_put_failure;
  		ipv6_key = nla_data(nla);
  		memcpy(ipv6_key->ipv6_src, &output->ipv6.addr.src,
  				sizeof(ipv6_key->ipv6_src));
  		memcpy(ipv6_key->ipv6_dst, &output->ipv6.addr.dst,
  				sizeof(ipv6_key->ipv6_dst));
  		ipv6_key->ipv6_label = output->ipv6.label;
  		ipv6_key->ipv6_proto = output->ip.proto;
  		ipv6_key->ipv6_tclass = output->ip.tos;
  		ipv6_key->ipv6_hlimit = output->ip.ttl;
  		ipv6_key->ipv6_frag = output->ip.frag;
b2d0f5d5d   Yi Yang   openvswitch: enab...
2034
2035
2036
  	} else if (swkey->eth.type == htons(ETH_P_NSH)) {
  		if (nsh_key_to_nlattr(&output->nsh, is_mask, skb))
  			goto nla_put_failure;
e64457191   Pravin B Shelar   openvswitch: Rest...
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
  	} else if (swkey->eth.type == htons(ETH_P_ARP) ||
  		   swkey->eth.type == htons(ETH_P_RARP)) {
  		struct ovs_key_arp *arp_key;
  
  		nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
  		if (!nla)
  			goto nla_put_failure;
  		arp_key = nla_data(nla);
  		memset(arp_key, 0, sizeof(struct ovs_key_arp));
  		arp_key->arp_sip = output->ipv4.addr.src;
  		arp_key->arp_tip = output->ipv4.addr.dst;
  		arp_key->arp_op = htons(output->ip.proto);
8c63ff09b   Joe Perches   openvswitch: Use ...
2049
2050
  		ether_addr_copy(arp_key->arp_sha, output->ipv4.arp.sha);
  		ether_addr_copy(arp_key->arp_tha, output->ipv4.arp.tha);
25cd9ba0a   Simon Horman   openvswitch: Add ...
2051
  	} else if (eth_p_mpls(swkey->eth.type)) {
fbdcdd78d   Martin Varghese   Change in Openvsw...
2052
  		u8 i, num_labels;
25cd9ba0a   Simon Horman   openvswitch: Add ...
2053
  		struct ovs_key_mpls *mpls_key;
fbdcdd78d   Martin Varghese   Change in Openvsw...
2054
2055
2056
  		num_labels = hweight_long(output->mpls.num_labels_mask);
  		nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS,
  				  num_labels * sizeof(*mpls_key));
25cd9ba0a   Simon Horman   openvswitch: Add ...
2057
2058
  		if (!nla)
  			goto nla_put_failure;
fbdcdd78d   Martin Varghese   Change in Openvsw...
2059

25cd9ba0a   Simon Horman   openvswitch: Add ...
2060
  		mpls_key = nla_data(nla);
fbdcdd78d   Martin Varghese   Change in Openvsw...
2061
2062
  		for (i = 0; i < num_labels; i++)
  			mpls_key[i].mpls_lse = output->mpls.lse[i];
e64457191   Pravin B Shelar   openvswitch: Rest...
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
  	}
  
  	if ((swkey->eth.type == htons(ETH_P_IP) ||
  	     swkey->eth.type == htons(ETH_P_IPV6)) &&
  	     swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
  
  		if (swkey->ip.proto == IPPROTO_TCP) {
  			struct ovs_key_tcp *tcp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_TCP, sizeof(*tcp_key));
  			if (!nla)
  				goto nla_put_failure;
  			tcp_key = nla_data(nla);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
2076
2077
2078
2079
2080
  			tcp_key->tcp_src = output->tp.src;
  			tcp_key->tcp_dst = output->tp.dst;
  			if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS,
  					 output->tp.flags))
  				goto nla_put_failure;
e64457191   Pravin B Shelar   openvswitch: Rest...
2081
2082
2083
2084
2085
2086
2087
  		} else if (swkey->ip.proto == IPPROTO_UDP) {
  			struct ovs_key_udp *udp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_UDP, sizeof(*udp_key));
  			if (!nla)
  				goto nla_put_failure;
  			udp_key = nla_data(nla);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
2088
2089
  			udp_key->udp_src = output->tp.src;
  			udp_key->udp_dst = output->tp.dst;
e64457191   Pravin B Shelar   openvswitch: Rest...
2090
2091
2092
2093
2094
2095
2096
  		} else if (swkey->ip.proto == IPPROTO_SCTP) {
  			struct ovs_key_sctp *sctp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_SCTP, sizeof(*sctp_key));
  			if (!nla)
  				goto nla_put_failure;
  			sctp_key = nla_data(nla);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
2097
2098
  			sctp_key->sctp_src = output->tp.src;
  			sctp_key->sctp_dst = output->tp.dst;
e64457191   Pravin B Shelar   openvswitch: Rest...
2099
2100
2101
2102
2103
2104
2105
2106
  		} else if (swkey->eth.type == htons(ETH_P_IP) &&
  			   swkey->ip.proto == IPPROTO_ICMP) {
  			struct ovs_key_icmp *icmp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMP, sizeof(*icmp_key));
  			if (!nla)
  				goto nla_put_failure;
  			icmp_key = nla_data(nla);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
2107
2108
  			icmp_key->icmp_type = ntohs(output->tp.src);
  			icmp_key->icmp_code = ntohs(output->tp.dst);
e64457191   Pravin B Shelar   openvswitch: Rest...
2109
2110
2111
2112
2113
2114
2115
2116
2117
  		} else if (swkey->eth.type == htons(ETH_P_IPV6) &&
  			   swkey->ip.proto == IPPROTO_ICMPV6) {
  			struct ovs_key_icmpv6 *icmpv6_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMPV6,
  						sizeof(*icmpv6_key));
  			if (!nla)
  				goto nla_put_failure;
  			icmpv6_key = nla_data(nla);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
2118
2119
  			icmpv6_key->icmpv6_type = ntohs(output->tp.src);
  			icmpv6_key->icmpv6_code = ntohs(output->tp.dst);
e64457191   Pravin B Shelar   openvswitch: Rest...
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
  
  			if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
  			    icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
  				struct ovs_key_nd *nd_key;
  
  				nla = nla_reserve(skb, OVS_KEY_ATTR_ND, sizeof(*nd_key));
  				if (!nla)
  					goto nla_put_failure;
  				nd_key = nla_data(nla);
  				memcpy(nd_key->nd_target, &output->ipv6.nd.target,
  							sizeof(nd_key->nd_target));
8c63ff09b   Joe Perches   openvswitch: Use ...
2131
2132
  				ether_addr_copy(nd_key->nd_sll, output->ipv6.nd.sll);
  				ether_addr_copy(nd_key->nd_tll, output->ipv6.nd.tll);
e64457191   Pravin B Shelar   openvswitch: Rest...
2133
2134
2135
2136
2137
  			}
  		}
  	}
  
  unencap:
018c1dda5   Eric Garver   openvswitch: 802....
2138
2139
  	if (in_encap)
  		nla_nest_end(skb, in_encap);
e64457191   Pravin B Shelar   openvswitch: Rest...
2140
2141
2142
2143
2144
2145
2146
2147
  	if (encap)
  		nla_nest_end(skb, encap);
  
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
5b4237bbc   Joe Stringer   openvswitch: Refa...
2148
2149
2150
2151
2152
2153
  int ovs_nla_put_key(const struct sw_flow_key *swkey,
  		    const struct sw_flow_key *output, int attr, bool is_mask,
  		    struct sk_buff *skb)
  {
  	int err;
  	struct nlattr *nla;
ae0be8de9   Michal Kubecek   netlink: make nla...
2154
  	nla = nla_nest_start_noflag(skb, attr);
5b4237bbc   Joe Stringer   openvswitch: Refa...
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
  	if (!nla)
  		return -EMSGSIZE;
  	err = __ovs_nla_put_key(swkey, output, is_mask, skb);
  	if (err)
  		return err;
  	nla_nest_end(skb, nla);
  
  	return 0;
  }
  
  /* Called with ovs_mutex or RCU read lock. */
74ed7ab92   Joe Stringer   openvswitch: Add ...
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
  int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb)
  {
  	if (ovs_identifier_is_ufid(&flow->id))
  		return nla_put(skb, OVS_FLOW_ATTR_UFID, flow->id.ufid_len,
  			       flow->id.ufid);
  
  	return ovs_nla_put_key(flow->id.unmasked_key, flow->id.unmasked_key,
  			       OVS_FLOW_ATTR_KEY, false, skb);
  }
  
  /* Called with ovs_mutex or RCU read lock. */
  int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb)
5b4237bbc   Joe Stringer   openvswitch: Refa...
2178
  {
26ad0b835   Pravin B Shelar   openvswitch: Fix ...
2179
  	return ovs_nla_put_key(&flow->key, &flow->key,
5b4237bbc   Joe Stringer   openvswitch: Refa...
2180
2181
2182
2183
2184
2185
2186
2187
2188
  				OVS_FLOW_ATTR_KEY, false, skb);
  }
  
  /* Called with ovs_mutex or RCU read lock. */
  int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb)
  {
  	return ovs_nla_put_key(&flow->key, &flow->mask->key,
  				OVS_FLOW_ATTR_MASK, true, skb);
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
2189
  #define MAX_ACTIONS_BUFSIZE	(32 * 1024)
67c8d22a7   zhangliping   openvswitch: fix ...
2190
  static struct sw_flow_actions *nla_alloc_flow_actions(int size)
e64457191   Pravin B Shelar   openvswitch: Rest...
2191
2192
  {
  	struct sw_flow_actions *sfa;
67c8d22a7   zhangliping   openvswitch: fix ...
2193
  	WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE);
e64457191   Pravin B Shelar   openvswitch: Rest...
2194
2195
2196
2197
2198
2199
2200
2201
  
  	sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL);
  	if (!sfa)
  		return ERR_PTR(-ENOMEM);
  
  	sfa->actions_len = 0;
  	return sfa;
  }
34ae932a4   Thomas Graf   openvswitch: Make...
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
  static void ovs_nla_free_set_action(const struct nlattr *a)
  {
  	const struct nlattr *ovs_key = nla_data(a);
  	struct ovs_tunnel_info *ovs_tun;
  
  	switch (nla_type(ovs_key)) {
  	case OVS_KEY_ATTR_TUNNEL_INFO:
  		ovs_tun = nla_data(ovs_key);
  		dst_release((struct dst_entry *)ovs_tun->tun_dst);
  		break;
  	}
  }
  
  void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
  {
  	const struct nlattr *a;
  	int rem;
  
  	if (!sf_acts)
  		return;
  
  	nla_for_each_attr(a, sf_acts->actions, sf_acts->actions_len, rem) {
  		switch (nla_type(a)) {
  		case OVS_ACTION_ATTR_SET:
  			ovs_nla_free_set_action(a);
  			break;
7f8a436ea   Joe Stringer   openvswitch: Add ...
2228
2229
2230
  		case OVS_ACTION_ATTR_CT:
  			ovs_ct_free_action(a);
  			break;
34ae932a4   Thomas Graf   openvswitch: Make...
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
  		}
  	}
  
  	kfree(sf_acts);
  }
  
  static void __ovs_nla_free_flow_actions(struct rcu_head *head)
  {
  	ovs_nla_free_flow_actions(container_of(head, struct sw_flow_actions, rcu));
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
2241
2242
  /* Schedules 'sf_acts' to be freed after the next RCU grace period.
   * The caller must hold rcu_read_lock for this to be sensible. */
34ae932a4   Thomas Graf   openvswitch: Make...
2243
  void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *sf_acts)
e64457191   Pravin B Shelar   openvswitch: Rest...
2244
  {
34ae932a4   Thomas Graf   openvswitch: Make...
2245
  	call_rcu(&sf_acts->rcu, __ovs_nla_free_flow_actions);
e64457191   Pravin B Shelar   openvswitch: Rest...
2246
2247
2248
  }
  
  static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2249
  				       int attr_len, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2250
2251
2252
2253
  {
  
  	struct sw_flow_actions *acts;
  	int new_acts_size;
f28cd2af2   Andrea Righi   openvswitch: fix ...
2254
  	size_t req_size = NLA_ALIGN(attr_len);
e64457191   Pravin B Shelar   openvswitch: Rest...
2255
2256
2257
2258
2259
  	int next_offset = offsetof(struct sw_flow_actions, actions) +
  					(*sfa)->actions_len;
  
  	if (req_size <= (ksize(*sfa) - next_offset))
  		goto out;
f28cd2af2   Andrea Righi   openvswitch: fix ...
2260
  	new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
e64457191   Pravin B Shelar   openvswitch: Rest...
2261
2262
  
  	if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
67c8d22a7   zhangliping   openvswitch: fix ...
2263
2264
2265
  		if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) {
  			OVS_NLERR(log, "Flow action size exceeds max %u",
  				  MAX_ACTIONS_BUFSIZE);
e64457191   Pravin B Shelar   openvswitch: Rest...
2266
  			return ERR_PTR(-EMSGSIZE);
67c8d22a7   zhangliping   openvswitch: fix ...
2267
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
2268
2269
  		new_acts_size = MAX_ACTIONS_BUFSIZE;
  	}
67c8d22a7   zhangliping   openvswitch: fix ...
2270
  	acts = nla_alloc_flow_actions(new_acts_size);
e64457191   Pravin B Shelar   openvswitch: Rest...
2271
2272
2273
2274
2275
  	if (IS_ERR(acts))
  		return (void *)acts;
  
  	memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len);
  	acts->actions_len = (*sfa)->actions_len;
8e2fed1c0   Joe Stringer   openvswitch: Seri...
2276
  	acts->orig_len = (*sfa)->orig_len;
e64457191   Pravin B Shelar   openvswitch: Rest...
2277
2278
2279
2280
2281
2282
2283
  	kfree(*sfa);
  	*sfa = acts;
  
  out:
  	(*sfa)->actions_len += req_size;
  	return  (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
  }
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2284
  static struct nlattr *__add_action(struct sw_flow_actions **sfa,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2285
  				   int attrtype, void *data, int len, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2286
2287
  {
  	struct nlattr *a;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2288
  	a = reserve_sfa_size(sfa, nla_attr_size(len), log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2289
  	if (IS_ERR(a))
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2290
  		return a;
e64457191   Pravin B Shelar   openvswitch: Rest...
2291
2292
2293
2294
2295
2296
2297
  
  	a->nla_type = attrtype;
  	a->nla_len = nla_attr_size(len);
  
  	if (data)
  		memcpy(nla_data(a), data, len);
  	memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2298
2299
  	return a;
  }
7f8a436ea   Joe Stringer   openvswitch: Add ...
2300
2301
  int ovs_nla_add_action(struct sw_flow_actions **sfa, int attrtype, void *data,
  		       int len, bool log)
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2302
2303
  {
  	struct nlattr *a;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2304
  	a = __add_action(sfa, attrtype, data, len, log);
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2305

f35423c13   Fabian Frederick   openvswitch: use ...
2306
  	return PTR_ERR_OR_ZERO(a);
e64457191   Pravin B Shelar   openvswitch: Rest...
2307
2308
2309
  }
  
  static inline int add_nested_action_start(struct sw_flow_actions **sfa,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2310
  					  int attrtype, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2311
2312
2313
  {
  	int used = (*sfa)->actions_len;
  	int err;
7f8a436ea   Joe Stringer   openvswitch: Add ...
2314
  	err = ovs_nla_add_action(sfa, attrtype, NULL, 0, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
  	if (err)
  		return err;
  
  	return used;
  }
  
  static inline void add_nested_action_end(struct sw_flow_actions *sfa,
  					 int st_offset)
  {
  	struct nlattr *a = (struct nlattr *) ((unsigned char *)sfa->actions +
  							       st_offset);
  
  	a->nla_len = sfa->actions_len - st_offset;
  }
7f8a436ea   Joe Stringer   openvswitch: Add ...
2329
  static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
25cd9ba0a   Simon Horman   openvswitch: Add ...
2330
  				  const struct sw_flow_key *key,
798c16617   andy zhou   openvswitch: Opti...
2331
  				  struct sw_flow_actions **sfa,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2332
2333
  				  __be16 eth_type, __be16 vlan_tci,
  				  u32 mpls_label_count, bool log);
25cd9ba0a   Simon Horman   openvswitch: Add ...
2334

7f8a436ea   Joe Stringer   openvswitch: Add ...
2335
  static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
798c16617   andy zhou   openvswitch: Opti...
2336
  				    const struct sw_flow_key *key,
25cd9ba0a   Simon Horman   openvswitch: Add ...
2337
  				    struct sw_flow_actions **sfa,
798c16617   andy zhou   openvswitch: Opti...
2338
  				    __be16 eth_type, __be16 vlan_tci,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2339
  				    u32 mpls_label_count, bool log, bool last)
e64457191   Pravin B Shelar   openvswitch: Rest...
2340
2341
2342
2343
  {
  	const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
  	const struct nlattr *probability, *actions;
  	const struct nlattr *a;
798c16617   andy zhou   openvswitch: Opti...
2344
2345
  	int rem, start, err;
  	struct sample_arg arg;
e64457191   Pravin B Shelar   openvswitch: Rest...
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
  
  	memset(attrs, 0, sizeof(attrs));
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
  		if (!type || type > OVS_SAMPLE_ATTR_MAX || attrs[type])
  			return -EINVAL;
  		attrs[type] = a;
  	}
  	if (rem)
  		return -EINVAL;
  
  	probability = attrs[OVS_SAMPLE_ATTR_PROBABILITY];
  	if (!probability || nla_len(probability) != sizeof(u32))
  		return -EINVAL;
  
  	actions = attrs[OVS_SAMPLE_ATTR_ACTIONS];
  	if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
  		return -EINVAL;
  
  	/* validation done, copy sample action. */
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2366
  	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2367
2368
  	if (start < 0)
  		return start;
798c16617   andy zhou   openvswitch: Opti...
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
  
  	/* When both skb and flow may be changed, put the sample
  	 * into a deferred fifo. On the other hand, if only skb
  	 * may be modified, the actions can be executed in place.
  	 *
  	 * Do this analysis at the flow installation time.
  	 * Set 'clone_action->exec' to true if the actions can be
  	 * executed without being deferred.
  	 *
  	 * If the sample is the last action, it can always be excuted
  	 * rather than deferred.
  	 */
  	arg.exec = last || !actions_may_change_flow(actions);
  	arg.probability = nla_get_u32(probability);
  
  	err = ovs_nla_add_action(sfa, OVS_SAMPLE_ATTR_ARG, &arg, sizeof(arg),
  				 log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2386
2387
  	if (err)
  		return err;
e64457191   Pravin B Shelar   openvswitch: Rest...
2388

798c16617   andy zhou   openvswitch: Opti...
2389
  	err = __ovs_nla_copy_actions(net, actions, key, sfa,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2390
  				     eth_type, vlan_tci, mpls_label_count, log);
798c16617   andy zhou   openvswitch: Opti...
2391

e64457191   Pravin B Shelar   openvswitch: Rest...
2392
2393
  	if (err)
  		return err;
e64457191   Pravin B Shelar   openvswitch: Rest...
2394
2395
2396
2397
  	add_nested_action_end(*sfa, start);
  
  	return 0;
  }
744676e77   Matteo Croce   openvswitch: add ...
2398
2399
2400
2401
2402
2403
2404
  static int validate_and_copy_dec_ttl(struct net *net,
  				     const struct nlattr *attr,
  				     const struct sw_flow_key *key,
  				     struct sw_flow_actions **sfa,
  				     __be16 eth_type, __be16 vlan_tci,
  				     u32 mpls_label_count, bool log)
  {
69929d4c4   Eelco Chaudron   net: openvswitch:...
2405
2406
2407
2408
2409
2410
2411
  	const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1];
  	int start, action_start, err, rem;
  	const struct nlattr *a, *actions;
  
  	memset(attrs, 0, sizeof(attrs));
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
744676e77   Matteo Croce   openvswitch: add ...
2412

69929d4c4   Eelco Chaudron   net: openvswitch:...
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
  		/* Ignore unknown attributes to be future proof. */
  		if (type > OVS_DEC_TTL_ATTR_MAX)
  			continue;
  
  		if (!type || attrs[type])
  			return -EINVAL;
  
  		attrs[type] = a;
  	}
  
  	actions = attrs[OVS_DEC_TTL_ATTR_ACTION];
  	if (rem || !actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
  		return -EINVAL;
744676e77   Matteo Croce   openvswitch: add ...
2426
2427
2428
2429
  
  	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log);
  	if (start < 0)
  		return start;
69929d4c4   Eelco Chaudron   net: openvswitch:...
2430
2431
  	action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log);
  	if (action_start < 0)
bb2da7651   Wang Hai   openvswitch: fix ...
2432
  		return action_start;
744676e77   Matteo Croce   openvswitch: add ...
2433

69929d4c4   Eelco Chaudron   net: openvswitch:...
2434
  	err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
744676e77   Matteo Croce   openvswitch: add ...
2435
2436
2437
  				     vlan_tci, mpls_label_count, log);
  	if (err)
  		return err;
69929d4c4   Eelco Chaudron   net: openvswitch:...
2438
  	add_nested_action_end(*sfa, action_start);
744676e77   Matteo Croce   openvswitch: add ...
2439
2440
2441
  	add_nested_action_end(*sfa, start);
  	return 0;
  }
b23350403   Yifeng Sun   openvswitch: kern...
2442
2443
2444
2445
2446
  static int validate_and_copy_clone(struct net *net,
  				   const struct nlattr *attr,
  				   const struct sw_flow_key *key,
  				   struct sw_flow_actions **sfa,
  				   __be16 eth_type, __be16 vlan_tci,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2447
  				   u32 mpls_label_count, bool log, bool last)
b23350403   Yifeng Sun   openvswitch: kern...
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
  {
  	int start, err;
  	u32 exec;
  
  	if (nla_len(attr) && nla_len(attr) < NLA_HDRLEN)
  		return -EINVAL;
  
  	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CLONE, log);
  	if (start < 0)
  		return start;
  
  	exec = last || !actions_may_change_flow(attr);
  
  	err = ovs_nla_add_action(sfa, OVS_CLONE_ATTR_EXEC, &exec,
  				 sizeof(exec), log);
  	if (err)
  		return err;
  
  	err = __ovs_nla_copy_actions(net, attr, key, sfa,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2467
  				     eth_type, vlan_tci, mpls_label_count, log);
b23350403   Yifeng Sun   openvswitch: kern...
2468
2469
2470
2471
2472
2473
2474
  	if (err)
  		return err;
  
  	add_nested_action_end(*sfa, start);
  
  	return 0;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
2475
2476
  void ovs_match_init(struct sw_flow_match *match,
  		    struct sw_flow_key *key,
2279994d0   pravin shelar   openvswitch: avoi...
2477
  		    bool reset_key,
e64457191   Pravin B Shelar   openvswitch: Rest...
2478
2479
2480
2481
2482
  		    struct sw_flow_mask *mask)
  {
  	memset(match, 0, sizeof(*match));
  	match->key = key;
  	match->mask = mask;
2279994d0   pravin shelar   openvswitch: avoi...
2483
2484
  	if (reset_key)
  		memset(key, 0, sizeof(*key));
e64457191   Pravin B Shelar   openvswitch: Rest...
2485
2486
2487
2488
2489
2490
  
  	if (mask) {
  		memset(&mask->key, 0, sizeof(mask->key));
  		mask->range.start = mask->range.end = 0;
  	}
  }
d91641d9b   Thomas Graf   openvswitch: Rena...
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
  static int validate_geneve_opts(struct sw_flow_key *key)
  {
  	struct geneve_opt *option;
  	int opts_len = key->tun_opts_len;
  	bool crit_opt = false;
  
  	option = (struct geneve_opt *)TUN_METADATA_OPTS(key, key->tun_opts_len);
  	while (opts_len > 0) {
  		int len;
  
  		if (opts_len < sizeof(*option))
  			return -EINVAL;
  
  		len = sizeof(*option) + option->length * 4;
  		if (len > opts_len)
  			return -EINVAL;
  
  		crit_opt |= !!(option->type & GENEVE_CRIT_OPT_TYPE);
  
  		option = (struct geneve_opt *)((u8 *)option + len);
  		opts_len -= len;
89290b831   Christopher Díaz Riveros   flow_netlink: Rem...
2512
  	}
d91641d9b   Thomas Graf   openvswitch: Rena...
2513
2514
2515
2516
2517
  
  	key->tun_key.tun_flags |= crit_opt ? TUNNEL_CRIT_OPT : 0;
  
  	return 0;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
2518
  static int validate_and_copy_set_tun(const struct nlattr *attr,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2519
  				     struct sw_flow_actions **sfa, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2520
2521
2522
  {
  	struct sw_flow_match match;
  	struct sw_flow_key key;
34ae932a4   Thomas Graf   openvswitch: Make...
2523
  	struct metadata_dst *tun_dst;
1d8fff907   Thomas Graf   ip_tunnel: Make o...
2524
  	struct ip_tunnel_info *tun_info;
34ae932a4   Thomas Graf   openvswitch: Make...
2525
  	struct ovs_tunnel_info *ovs_tun;
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2526
  	struct nlattr *a;
13101602c   Geert Uytterhoeven   openvswitch: Add ...
2527
  	int err = 0, start, opts_type;
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
2528
  	__be16 dst_opt_type;
e64457191   Pravin B Shelar   openvswitch: Rest...
2529

256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
2530
  	dst_opt_type = 0;
2279994d0   pravin shelar   openvswitch: avoi...
2531
  	ovs_match_init(&match, &key, true, NULL);
6b26ba3a7   Jiri Benc   openvswitch: netl...
2532
  	opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
1dd144cf5   Thomas Graf   openvswitch: Supp...
2533
2534
  	if (opts_type < 0)
  		return opts_type;
e64457191   Pravin B Shelar   openvswitch: Rest...
2535

f57966840   Jesse Gross   openvswitch: Add ...
2536
  	if (key.tun_opts_len) {
1dd144cf5   Thomas Graf   openvswitch: Supp...
2537
2538
2539
2540
2541
  		switch (opts_type) {
  		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
  			err = validate_geneve_opts(&key);
  			if (err < 0)
  				return err;
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
2542
  			dst_opt_type = TUNNEL_GENEVE_OPT;
1dd144cf5   Thomas Graf   openvswitch: Supp...
2543
2544
  			break;
  		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
2545
  			dst_opt_type = TUNNEL_VXLAN_OPT;
1dd144cf5   Thomas Graf   openvswitch: Supp...
2546
  			break;
fc1372f89   William Tu   openvswitch: add ...
2547
  		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
2548
  			dst_opt_type = TUNNEL_ERSPAN_OPT;
fc1372f89   William Tu   openvswitch: add ...
2549
  			break;
1dd144cf5   Thomas Graf   openvswitch: Supp...
2550
  		}
89290b831   Christopher Díaz Riveros   flow_netlink: Rem...
2551
  	}
f57966840   Jesse Gross   openvswitch: Add ...
2552

05da5898a   Jarno Rajahalme   openvswitch: Add ...
2553
  	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2554
2555
  	if (start < 0)
  		return start;
3fcece12b   Jakub Kicinski   net: store port/r...
2556
2557
  	tun_dst = metadata_dst_alloc(key.tun_opts_len, METADATA_IP_TUNNEL,
  				     GFP_KERNEL);
34ae932a4   Thomas Graf   openvswitch: Make...
2558
2559
  	if (!tun_dst)
  		return -ENOMEM;
d71785ffc   Paolo Abeni   net: add dst_cach...
2560
2561
2562
2563
2564
  	err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
  	if (err) {
  		dst_release((struct dst_entry *)tun_dst);
  		return err;
  	}
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2565
  	a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
34ae932a4   Thomas Graf   openvswitch: Make...
2566
2567
2568
  			 sizeof(*ovs_tun), log);
  	if (IS_ERR(a)) {
  		dst_release((struct dst_entry *)tun_dst);
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2569
  		return PTR_ERR(a);
34ae932a4   Thomas Graf   openvswitch: Make...
2570
2571
2572
2573
  	}
  
  	ovs_tun = nla_data(a);
  	ovs_tun->tun_dst = tun_dst;
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2574

34ae932a4   Thomas Graf   openvswitch: Make...
2575
2576
  	tun_info = &tun_dst->u.tun_info;
  	tun_info->mode = IP_TUNNEL_INFO_TX;
00a93babd   Jiri Benc   openvswitch: add ...
2577
2578
  	if (key.tun_proto == AF_INET6)
  		tun_info->mode |= IP_TUNNEL_INFO_IPV6;
18b6f7174   wenxu   openvswitch: Make...
2579
2580
  	else if (key.tun_proto == AF_INET && key.tun_key.u.ipv4.dst == 0)
  		tun_info->mode |= IP_TUNNEL_INFO_BRIDGE;
1d8fff907   Thomas Graf   ip_tunnel: Make o...
2581
  	tun_info->key = key.tun_key;
f0b128c1e   Jesse Gross   openvswitch: Wrap...
2582

4c2227984   Pravin B Shelar   ip-tunnel: Use AP...
2583
2584
2585
2586
2587
2588
  	/* We need to store the options in the action itself since
  	 * everything else will go away after flow setup. We can append
  	 * it to tun_info and then point there.
  	 */
  	ip_tunnel_info_opts_set(tun_info,
  				TUN_METADATA_OPTS(&key, key.tun_opts_len),
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
2589
  				key.tun_opts_len, dst_opt_type);
e64457191   Pravin B Shelar   openvswitch: Rest...
2590
2591
2592
2593
  	add_nested_action_end(*sfa, start);
  
  	return err;
  }
b2d0f5d5d   Yi Yang   openvswitch: enab...
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
  static bool validate_nsh(const struct nlattr *attr, bool is_mask,
  			 bool is_push_nsh, bool log)
  {
  	struct sw_flow_match match;
  	struct sw_flow_key key;
  	int ret = 0;
  
  	ovs_match_init(&match, &key, true, NULL);
  	ret = nsh_key_put_from_nlattr(attr, &match, is_mask,
  				      is_push_nsh, log);
  	return !ret;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
  /* Return false if there are any non-masked bits set.
   * Mask follows data immediately, before any netlink padding.
   */
  static bool validate_masked(u8 *data, int len)
  {
  	u8 *mask = data + len;
  
  	while (len--)
  		if (*data++ & ~*mask++)
  			return false;
  
  	return true;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
2619
2620
  static int validate_set(const struct nlattr *a,
  			const struct sw_flow_key *flow_key,
0a6410fbd   Jiri Benc   openvswitch: netl...
2621
2622
  			struct sw_flow_actions **sfa, bool *skip_copy,
  			u8 mac_proto, __be16 eth_type, bool masked, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2623
2624
2625
  {
  	const struct nlattr *ovs_key = nla_data(a);
  	int key_type = nla_type(ovs_key);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2626
  	size_t key_len;
e64457191   Pravin B Shelar   openvswitch: Rest...
2627
2628
2629
2630
  
  	/* There can be only one key in a action */
  	if (nla_total_size(nla_len(ovs_key)) != nla_len(a))
  		return -EINVAL;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2631
2632
2633
  	key_len = nla_len(ovs_key);
  	if (masked)
  		key_len /= 2;
e64457191   Pravin B Shelar   openvswitch: Rest...
2634
  	if (key_type > OVS_KEY_ATTR_MAX ||
982b52700   Jesse Gross   openvswitch: Fix ...
2635
  	    !check_attr_len(key_len, ovs_key_lens[key_type].len))
e64457191   Pravin B Shelar   openvswitch: Rest...
2636
  		return -EINVAL;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2637
2638
  	if (masked && !validate_masked(nla_data(ovs_key), key_len))
  		return -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
2639
  	switch (key_type) {
e64457191   Pravin B Shelar   openvswitch: Rest...
2640
2641
  	case OVS_KEY_ATTR_PRIORITY:
  	case OVS_KEY_ATTR_SKB_MARK:
182e3042e   Joe Stringer   openvswitch: Allo...
2642
  	case OVS_KEY_ATTR_CT_MARK:
33db4125e   Joe Stringer   openvswitch: Rena...
2643
  	case OVS_KEY_ATTR_CT_LABELS:
e64457191   Pravin B Shelar   openvswitch: Rest...
2644
  		break;
0a6410fbd   Jiri Benc   openvswitch: netl...
2645
2646
2647
  	case OVS_KEY_ATTR_ETHERNET:
  		if (mac_proto != MAC_PROTO_ETHERNET)
  			return -EINVAL;
87e159c59   Jarno Rajahalme   openvswitch: Add ...
2648
  		break;
0a6410fbd   Jiri Benc   openvswitch: netl...
2649

16a556eeb   Kees Cook   openvswitch: Dist...
2650
2651
  	case OVS_KEY_ATTR_TUNNEL: {
  		int err;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2652
2653
2654
2655
  		if (masked)
  			return -EINVAL; /* Masked tunnel set not supported. */
  
  		*skip_copy = true;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2656
  		err = validate_and_copy_set_tun(a, sfa, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2657
2658
2659
  		if (err)
  			return err;
  		break;
16a556eeb   Kees Cook   openvswitch: Dist...
2660
2661
2662
  	}
  	case OVS_KEY_ATTR_IPV4: {
  		const struct ovs_key_ipv4 *ipv4_key;
e64457191   Pravin B Shelar   openvswitch: Rest...
2663

25cd9ba0a   Simon Horman   openvswitch: Add ...
2664
  		if (eth_type != htons(ETH_P_IP))
e64457191   Pravin B Shelar   openvswitch: Rest...
2665
  			return -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
2666
  		ipv4_key = nla_data(ovs_key);
e64457191   Pravin B Shelar   openvswitch: Rest...
2667

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2668
2669
  		if (masked) {
  			const struct ovs_key_ipv4 *mask = ipv4_key + 1;
e64457191   Pravin B Shelar   openvswitch: Rest...
2670

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
  			/* Non-writeable fields. */
  			if (mask->ipv4_proto || mask->ipv4_frag)
  				return -EINVAL;
  		} else {
  			if (ipv4_key->ipv4_proto != flow_key->ip.proto)
  				return -EINVAL;
  
  			if (ipv4_key->ipv4_frag != flow_key->ip.frag)
  				return -EINVAL;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
2681
  		break;
16a556eeb   Kees Cook   openvswitch: Dist...
2682
2683
2684
  	}
  	case OVS_KEY_ATTR_IPV6: {
  		const struct ovs_key_ipv6 *ipv6_key;
e64457191   Pravin B Shelar   openvswitch: Rest...
2685

25cd9ba0a   Simon Horman   openvswitch: Add ...
2686
  		if (eth_type != htons(ETH_P_IPV6))
e64457191   Pravin B Shelar   openvswitch: Rest...
2687
  			return -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
2688
  		ipv6_key = nla_data(ovs_key);
e64457191   Pravin B Shelar   openvswitch: Rest...
2689

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
  		if (masked) {
  			const struct ovs_key_ipv6 *mask = ipv6_key + 1;
  
  			/* Non-writeable fields. */
  			if (mask->ipv6_proto || mask->ipv6_frag)
  				return -EINVAL;
  
  			/* Invalid bits in the flow label mask? */
  			if (ntohl(mask->ipv6_label) & 0xFFF00000)
  				return -EINVAL;
  		} else {
  			if (ipv6_key->ipv6_proto != flow_key->ip.proto)
  				return -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
2703

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2704
2705
2706
  			if (ipv6_key->ipv6_frag != flow_key->ip.frag)
  				return -EINVAL;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
2707
2708
2709
2710
  		if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000)
  			return -EINVAL;
  
  		break;
16a556eeb   Kees Cook   openvswitch: Dist...
2711
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
2712
  	case OVS_KEY_ATTR_TCP:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2713
2714
2715
  		if ((eth_type != htons(ETH_P_IP) &&
  		     eth_type != htons(ETH_P_IPV6)) ||
  		    flow_key->ip.proto != IPPROTO_TCP)
e64457191   Pravin B Shelar   openvswitch: Rest...
2716
  			return -EINVAL;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2717
  		break;
e64457191   Pravin B Shelar   openvswitch: Rest...
2718
2719
  
  	case OVS_KEY_ATTR_UDP:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2720
2721
2722
  		if ((eth_type != htons(ETH_P_IP) &&
  		     eth_type != htons(ETH_P_IPV6)) ||
  		    flow_key->ip.proto != IPPROTO_UDP)
e64457191   Pravin B Shelar   openvswitch: Rest...
2723
  			return -EINVAL;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2724
  		break;
25cd9ba0a   Simon Horman   openvswitch: Add ...
2725
2726
2727
2728
2729
  
  	case OVS_KEY_ATTR_MPLS:
  		if (!eth_p_mpls(eth_type))
  			return -EINVAL;
  		break;
e64457191   Pravin B Shelar   openvswitch: Rest...
2730
2731
  
  	case OVS_KEY_ATTR_SCTP:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2732
2733
2734
  		if ((eth_type != htons(ETH_P_IP) &&
  		     eth_type != htons(ETH_P_IPV6)) ||
  		    flow_key->ip.proto != IPPROTO_SCTP)
e64457191   Pravin B Shelar   openvswitch: Rest...
2735
  			return -EINVAL;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2736
  		break;
e64457191   Pravin B Shelar   openvswitch: Rest...
2737

b2d0f5d5d   Yi Yang   openvswitch: enab...
2738
2739
2740
2741
2742
2743
  	case OVS_KEY_ATTR_NSH:
  		if (eth_type != htons(ETH_P_NSH))
  			return -EINVAL;
  		if (!validate_nsh(nla_data(a), masked, false, log))
  			return -EINVAL;
  		break;
e64457191   Pravin B Shelar   openvswitch: Rest...
2744
2745
2746
  	default:
  		return -EINVAL;
  	}
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
  	/* Convert non-masked non-tunnel set actions to masked set actions. */
  	if (!masked && key_type != OVS_KEY_ATTR_TUNNEL) {
  		int start, len = key_len * 2;
  		struct nlattr *at;
  
  		*skip_copy = true;
  
  		start = add_nested_action_start(sfa,
  						OVS_ACTION_ATTR_SET_TO_MASKED,
  						log);
  		if (start < 0)
  			return start;
  
  		at = __add_action(sfa, key_type, NULL, len, log);
  		if (IS_ERR(at))
  			return PTR_ERR(at);
  
  		memcpy(nla_data(at), nla_data(ovs_key), key_len); /* Key. */
  		memset(nla_data(at) + key_len, 0xff, key_len);    /* Mask. */
  		/* Clear non-writeable bits from otherwise writeable fields. */
  		if (key_type == OVS_KEY_ATTR_IPV6) {
  			struct ovs_key_ipv6 *mask = nla_data(at) + key_len;
  
  			mask->ipv6_label &= htonl(0x000FFFFF);
  		}
  		add_nested_action_end(*sfa, start);
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
2774
2775
2776
2777
2778
2779
2780
2781
  	return 0;
  }
  
  static int validate_userspace(const struct nlattr *attr)
  {
  	static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = {
  		[OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
  		[OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
2782
  		[OVS_USERSPACE_ATTR_EGRESS_TUN_PORT] = {.type = NLA_U32 },
e64457191   Pravin B Shelar   openvswitch: Rest...
2783
2784
2785
  	};
  	struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
  	int error;
8cb081746   Johannes Berg   netlink: make val...
2786
2787
  	error = nla_parse_nested_deprecated(a, OVS_USERSPACE_ATTR_MAX, attr,
  					    userspace_policy, NULL);
e64457191   Pravin B Shelar   openvswitch: Rest...
2788
2789
2790
2791
2792
2793
2794
2795
2796
  	if (error)
  		return error;
  
  	if (!a[OVS_USERSPACE_ATTR_PID] ||
  	    !nla_get_u32(a[OVS_USERSPACE_ATTR_PID]))
  		return -EINVAL;
  
  	return 0;
  }
4d5ec89fc   Numan Siddique   net: openvswitch:...
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
  static const struct nla_policy cpl_policy[OVS_CHECK_PKT_LEN_ATTR_MAX + 1] = {
  	[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] = {.type = NLA_U16 },
  	[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER] = {.type = NLA_NESTED },
  	[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL] = {.type = NLA_NESTED },
  };
  
  static int validate_and_copy_check_pkt_len(struct net *net,
  					   const struct nlattr *attr,
  					   const struct sw_flow_key *key,
  					   struct sw_flow_actions **sfa,
  					   __be16 eth_type, __be16 vlan_tci,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2808
  					   u32 mpls_label_count,
4d5ec89fc   Numan Siddique   net: openvswitch:...
2809
2810
2811
2812
2813
2814
2815
  					   bool log, bool last)
  {
  	const struct nlattr *acts_if_greater, *acts_if_lesser_eq;
  	struct nlattr *a[OVS_CHECK_PKT_LEN_ATTR_MAX + 1];
  	struct check_pkt_len_arg arg;
  	int nested_acts_start;
  	int start, err;
8cb081746   Johannes Berg   netlink: make val...
2816
2817
2818
  	err = nla_parse_deprecated_strict(a, OVS_CHECK_PKT_LEN_ATTR_MAX,
  					  nla_data(attr), nla_len(attr),
  					  cpl_policy, NULL);
4d5ec89fc   Numan Siddique   net: openvswitch:...
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
  	if (err)
  		return err;
  
  	if (!a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] ||
  	    !nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]))
  		return -EINVAL;
  
  	acts_if_lesser_eq = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL];
  	acts_if_greater = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER];
  
  	/* Both the nested action should be present. */
  	if (!acts_if_greater || !acts_if_lesser_eq)
  		return -EINVAL;
  
  	/* validation done, copy the nested actions. */
  	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CHECK_PKT_LEN,
  					log);
  	if (start < 0)
  		return start;
  
  	arg.pkt_len = nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]);
  	arg.exec_for_lesser_equal =
  		last || !actions_may_change_flow(acts_if_lesser_eq);
  	arg.exec_for_greater =
  		last || !actions_may_change_flow(acts_if_greater);
  
  	err = ovs_nla_add_action(sfa, OVS_CHECK_PKT_LEN_ATTR_ARG, &arg,
  				 sizeof(arg), log);
  	if (err)
  		return err;
  
  	nested_acts_start = add_nested_action_start(sfa,
  		OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL, log);
  	if (nested_acts_start < 0)
  		return nested_acts_start;
  
  	err = __ovs_nla_copy_actions(net, acts_if_lesser_eq, key, sfa,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2856
  				     eth_type, vlan_tci, mpls_label_count, log);
4d5ec89fc   Numan Siddique   net: openvswitch:...
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
  
  	if (err)
  		return err;
  
  	add_nested_action_end(*sfa, nested_acts_start);
  
  	nested_acts_start = add_nested_action_start(sfa,
  		OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER, log);
  	if (nested_acts_start < 0)
  		return nested_acts_start;
  
  	err = __ovs_nla_copy_actions(net, acts_if_greater, key, sfa,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2869
  				     eth_type, vlan_tci, mpls_label_count, log);
4d5ec89fc   Numan Siddique   net: openvswitch:...
2870
2871
2872
2873
2874
2875
2876
2877
  
  	if (err)
  		return err;
  
  	add_nested_action_end(*sfa, nested_acts_start);
  	add_nested_action_end(*sfa, start);
  	return 0;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
2878
  static int copy_action(const struct nlattr *from,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2879
  		       struct sw_flow_actions **sfa, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2880
2881
2882
  {
  	int totlen = NLA_ALIGN(from->nla_len);
  	struct nlattr *to;
05da5898a   Jarno Rajahalme   openvswitch: Add ...
2883
  	to = reserve_sfa_size(sfa, from->nla_len, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
2884
2885
2886
2887
2888
2889
  	if (IS_ERR(to))
  		return PTR_ERR(to);
  
  	memcpy(to, from, totlen);
  	return 0;
  }
7f8a436ea   Joe Stringer   openvswitch: Add ...
2890
  static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
25cd9ba0a   Simon Horman   openvswitch: Add ...
2891
  				  const struct sw_flow_key *key,
798c16617   andy zhou   openvswitch: Opti...
2892
  				  struct sw_flow_actions **sfa,
fbdcdd78d   Martin Varghese   Change in Openvsw...
2893
2894
  				  __be16 eth_type, __be16 vlan_tci,
  				  u32 mpls_label_count, bool log)
e64457191   Pravin B Shelar   openvswitch: Rest...
2895
  {
0a6410fbd   Jiri Benc   openvswitch: netl...
2896
  	u8 mac_proto = ovs_key_mac_proto(key);
e64457191   Pravin B Shelar   openvswitch: Rest...
2897
2898
  	const struct nlattr *a;
  	int rem, err;
e64457191   Pravin B Shelar   openvswitch: Rest...
2899
2900
2901
2902
  	nla_for_each_nested(a, attr, rem) {
  		/* Expected argument lengths, (u32)-1 for variable length. */
  		static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
  			[OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
971427f35   Andy Zhou   openvswitch: Add ...
2903
  			[OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
e64457191   Pravin B Shelar   openvswitch: Rest...
2904
  			[OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
25cd9ba0a   Simon Horman   openvswitch: Add ...
2905
2906
  			[OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls),
  			[OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
e64457191   Pravin B Shelar   openvswitch: Rest...
2907
2908
2909
  			[OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
  			[OVS_ACTION_ATTR_POP_VLAN] = 0,
  			[OVS_ACTION_ATTR_SET] = (u32)-1,
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
2910
  			[OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
971427f35   Andy Zhou   openvswitch: Add ...
2911
  			[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
7f8a436ea   Joe Stringer   openvswitch: Add ...
2912
2913
  			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
  			[OVS_ACTION_ATTR_CT] = (u32)-1,
b8226962b   Eric Garver   openvswitch: add ...
2914
  			[OVS_ACTION_ATTR_CT_CLEAR] = 0,
f2a4d086e   William Tu   openvswitch: Add ...
2915
  			[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
91820da6a   Jiri Benc   openvswitch: add ...
2916
2917
  			[OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
  			[OVS_ACTION_ATTR_POP_ETH] = 0,
b2d0f5d5d   Yi Yang   openvswitch: enab...
2918
2919
  			[OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
  			[OVS_ACTION_ATTR_POP_NSH] = 0,
cd8a6c336   Andy Zhou   openvswitch: Add ...
2920
  			[OVS_ACTION_ATTR_METER] = sizeof(u32),
b23350403   Yifeng Sun   openvswitch: kern...
2921
  			[OVS_ACTION_ATTR_CLONE] = (u32)-1,
4d5ec89fc   Numan Siddique   net: openvswitch:...
2922
  			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
f66b53fdb   Martin Varghese   openvswitch: New ...
2923
  			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
744676e77   Matteo Croce   openvswitch: add ...
2924
  			[OVS_ACTION_ATTR_DEC_TTL] = (u32)-1,
e64457191   Pravin B Shelar   openvswitch: Rest...
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
  		};
  		const struct ovs_action_push_vlan *vlan;
  		int type = nla_type(a);
  		bool skip_copy;
  
  		if (type > OVS_ACTION_ATTR_MAX ||
  		    (action_lens[type] != nla_len(a) &&
  		     action_lens[type] != (u32)-1))
  			return -EINVAL;
  
  		skip_copy = false;
  		switch (type) {
  		case OVS_ACTION_ATTR_UNSPEC:
  			return -EINVAL;
  
  		case OVS_ACTION_ATTR_USERSPACE:
  			err = validate_userspace(a);
  			if (err)
  				return err;
  			break;
  
  		case OVS_ACTION_ATTR_OUTPUT:
  			if (nla_get_u32(a) >= DP_MAX_PORTS)
  				return -EINVAL;
  			break;
f2a4d086e   William Tu   openvswitch: Add ...
2950
2951
2952
2953
2954
2955
2956
  		case OVS_ACTION_ATTR_TRUNC: {
  			const struct ovs_action_trunc *trunc = nla_data(a);
  
  			if (trunc->max_len < ETH_HLEN)
  				return -EINVAL;
  			break;
  		}
971427f35   Andy Zhou   openvswitch: Add ...
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
  		case OVS_ACTION_ATTR_HASH: {
  			const struct ovs_action_hash *act_hash = nla_data(a);
  
  			switch (act_hash->hash_alg) {
  			case OVS_HASH_ALG_L4:
  				break;
  			default:
  				return  -EINVAL;
  			}
  
  			break;
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
2969
2970
  
  		case OVS_ACTION_ATTR_POP_VLAN:
0a6410fbd   Jiri Benc   openvswitch: netl...
2971
2972
  			if (mac_proto != MAC_PROTO_ETHERNET)
  				return -EINVAL;
25cd9ba0a   Simon Horman   openvswitch: Add ...
2973
  			vlan_tci = htons(0);
e64457191   Pravin B Shelar   openvswitch: Rest...
2974
2975
2976
  			break;
  
  		case OVS_ACTION_ATTR_PUSH_VLAN:
0a6410fbd   Jiri Benc   openvswitch: netl...
2977
2978
  			if (mac_proto != MAC_PROTO_ETHERNET)
  				return -EINVAL;
e64457191   Pravin B Shelar   openvswitch: Rest...
2979
  			vlan = nla_data(a);
018c1dda5   Eric Garver   openvswitch: 802....
2980
  			if (!eth_type_vlan(vlan->vlan_tpid))
e64457191   Pravin B Shelar   openvswitch: Rest...
2981
  				return -EINVAL;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
2982
  			if (!(vlan->vlan_tci & htons(VLAN_CFI_MASK)))
e64457191   Pravin B Shelar   openvswitch: Rest...
2983
  				return -EINVAL;
25cd9ba0a   Simon Horman   openvswitch: Add ...
2984
  			vlan_tci = vlan->vlan_tci;
e64457191   Pravin B Shelar   openvswitch: Rest...
2985
  			break;
971427f35   Andy Zhou   openvswitch: Add ...
2986
2987
  		case OVS_ACTION_ATTR_RECIRC:
  			break;
f66b53fdb   Martin Varghese   openvswitch: New ...
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
  		case OVS_ACTION_ATTR_ADD_MPLS: {
  			const struct ovs_action_add_mpls *mpls = nla_data(a);
  
  			if (!eth_p_mpls(mpls->mpls_ethertype))
  				return -EINVAL;
  
  			if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK) {
  				if (vlan_tci & htons(VLAN_CFI_MASK) ||
  				    (eth_type != htons(ETH_P_IP) &&
  				     eth_type != htons(ETH_P_IPV6) &&
  				     eth_type != htons(ETH_P_ARP) &&
  				     eth_type != htons(ETH_P_RARP) &&
  				     !eth_p_mpls(eth_type)))
  					return -EINVAL;
  				mpls_label_count++;
  			} else {
  				if (mac_proto == MAC_PROTO_ETHERNET) {
  					mpls_label_count = 1;
  					mac_proto = MAC_PROTO_NONE;
  				} else {
  					mpls_label_count++;
  				}
  			}
  			eth_type = mpls->mpls_ethertype;
  			break;
  		}
25cd9ba0a   Simon Horman   openvswitch: Add ...
3014
3015
  		case OVS_ACTION_ATTR_PUSH_MPLS: {
  			const struct ovs_action_push_mpls *mpls = nla_data(a);
25cd9ba0a   Simon Horman   openvswitch: Add ...
3016
3017
3018
3019
3020
  			if (!eth_p_mpls(mpls->mpls_ethertype))
  				return -EINVAL;
  			/* Prohibit push MPLS other than to a white list
  			 * for packets that have a known tag order.
  			 */
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
3021
  			if (vlan_tci & htons(VLAN_CFI_MASK) ||
25cd9ba0a   Simon Horman   openvswitch: Add ...
3022
3023
3024
3025
3026
3027
3028
  			    (eth_type != htons(ETH_P_IP) &&
  			     eth_type != htons(ETH_P_IPV6) &&
  			     eth_type != htons(ETH_P_ARP) &&
  			     eth_type != htons(ETH_P_RARP) &&
  			     !eth_p_mpls(eth_type)))
  				return -EINVAL;
  			eth_type = mpls->mpls_ethertype;
fbdcdd78d   Martin Varghese   Change in Openvsw...
3029
  			mpls_label_count++;
25cd9ba0a   Simon Horman   openvswitch: Add ...
3030
3031
  			break;
  		}
fbdcdd78d   Martin Varghese   Change in Openvsw...
3032
3033
  		case OVS_ACTION_ATTR_POP_MPLS: {
  			__be16  proto;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
3034
  			if (vlan_tci & htons(VLAN_CFI_MASK) ||
25cd9ba0a   Simon Horman   openvswitch: Add ...
3035
3036
  			    !eth_p_mpls(eth_type))
  				return -EINVAL;
fbdcdd78d   Martin Varghese   Change in Openvsw...
3037
3038
3039
3040
3041
3042
  			/* Disallow subsequent L2.5+ set actions and mpls_pop
  			 * actions once the last MPLS label in the packet is
  			 * is popped as there is no check here to ensure that
  			 * the new eth type is valid and thus set actions could
  			 * write off the end of the packet or otherwise corrupt
  			 * it.
25cd9ba0a   Simon Horman   openvswitch: Add ...
3043
3044
3045
3046
  			 *
  			 * Support for these actions is planned using packet
  			 * recirculation.
  			 */
fbdcdd78d   Martin Varghese   Change in Openvsw...
3047
  			proto = nla_get_be16(a);
f66b53fdb   Martin Varghese   openvswitch: New ...
3048
3049
3050
3051
  
  			if (proto == htons(ETH_P_TEB) &&
  			    mac_proto != MAC_PROTO_NONE)
  				return -EINVAL;
fbdcdd78d   Martin Varghese   Change in Openvsw...
3052
3053
3054
3055
3056
3057
  			mpls_label_count--;
  
  			if (!eth_p_mpls(proto) || !mpls_label_count)
  				eth_type = htons(0);
  			else
  				eth_type =  proto;
25cd9ba0a   Simon Horman   openvswitch: Add ...
3058
  			break;
fbdcdd78d   Martin Varghese   Change in Openvsw...
3059
  		}
25cd9ba0a   Simon Horman   openvswitch: Add ...
3060

e64457191   Pravin B Shelar   openvswitch: Rest...
3061
  		case OVS_ACTION_ATTR_SET:
25cd9ba0a   Simon Horman   openvswitch: Add ...
3062
  			err = validate_set(a, key, sfa,
0a6410fbd   Jiri Benc   openvswitch: netl...
3063
3064
  					   &skip_copy, mac_proto, eth_type,
  					   false, log);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3065
3066
3067
3068
3069
3070
  			if (err)
  				return err;
  			break;
  
  		case OVS_ACTION_ATTR_SET_MASKED:
  			err = validate_set(a, key, sfa,
0a6410fbd   Jiri Benc   openvswitch: netl...
3071
3072
  					   &skip_copy, mac_proto, eth_type,
  					   true, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
3073
3074
3075
  			if (err)
  				return err;
  			break;
798c16617   andy zhou   openvswitch: Opti...
3076
3077
3078
3079
3080
  		case OVS_ACTION_ATTR_SAMPLE: {
  			bool last = nla_is_last(a, rem);
  
  			err = validate_and_copy_sample(net, a, key, sfa,
  						       eth_type, vlan_tci,
fbdcdd78d   Martin Varghese   Change in Openvsw...
3081
  						       mpls_label_count,
798c16617   andy zhou   openvswitch: Opti...
3082
  						       log, last);
e64457191   Pravin B Shelar   openvswitch: Rest...
3083
3084
3085
3086
  			if (err)
  				return err;
  			skip_copy = true;
  			break;
798c16617   andy zhou   openvswitch: Opti...
3087
  		}
e64457191   Pravin B Shelar   openvswitch: Rest...
3088

7f8a436ea   Joe Stringer   openvswitch: Add ...
3089
3090
3091
3092
3093
3094
  		case OVS_ACTION_ATTR_CT:
  			err = ovs_ct_copy_action(net, a, key, sfa, log);
  			if (err)
  				return err;
  			skip_copy = true;
  			break;
b8226962b   Eric Garver   openvswitch: add ...
3095
3096
  		case OVS_ACTION_ATTR_CT_CLEAR:
  			break;
91820da6a   Jiri Benc   openvswitch: add ...
3097
3098
3099
3100
3101
  		case OVS_ACTION_ATTR_PUSH_ETH:
  			/* Disallow pushing an Ethernet header if one
  			 * is already present */
  			if (mac_proto != MAC_PROTO_NONE)
  				return -EINVAL;
46ebe2834   Jaime Caamaño Ruiz   openvswitch: Fix ...
3102
  			mac_proto = MAC_PROTO_ETHERNET;
91820da6a   Jiri Benc   openvswitch: add ...
3103
3104
3105
3106
3107
  			break;
  
  		case OVS_ACTION_ATTR_POP_ETH:
  			if (mac_proto != MAC_PROTO_ETHERNET)
  				return -EINVAL;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
3108
  			if (vlan_tci & htons(VLAN_CFI_MASK))
91820da6a   Jiri Benc   openvswitch: add ...
3109
  				return -EINVAL;
46ebe2834   Jaime Caamaño Ruiz   openvswitch: Fix ...
3110
  			mac_proto = MAC_PROTO_NONE;
91820da6a   Jiri Benc   openvswitch: add ...
3111
  			break;
b2d0f5d5d   Yi Yang   openvswitch: enab...
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
  		case OVS_ACTION_ATTR_PUSH_NSH:
  			if (mac_proto != MAC_PROTO_ETHERNET) {
  				u8 next_proto;
  
  				next_proto = tun_p_from_eth_p(eth_type);
  				if (!next_proto)
  					return -EINVAL;
  			}
  			mac_proto = MAC_PROTO_NONE;
  			if (!validate_nsh(nla_data(a), false, true, true))
  				return -EINVAL;
  			break;
  
  		case OVS_ACTION_ATTR_POP_NSH: {
  			__be16 inner_proto;
  
  			if (eth_type != htons(ETH_P_NSH))
  				return -EINVAL;
  			inner_proto = tun_p_to_eth_p(key->nsh.base.np);
  			if (!inner_proto)
  				return -EINVAL;
  			if (key->nsh.base.np == TUN_P_ETHERNET)
  				mac_proto = MAC_PROTO_ETHERNET;
  			else
  				mac_proto = MAC_PROTO_NONE;
  			break;
  		}
cd8a6c336   Andy Zhou   openvswitch: Add ...
3139
3140
3141
  		case OVS_ACTION_ATTR_METER:
  			/* Non-existent meters are simply ignored.  */
  			break;
b23350403   Yifeng Sun   openvswitch: kern...
3142
3143
3144
3145
3146
  		case OVS_ACTION_ATTR_CLONE: {
  			bool last = nla_is_last(a, rem);
  
  			err = validate_and_copy_clone(net, a, key, sfa,
  						      eth_type, vlan_tci,
fbdcdd78d   Martin Varghese   Change in Openvsw...
3147
  						      mpls_label_count,
b23350403   Yifeng Sun   openvswitch: kern...
3148
3149
3150
3151
3152
3153
  						      log, last);
  			if (err)
  				return err;
  			skip_copy = true;
  			break;
  		}
4d5ec89fc   Numan Siddique   net: openvswitch:...
3154
3155
3156
3157
3158
  		case OVS_ACTION_ATTR_CHECK_PKT_LEN: {
  			bool last = nla_is_last(a, rem);
  
  			err = validate_and_copy_check_pkt_len(net, a, key, sfa,
  							      eth_type,
fbdcdd78d   Martin Varghese   Change in Openvsw...
3159
3160
3161
  							      vlan_tci,
  							      mpls_label_count,
  							      log, last);
4d5ec89fc   Numan Siddique   net: openvswitch:...
3162
3163
3164
3165
3166
  			if (err)
  				return err;
  			skip_copy = true;
  			break;
  		}
744676e77   Matteo Croce   openvswitch: add ...
3167
3168
3169
3170
3171
3172
3173
3174
  		case OVS_ACTION_ATTR_DEC_TTL:
  			err = validate_and_copy_dec_ttl(net, a, key, sfa,
  							eth_type, vlan_tci,
  							mpls_label_count, log);
  			if (err)
  				return err;
  			skip_copy = true;
  			break;
e64457191   Pravin B Shelar   openvswitch: Rest...
3175
  		default:
05da5898a   Jarno Rajahalme   openvswitch: Add ...
3176
  			OVS_NLERR(log, "Unknown Action type %d", type);
e64457191   Pravin B Shelar   openvswitch: Rest...
3177
3178
3179
  			return -EINVAL;
  		}
  		if (!skip_copy) {
05da5898a   Jarno Rajahalme   openvswitch: Add ...
3180
  			err = copy_action(a, sfa, log);
e64457191   Pravin B Shelar   openvswitch: Rest...
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
  			if (err)
  				return err;
  		}
  	}
  
  	if (rem > 0)
  		return -EINVAL;
  
  	return 0;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3191
  /* 'key' must be the masked key. */
7f8a436ea   Joe Stringer   openvswitch: Add ...
3192
  int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
25cd9ba0a   Simon Horman   openvswitch: Add ...
3193
  			 const struct sw_flow_key *key,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
3194
  			 struct sw_flow_actions **sfa, bool log)
25cd9ba0a   Simon Horman   openvswitch: Add ...
3195
  {
2fdb957d6   Pravin B Shelar   openvswitch: Refa...
3196
  	int err;
fbdcdd78d   Martin Varghese   Change in Openvsw...
3197
  	u32 mpls_label_count = 0;
2fdb957d6   Pravin B Shelar   openvswitch: Refa...
3198

67c8d22a7   zhangliping   openvswitch: fix ...
3199
  	*sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE));
2fdb957d6   Pravin B Shelar   openvswitch: Refa...
3200
3201
  	if (IS_ERR(*sfa))
  		return PTR_ERR(*sfa);
fbdcdd78d   Martin Varghese   Change in Openvsw...
3202
3203
  	if (eth_p_mpls(key->eth.type))
  		mpls_label_count = hweight_long(key->mpls.num_labels_mask);
8e2fed1c0   Joe Stringer   openvswitch: Seri...
3204
  	(*sfa)->orig_len = nla_len(attr);
798c16617   andy zhou   openvswitch: Opti...
3205
  	err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type,
fbdcdd78d   Martin Varghese   Change in Openvsw...
3206
  				     key->eth.vlan.tci, mpls_label_count, log);
2fdb957d6   Pravin B Shelar   openvswitch: Refa...
3207
  	if (err)
34ae932a4   Thomas Graf   openvswitch: Make...
3208
  		ovs_nla_free_flow_actions(*sfa);
2fdb957d6   Pravin B Shelar   openvswitch: Refa...
3209
3210
  
  	return err;
25cd9ba0a   Simon Horman   openvswitch: Add ...
3211
  }
798c16617   andy zhou   openvswitch: Opti...
3212
3213
  static int sample_action_to_attr(const struct nlattr *attr,
  				 struct sk_buff *skb)
e64457191   Pravin B Shelar   openvswitch: Rest...
3214
  {
798c16617   andy zhou   openvswitch: Opti...
3215
3216
3217
3218
  	struct nlattr *start, *ac_start = NULL, *sample_arg;
  	int err = 0, rem = nla_len(attr);
  	const struct sample_arg *arg;
  	struct nlattr *actions;
e64457191   Pravin B Shelar   openvswitch: Rest...
3219

ae0be8de9   Michal Kubecek   netlink: make nla...
3220
  	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SAMPLE);
e64457191   Pravin B Shelar   openvswitch: Rest...
3221
3222
  	if (!start)
  		return -EMSGSIZE;
798c16617   andy zhou   openvswitch: Opti...
3223
3224
3225
  	sample_arg = nla_data(attr);
  	arg = nla_data(sample_arg);
  	actions = nla_next(sample_arg, &rem);
e64457191   Pravin B Shelar   openvswitch: Rest...
3226

798c16617   andy zhou   openvswitch: Opti...
3227
3228
3229
3230
  	if (nla_put_u32(skb, OVS_SAMPLE_ATTR_PROBABILITY, arg->probability)) {
  		err = -EMSGSIZE;
  		goto out;
  	}
ae0be8de9   Michal Kubecek   netlink: make nla...
3231
  	ac_start = nla_nest_start_noflag(skb, OVS_SAMPLE_ATTR_ACTIONS);
798c16617   andy zhou   openvswitch: Opti...
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
  	if (!ac_start) {
  		err = -EMSGSIZE;
  		goto out;
  	}
  
  	err = ovs_nla_put_actions(actions, rem, skb);
  
  out:
  	if (err) {
  		nla_nest_cancel(skb, ac_start);
  		nla_nest_cancel(skb, start);
  	} else {
  		nla_nest_end(skb, ac_start);
  		nla_nest_end(skb, start);
e64457191   Pravin B Shelar   openvswitch: Rest...
3246
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
3247
3248
  	return err;
  }
b23350403   Yifeng Sun   openvswitch: kern...
3249
3250
3251
3252
3253
  static int clone_action_to_attr(const struct nlattr *attr,
  				struct sk_buff *skb)
  {
  	struct nlattr *start;
  	int err = 0, rem = nla_len(attr);
ae0be8de9   Michal Kubecek   netlink: make nla...
3254
  	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CLONE);
b23350403   Yifeng Sun   openvswitch: kern...
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
  	if (!start)
  		return -EMSGSIZE;
  
  	err = ovs_nla_put_actions(nla_data(attr), rem, skb);
  
  	if (err)
  		nla_nest_cancel(skb, start);
  	else
  		nla_nest_end(skb, start);
  
  	return err;
  }
4d5ec89fc   Numan Siddique   net: openvswitch:...
3267
3268
3269
3270
3271
3272
3273
  static int check_pkt_len_action_to_attr(const struct nlattr *attr,
  					struct sk_buff *skb)
  {
  	struct nlattr *start, *ac_start = NULL;
  	const struct check_pkt_len_arg *arg;
  	const struct nlattr *a, *cpl_arg;
  	int err = 0, rem = nla_len(attr);
ae0be8de9   Michal Kubecek   netlink: make nla...
3274
  	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CHECK_PKT_LEN);
4d5ec89fc   Numan Siddique   net: openvswitch:...
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
  	if (!start)
  		return -EMSGSIZE;
  
  	/* The first nested attribute in 'attr' is always
  	 * 'OVS_CHECK_PKT_LEN_ATTR_ARG'.
  	 */
  	cpl_arg = nla_data(attr);
  	arg = nla_data(cpl_arg);
  
  	if (nla_put_u16(skb, OVS_CHECK_PKT_LEN_ATTR_PKT_LEN, arg->pkt_len)) {
  		err = -EMSGSIZE;
  		goto out;
  	}
  
  	/* Second nested attribute in 'attr' is always
  	 * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL'.
  	 */
  	a = nla_next(cpl_arg, &rem);
ae0be8de9   Michal Kubecek   netlink: make nla...
3293
3294
  	ac_start =  nla_nest_start_noflag(skb,
  					  OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL);
4d5ec89fc   Numan Siddique   net: openvswitch:...
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
  	if (!ac_start) {
  		err = -EMSGSIZE;
  		goto out;
  	}
  
  	err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
  	if (err) {
  		nla_nest_cancel(skb, ac_start);
  		goto out;
  	} else {
  		nla_nest_end(skb, ac_start);
  	}
  
  	/* Third nested attribute in 'attr' is always
  	 * OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER.
  	 */
  	a = nla_next(a, &rem);
ae0be8de9   Michal Kubecek   netlink: make nla...
3312
3313
  	ac_start =  nla_nest_start_noflag(skb,
  					  OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER);
4d5ec89fc   Numan Siddique   net: openvswitch:...
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
  	if (!ac_start) {
  		err = -EMSGSIZE;
  		goto out;
  	}
  
  	err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
  	if (err) {
  		nla_nest_cancel(skb, ac_start);
  		goto out;
  	} else {
  		nla_nest_end(skb, ac_start);
  	}
  
  	nla_nest_end(skb, start);
  	return 0;
  
  out:
  	nla_nest_cancel(skb, start);
  	return err;
  }
744676e77   Matteo Croce   openvswitch: add ...
3334
3335
3336
  static int dec_ttl_action_to_attr(const struct nlattr *attr,
  				  struct sk_buff *skb)
  {
69929d4c4   Eelco Chaudron   net: openvswitch:...
3337
3338
3339
  	struct nlattr *start, *action_start;
  	const struct nlattr *a;
  	int err = 0, rem;
744676e77   Matteo Croce   openvswitch: add ...
3340
3341
  
  	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL);
744676e77   Matteo Croce   openvswitch: add ...
3342
3343
  	if (!start)
  		return -EMSGSIZE;
69929d4c4   Eelco Chaudron   net: openvswitch:...
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
  	nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) {
  		switch (nla_type(a)) {
  		case OVS_DEC_TTL_ATTR_ACTION:
  
  			action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION);
  			if (!action_start) {
  				err = -EMSGSIZE;
  				goto out;
  			}
  
  			err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
  			if (err)
  				goto out;
  
  			nla_nest_end(skb, action_start);
  			break;
744676e77   Matteo Croce   openvswitch: add ...
3360

69929d4c4   Eelco Chaudron   net: openvswitch:...
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
  		default:
  			/* Ignore all other option to be future compatible */
  			break;
  		}
  	}
  
  	nla_nest_end(skb, start);
  	return 0;
  
  out:
  	nla_nest_cancel(skb, start);
744676e77   Matteo Croce   openvswitch: add ...
3372
3373
  	return err;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
3374
3375
3376
3377
3378
3379
3380
3381
  static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
  {
  	const struct nlattr *ovs_key = nla_data(a);
  	int key_type = nla_type(ovs_key);
  	struct nlattr *start;
  	int err;
  
  	switch (key_type) {
f0b128c1e   Jesse Gross   openvswitch: Wrap...
3382
  	case OVS_KEY_ATTR_TUNNEL_INFO: {
34ae932a4   Thomas Graf   openvswitch: Make...
3383
3384
  		struct ovs_tunnel_info *ovs_tun = nla_data(ovs_key);
  		struct ip_tunnel_info *tun_info = &ovs_tun->tun_dst->u.tun_info;
f0b128c1e   Jesse Gross   openvswitch: Wrap...
3385

ae0be8de9   Michal Kubecek   netlink: make nla...
3386
  		start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET);
e64457191   Pravin B Shelar   openvswitch: Rest...
3387
3388
  		if (!start)
  			return -EMSGSIZE;
e905eabc9   Simon Horman   openvswitch: corr...
3389
3390
3391
  		err =  ip_tun_to_nlattr(skb, &tun_info->key,
  					ip_tunnel_info_opts(tun_info),
  					tun_info->options_len,
18b6f7174   wenxu   openvswitch: Make...
3392
  					ip_tunnel_info_af(tun_info), tun_info->mode);
e64457191   Pravin B Shelar   openvswitch: Rest...
3393
3394
3395
3396
  		if (err)
  			return err;
  		nla_nest_end(skb, start);
  		break;
f0b128c1e   Jesse Gross   openvswitch: Wrap...
3397
  	}
e64457191   Pravin B Shelar   openvswitch: Rest...
3398
3399
3400
3401
3402
3403
3404
3405
  	default:
  		if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
  			return -EMSGSIZE;
  		break;
  	}
  
  	return 0;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3406
3407
3408
3409
  static int masked_set_action_to_set_action_attr(const struct nlattr *a,
  						struct sk_buff *skb)
  {
  	const struct nlattr *ovs_key = nla_data(a);
f4f8e7385   Joe Stringer   openvswitch: Fix ...
3410
  	struct nlattr *nla;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3411
3412
3413
3414
3415
  	size_t key_len = nla_len(ovs_key) / 2;
  
  	/* Revert the conversion we did from a non-masked set action to
  	 * masked set action.
  	 */
ae0be8de9   Michal Kubecek   netlink: make nla...
3416
  	nla = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET);
f4f8e7385   Joe Stringer   openvswitch: Fix ...
3417
  	if (!nla)
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3418
  		return -EMSGSIZE;
f4f8e7385   Joe Stringer   openvswitch: Fix ...
3419
3420
3421
3422
  	if (nla_put(skb, nla_type(ovs_key), key_len, nla_data(ovs_key)))
  		return -EMSGSIZE;
  
  	nla_nest_end(skb, nla);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3423
3424
  	return 0;
  }
e64457191   Pravin B Shelar   openvswitch: Rest...
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
  int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb)
  {
  	const struct nlattr *a;
  	int rem, err;
  
  	nla_for_each_attr(a, attr, len, rem) {
  		int type = nla_type(a);
  
  		switch (type) {
  		case OVS_ACTION_ATTR_SET:
  			err = set_action_to_attr(a, skb);
  			if (err)
  				return err;
  			break;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
3439
3440
3441
3442
3443
  		case OVS_ACTION_ATTR_SET_TO_MASKED:
  			err = masked_set_action_to_set_action_attr(a, skb);
  			if (err)
  				return err;
  			break;
e64457191   Pravin B Shelar   openvswitch: Rest...
3444
3445
3446
3447
3448
  		case OVS_ACTION_ATTR_SAMPLE:
  			err = sample_action_to_attr(a, skb);
  			if (err)
  				return err;
  			break;
7f8a436ea   Joe Stringer   openvswitch: Add ...
3449
3450
3451
3452
3453
3454
  
  		case OVS_ACTION_ATTR_CT:
  			err = ovs_ct_action_to_attr(nla_data(a), skb);
  			if (err)
  				return err;
  			break;
b23350403   Yifeng Sun   openvswitch: kern...
3455
3456
3457
3458
3459
  		case OVS_ACTION_ATTR_CLONE:
  			err = clone_action_to_attr(a, skb);
  			if (err)
  				return err;
  			break;
4d5ec89fc   Numan Siddique   net: openvswitch:...
3460
3461
3462
3463
3464
  		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
  			err = check_pkt_len_action_to_attr(a, skb);
  			if (err)
  				return err;
  			break;
744676e77   Matteo Croce   openvswitch: add ...
3465
3466
3467
3468
3469
  		case OVS_ACTION_ATTR_DEC_TTL:
  			err = dec_ttl_action_to_attr(a, skb);
  			if (err)
  				return err;
  			break;
e64457191   Pravin B Shelar   openvswitch: Rest...
3470
3471
3472
3473
3474
3475
3476
3477
3478
  		default:
  			if (nla_put(skb, type, nla_len(a), nla_data(a)))
  				return -EMSGSIZE;
  			break;
  		}
  	}
  
  	return 0;
  }