xref: /linux/net/openvswitch/flow_netlink.c (revision 9410645520e9b820069761f3450ef6661418e279)
1c9422999SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e6445719SPravin B Shelar /*
3798c1661Sandy zhou  * Copyright (c) 2007-2017 Nicira, Inc.
4e6445719SPravin B Shelar  */
5e6445719SPravin B Shelar 
62235ad1cSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
72235ad1cSJoe Perches 
8e6445719SPravin B Shelar #include "flow.h"
9e6445719SPravin B Shelar #include "datapath.h"
10e6445719SPravin B Shelar #include <linux/uaccess.h>
11e6445719SPravin B Shelar #include <linux/netdevice.h>
12e6445719SPravin B Shelar #include <linux/etherdevice.h>
13e6445719SPravin B Shelar #include <linux/if_ether.h>
14e6445719SPravin B Shelar #include <linux/if_vlan.h>
15e6445719SPravin B Shelar #include <net/llc_pdu.h>
16e6445719SPravin B Shelar #include <linux/kernel.h>
17e6445719SPravin B Shelar #include <linux/jhash.h>
18e6445719SPravin B Shelar #include <linux/jiffies.h>
19e6445719SPravin B Shelar #include <linux/llc.h>
20e6445719SPravin B Shelar #include <linux/module.h>
21e6445719SPravin B Shelar #include <linux/in.h>
22e6445719SPravin B Shelar #include <linux/rcupdate.h>
23e6445719SPravin B Shelar #include <linux/if_arp.h>
24e6445719SPravin B Shelar #include <linux/ip.h>
25e6445719SPravin B Shelar #include <linux/ipv6.h>
26e6445719SPravin B Shelar #include <linux/sctp.h>
27e6445719SPravin B Shelar #include <linux/tcp.h>
28e6445719SPravin B Shelar #include <linux/udp.h>
29e6445719SPravin B Shelar #include <linux/icmp.h>
30e6445719SPravin B Shelar #include <linux/icmpv6.h>
31e6445719SPravin B Shelar #include <linux/rculist.h>
32f5796684SJesse Gross #include <net/geneve.h>
33e6445719SPravin B Shelar #include <net/ip.h>
34e6445719SPravin B Shelar #include <net/ipv6.h>
35e6445719SPravin B Shelar #include <net/ndisc.h>
3625cd9ba0SSimon Horman #include <net/mpls.h>
37614732eaSThomas Graf #include <net/vxlan.h>
38b2d0f5d5SYi Yang #include <net/tun_proto.h>
39fc1372f8SWilliam Tu #include <net/erspan.h>
40e6445719SPravin B Shelar 
41e7bc7db9SEric Garver #include "drop.h"
42e6445719SPravin B Shelar #include "flow_netlink.h"
43e6445719SPravin B Shelar 
4481bfe3c3SThomas Graf struct ovs_len_tbl {
4581bfe3c3SThomas Graf 	int len;
4681bfe3c3SThomas Graf 	const struct ovs_len_tbl *next;
4781bfe3c3SThomas Graf };
4881bfe3c3SThomas Graf 
4981bfe3c3SThomas Graf #define OVS_ATTR_NESTED -1
50982b5270SJesse Gross #define OVS_ATTR_VARIABLE -2
516e2f90d3SAaron Conole #define OVS_COPY_ACTIONS_MAX_DEPTH 16
5281bfe3c3SThomas Graf 
actions_may_change_flow(const struct nlattr * actions)53798c1661Sandy zhou static bool actions_may_change_flow(const struct nlattr *actions)
54798c1661Sandy zhou {
55798c1661Sandy zhou 	struct nlattr *nla;
56798c1661Sandy zhou 	int rem;
57798c1661Sandy zhou 
58798c1661Sandy zhou 	nla_for_each_nested(nla, actions, rem) {
59798c1661Sandy zhou 		u16 action = nla_type(nla);
60798c1661Sandy zhou 
61798c1661Sandy zhou 		switch (action) {
62798c1661Sandy zhou 		case OVS_ACTION_ATTR_OUTPUT:
63798c1661Sandy zhou 		case OVS_ACTION_ATTR_RECIRC:
64798c1661Sandy zhou 		case OVS_ACTION_ATTR_TRUNC:
65798c1661Sandy zhou 		case OVS_ACTION_ATTR_USERSPACE:
66e7bc7db9SEric Garver 		case OVS_ACTION_ATTR_DROP:
67aae0b82bSAdrian Moreno 		case OVS_ACTION_ATTR_PSAMPLE:
68798c1661Sandy zhou 			break;
69798c1661Sandy zhou 
70798c1661Sandy zhou 		case OVS_ACTION_ATTR_CT:
71b8226962SEric Garver 		case OVS_ACTION_ATTR_CT_CLEAR:
72798c1661Sandy zhou 		case OVS_ACTION_ATTR_HASH:
73798c1661Sandy zhou 		case OVS_ACTION_ATTR_POP_ETH:
74798c1661Sandy zhou 		case OVS_ACTION_ATTR_POP_MPLS:
75b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_POP_NSH:
76798c1661Sandy zhou 		case OVS_ACTION_ATTR_POP_VLAN:
77798c1661Sandy zhou 		case OVS_ACTION_ATTR_PUSH_ETH:
78798c1661Sandy zhou 		case OVS_ACTION_ATTR_PUSH_MPLS:
79b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_PUSH_NSH:
80798c1661Sandy zhou 		case OVS_ACTION_ATTR_PUSH_VLAN:
81798c1661Sandy zhou 		case OVS_ACTION_ATTR_SAMPLE:
82798c1661Sandy zhou 		case OVS_ACTION_ATTR_SET:
83798c1661Sandy zhou 		case OVS_ACTION_ATTR_SET_MASKED:
84cd8a6c33SAndy Zhou 		case OVS_ACTION_ATTR_METER:
854d5ec89fSNuman Siddique 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
86f66b53fdSMartin Varghese 		case OVS_ACTION_ATTR_ADD_MPLS:
87744676e7SMatteo Croce 		case OVS_ACTION_ATTR_DEC_TTL:
88798c1661Sandy zhou 		default:
89798c1661Sandy zhou 			return true;
90798c1661Sandy zhou 		}
91798c1661Sandy zhou 	}
92798c1661Sandy zhou 	return false;
93798c1661Sandy zhou }
94798c1661Sandy zhou 
update_range(struct sw_flow_match * match,size_t offset,size_t size,bool is_mask)95a85311bfSPravin B Shelar static void update_range(struct sw_flow_match *match,
96e6445719SPravin B Shelar 			 size_t offset, size_t size, bool is_mask)
97e6445719SPravin B Shelar {
98a85311bfSPravin B Shelar 	struct sw_flow_key_range *range;
99e6445719SPravin B Shelar 	size_t start = rounddown(offset, sizeof(long));
100e6445719SPravin B Shelar 	size_t end = roundup(offset + size, sizeof(long));
101e6445719SPravin B Shelar 
102e6445719SPravin B Shelar 	if (!is_mask)
103e6445719SPravin B Shelar 		range = &match->range;
104a85311bfSPravin B Shelar 	else
105e6445719SPravin B Shelar 		range = &match->mask->range;
106e6445719SPravin B Shelar 
107e6445719SPravin B Shelar 	if (range->start == range->end) {
108e6445719SPravin B Shelar 		range->start = start;
109e6445719SPravin B Shelar 		range->end = end;
110e6445719SPravin B Shelar 		return;
111e6445719SPravin B Shelar 	}
112e6445719SPravin B Shelar 
113e6445719SPravin B Shelar 	if (range->start > start)
114e6445719SPravin B Shelar 		range->start = start;
115e6445719SPravin B Shelar 
116e6445719SPravin B Shelar 	if (range->end < end)
117e6445719SPravin B Shelar 		range->end = end;
118e6445719SPravin B Shelar }
119e6445719SPravin B Shelar 
120e6445719SPravin B Shelar #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
121e6445719SPravin B Shelar 	do { \
122a85311bfSPravin B Shelar 		update_range(match, offsetof(struct sw_flow_key, field),    \
123e6445719SPravin B Shelar 			     sizeof((match)->key->field), is_mask);	    \
124a85311bfSPravin B Shelar 		if (is_mask)						    \
125e6445719SPravin B Shelar 			(match)->mask->key.field = value;		    \
126a85311bfSPravin B Shelar 		else							    \
127e6445719SPravin B Shelar 			(match)->key->field = value;		            \
128e6445719SPravin B Shelar 	} while (0)
129e6445719SPravin B Shelar 
130f5796684SJesse Gross #define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask)	    \
131e6445719SPravin B Shelar 	do {								    \
132a85311bfSPravin B Shelar 		update_range(match, offset, len, is_mask);		    \
133f5796684SJesse Gross 		if (is_mask)						    \
134f5796684SJesse Gross 			memcpy((u8 *)&(match)->mask->key + offset, value_p, \
135f5796684SJesse Gross 			       len);					   \
136f5796684SJesse Gross 		else							    \
137f5796684SJesse Gross 			memcpy((u8 *)(match)->key + offset, value_p, len);  \
138e6445719SPravin B Shelar 	} while (0)
139e6445719SPravin B Shelar 
140f5796684SJesse Gross #define SW_FLOW_KEY_MEMCPY(match, field, value_p, len, is_mask)		      \
141f5796684SJesse Gross 	SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \
142f5796684SJesse Gross 				  value_p, len, is_mask)
143f5796684SJesse Gross 
144f47de068SPravin B Shelar #define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask)		    \
145f47de068SPravin B Shelar 	do {								    \
146a85311bfSPravin B Shelar 		update_range(match, offsetof(struct sw_flow_key, field),    \
147f47de068SPravin B Shelar 			     sizeof((match)->key->field), is_mask);	    \
148a85311bfSPravin B Shelar 		if (is_mask)						    \
149f47de068SPravin B Shelar 			memset((u8 *)&(match)->mask->key.field, value,      \
150f47de068SPravin B Shelar 			       sizeof((match)->mask->key.field));	    \
151a85311bfSPravin B Shelar 		else							    \
152f47de068SPravin B Shelar 			memset((u8 *)&(match)->key->field, value,           \
153f47de068SPravin B Shelar 			       sizeof((match)->key->field));                \
154f47de068SPravin B Shelar 	} while (0)
155e6445719SPravin B Shelar 
1565832c4a7SAlexander Lobakin #define SW_FLOW_KEY_BITMAP_COPY(match, field, value_p, nbits, is_mask) ({     \
1575832c4a7SAlexander Lobakin 	update_range(match, offsetof(struct sw_flow_key, field),	      \
1585832c4a7SAlexander Lobakin 		     bitmap_size(nbits), is_mask);			      \
1595832c4a7SAlexander Lobakin 	bitmap_copy(is_mask ? (match)->mask->key.field : (match)->key->field, \
1605832c4a7SAlexander Lobakin 		    value_p, nbits);					      \
1615832c4a7SAlexander Lobakin })
1625832c4a7SAlexander Lobakin 
match_validate(const struct sw_flow_match * match,u64 key_attrs,u64 mask_attrs,bool log)163e6445719SPravin B Shelar static bool match_validate(const struct sw_flow_match *match,
16405da5898SJarno Rajahalme 			   u64 key_attrs, u64 mask_attrs, bool log)
165e6445719SPravin B Shelar {
1660a6410fbSJiri Benc 	u64 key_expected = 0;
167e6445719SPravin B Shelar 	u64 mask_allowed = key_attrs;  /* At most allow all key attributes */
168e6445719SPravin B Shelar 
169e6445719SPravin B Shelar 	/* The following mask attributes allowed only if they
170e6445719SPravin B Shelar 	 * pass the validation tests. */
171e6445719SPravin B Shelar 	mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4)
1729dd7f890SJarno Rajahalme 			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)
173e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_IPV6)
1749dd7f890SJarno Rajahalme 			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)
175e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_TCP)
1765eb26b15SJarno Rajahalme 			| (1 << OVS_KEY_ATTR_TCP_FLAGS)
177e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_UDP)
178e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_SCTP)
179e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_ICMP)
180e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_ICMPV6)
181e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_ARP)
18225cd9ba0SSimon Horman 			| (1 << OVS_KEY_ATTR_ND)
183b2d0f5d5SYi Yang 			| (1 << OVS_KEY_ATTR_MPLS)
184b2d0f5d5SYi Yang 			| (1 << OVS_KEY_ATTR_NSH));
185e6445719SPravin B Shelar 
186e6445719SPravin B Shelar 	/* Always allowed mask fields. */
187e6445719SPravin B Shelar 	mask_allowed |= ((1 << OVS_KEY_ATTR_TUNNEL)
188e6445719SPravin B Shelar 		       | (1 << OVS_KEY_ATTR_IN_PORT)
189e6445719SPravin B Shelar 		       | (1 << OVS_KEY_ATTR_ETHERTYPE));
190e6445719SPravin B Shelar 
191e6445719SPravin B Shelar 	/* Check key attributes. */
192e6445719SPravin B Shelar 	if (match->key->eth.type == htons(ETH_P_ARP)
193e6445719SPravin B Shelar 			|| match->key->eth.type == htons(ETH_P_RARP)) {
194e6445719SPravin B Shelar 		key_expected |= 1 << OVS_KEY_ATTR_ARP;
195f2a01517SPravin B Shelar 		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
196e6445719SPravin B Shelar 			mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
197e6445719SPravin B Shelar 	}
198e6445719SPravin B Shelar 
19925cd9ba0SSimon Horman 	if (eth_p_mpls(match->key->eth.type)) {
20025cd9ba0SSimon Horman 		key_expected |= 1 << OVS_KEY_ATTR_MPLS;
20125cd9ba0SSimon Horman 		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
20225cd9ba0SSimon Horman 			mask_allowed |= 1 << OVS_KEY_ATTR_MPLS;
20325cd9ba0SSimon Horman 	}
20425cd9ba0SSimon Horman 
205e6445719SPravin B Shelar 	if (match->key->eth.type == htons(ETH_P_IP)) {
206e6445719SPravin B Shelar 		key_expected |= 1 << OVS_KEY_ATTR_IPV4;
2079dd7f890SJarno Rajahalme 		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {
208e6445719SPravin B Shelar 			mask_allowed |= 1 << OVS_KEY_ATTR_IPV4;
2099dd7f890SJarno Rajahalme 			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4;
2109dd7f890SJarno Rajahalme 		}
211e6445719SPravin B Shelar 
212e6445719SPravin B Shelar 		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
213e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_UDP) {
214e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_UDP;
215e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
216e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
217e6445719SPravin B Shelar 			}
218e6445719SPravin B Shelar 
219e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_SCTP) {
220e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
221e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
222e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
223e6445719SPravin B Shelar 			}
224e6445719SPravin B Shelar 
225e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_TCP) {
226e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_TCP;
2275eb26b15SJarno Rajahalme 				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2285eb26b15SJarno Rajahalme 				if (match->mask && (match->mask->key.ip.proto == 0xff)) {
229e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
2305eb26b15SJarno Rajahalme 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2315eb26b15SJarno Rajahalme 				}
232e6445719SPravin B Shelar 			}
233e6445719SPravin B Shelar 
234e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_ICMP) {
235e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_ICMP;
236e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
237e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_ICMP;
238e6445719SPravin B Shelar 			}
239e6445719SPravin B Shelar 		}
240e6445719SPravin B Shelar 	}
241e6445719SPravin B Shelar 
242e6445719SPravin B Shelar 	if (match->key->eth.type == htons(ETH_P_IPV6)) {
243e6445719SPravin B Shelar 		key_expected |= 1 << OVS_KEY_ATTR_IPV6;
2449dd7f890SJarno Rajahalme 		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {
245e6445719SPravin B Shelar 			mask_allowed |= 1 << OVS_KEY_ATTR_IPV6;
2469dd7f890SJarno Rajahalme 			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6;
2479dd7f890SJarno Rajahalme 		}
248e6445719SPravin B Shelar 
249e6445719SPravin B Shelar 		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
250e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_UDP) {
251e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_UDP;
252e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
253e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
254e6445719SPravin B Shelar 			}
255e6445719SPravin B Shelar 
256e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_SCTP) {
257e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
258e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
259e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
260e6445719SPravin B Shelar 			}
261e6445719SPravin B Shelar 
262e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_TCP) {
263e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_TCP;
2645eb26b15SJarno Rajahalme 				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2655eb26b15SJarno Rajahalme 				if (match->mask && (match->mask->key.ip.proto == 0xff)) {
266e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
2675eb26b15SJarno Rajahalme 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2685eb26b15SJarno Rajahalme 				}
269e6445719SPravin B Shelar 			}
270e6445719SPravin B Shelar 
271e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_ICMPV6) {
272e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_ICMPV6;
273e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
274e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6;
275e6445719SPravin B Shelar 
2761139e241SJarno Rajahalme 				if (match->key->tp.src ==
277e6445719SPravin B Shelar 						htons(NDISC_NEIGHBOUR_SOLICITATION) ||
2781139e241SJarno Rajahalme 				    match->key->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
279e6445719SPravin B Shelar 					key_expected |= 1 << OVS_KEY_ATTR_ND;
2809dd7f890SJarno Rajahalme 					/* Original direction conntrack tuple
2819dd7f890SJarno Rajahalme 					 * uses the same space as the ND fields
2829dd7f890SJarno Rajahalme 					 * in the key, so both are not allowed
2839dd7f890SJarno Rajahalme 					 * at the same time.
2849dd7f890SJarno Rajahalme 					 */
2859dd7f890SJarno Rajahalme 					mask_allowed &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
286f2a01517SPravin B Shelar 					if (match->mask && (match->mask->key.tp.src == htons(0xff)))
287e6445719SPravin B Shelar 						mask_allowed |= 1 << OVS_KEY_ATTR_ND;
288e6445719SPravin B Shelar 				}
289e6445719SPravin B Shelar 			}
290e6445719SPravin B Shelar 		}
291e6445719SPravin B Shelar 	}
292e6445719SPravin B Shelar 
293b2d0f5d5SYi Yang 	if (match->key->eth.type == htons(ETH_P_NSH)) {
294b2d0f5d5SYi Yang 		key_expected |= 1 << OVS_KEY_ATTR_NSH;
295b2d0f5d5SYi Yang 		if (match->mask &&
296b2d0f5d5SYi Yang 		    match->mask->key.eth.type == htons(0xffff)) {
297b2d0f5d5SYi Yang 			mask_allowed |= 1 << OVS_KEY_ATTR_NSH;
298b2d0f5d5SYi Yang 		}
299b2d0f5d5SYi Yang 	}
300b2d0f5d5SYi Yang 
301e6445719SPravin B Shelar 	if ((key_attrs & key_expected) != key_expected) {
302e6445719SPravin B Shelar 		/* Key attributes check failed. */
30305da5898SJarno Rajahalme 		OVS_NLERR(log, "Missing key (keys=%llx, expected=%llx)",
30405da5898SJarno Rajahalme 			  (unsigned long long)key_attrs,
30505da5898SJarno Rajahalme 			  (unsigned long long)key_expected);
306e6445719SPravin B Shelar 		return false;
307e6445719SPravin B Shelar 	}
308e6445719SPravin B Shelar 
309e6445719SPravin B Shelar 	if ((mask_attrs & mask_allowed) != mask_attrs) {
310e6445719SPravin B Shelar 		/* Mask attributes check failed. */
31105da5898SJarno Rajahalme 		OVS_NLERR(log, "Unexpected mask (mask=%llx, allowed=%llx)",
31205da5898SJarno Rajahalme 			  (unsigned long long)mask_attrs,
31305da5898SJarno Rajahalme 			  (unsigned long long)mask_allowed);
314e6445719SPravin B Shelar 		return false;
315e6445719SPravin B Shelar 	}
316e6445719SPravin B Shelar 
317e6445719SPravin B Shelar 	return true;
318e6445719SPravin B Shelar }
319e6445719SPravin B Shelar 
ovs_tun_key_attr_size(void)3208f0aad6fSWenyu Zhang size_t ovs_tun_key_attr_size(void)
3218f0aad6fSWenyu Zhang {
3228f0aad6fSWenyu Zhang 	/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
3238f0aad6fSWenyu Zhang 	 * updating this function.
3248f0aad6fSWenyu Zhang 	 */
325b46f6dedSNicolas Dichtel 	return    nla_total_size_64bit(8) /* OVS_TUNNEL_KEY_ATTR_ID */
3266b26ba3aSJiri Benc 		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */
3276b26ba3aSJiri Benc 		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */
3288f0aad6fSWenyu Zhang 		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */
3298f0aad6fSWenyu Zhang 		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TTL */
3308f0aad6fSWenyu Zhang 		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
3318f0aad6fSWenyu Zhang 		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_CSUM */
3328f0aad6fSWenyu Zhang 		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_OAM */
3338f0aad6fSWenyu Zhang 		+ nla_total_size(256)  /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
334fc1372f8SWilliam Tu 		/* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and
335fc1372f8SWilliam Tu 		 * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with
3361dd144cfSThomas Graf 		 * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.
3371dd144cfSThomas Graf 		 */
3388f0aad6fSWenyu Zhang 		+ nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
33995a33208SWilliam Tu 		+ nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
3408f0aad6fSWenyu Zhang }
3418f0aad6fSWenyu Zhang 
ovs_nsh_key_attr_size(void)34206c2351fSWei Yongjun static size_t ovs_nsh_key_attr_size(void)
343b2d0f5d5SYi Yang {
344b2d0f5d5SYi Yang 	/* Whenever adding new OVS_NSH_KEY_ FIELDS, we should consider
345b2d0f5d5SYi Yang 	 * updating this function.
346b2d0f5d5SYi Yang 	 */
347b2d0f5d5SYi Yang 	return  nla_total_size(NSH_BASE_HDR_LEN) /* OVS_NSH_KEY_ATTR_BASE */
348b2d0f5d5SYi Yang 		/* OVS_NSH_KEY_ATTR_MD1 and OVS_NSH_KEY_ATTR_MD2 are
349b2d0f5d5SYi Yang 		 * mutually exclusive, so the bigger one can cover
350b2d0f5d5SYi Yang 		 * the small one.
351b2d0f5d5SYi Yang 		 */
352b2d0f5d5SYi Yang 		+ nla_total_size(NSH_CTX_HDRS_MAX_LEN);
353b2d0f5d5SYi Yang }
354b2d0f5d5SYi Yang 
ovs_key_attr_size(void)35541af73e9SJoe Stringer size_t ovs_key_attr_size(void)
35641af73e9SJoe Stringer {
35741af73e9SJoe Stringer 	/* Whenever adding new OVS_KEY_ FIELDS, we should consider
35841af73e9SJoe Stringer 	 * updating this function.
35941af73e9SJoe Stringer 	 */
3601926407aSIlya Maximets 	BUILD_BUG_ON(OVS_KEY_ATTR_MAX != 32);
36141af73e9SJoe Stringer 
36241af73e9SJoe Stringer 	return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */
36341af73e9SJoe Stringer 		+ nla_total_size(0)   /* OVS_KEY_ATTR_TUNNEL */
3648f0aad6fSWenyu Zhang 		  + ovs_tun_key_attr_size()
36541af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_IN_PORT */
36641af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */
36741af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */
36841af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */
369fbccce59SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_STATE */
3707f8a436eSJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_CT_ZONE */
371182e3042SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_MARK */
37233db4125SJoe Stringer 		+ nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABELS */
3739dd7f890SJarno Rajahalme 		+ nla_total_size(40)  /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */
374b2d0f5d5SYi Yang 		+ nla_total_size(0)   /* OVS_KEY_ATTR_NSH */
375b2d0f5d5SYi Yang 		  + ovs_nsh_key_attr_size()
37641af73e9SJoe Stringer 		+ nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
37741af73e9SJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
37841af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
37941af73e9SJoe Stringer 		+ nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */
38041af73e9SJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
38141af73e9SJoe Stringer 		+ nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */
38241af73e9SJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */
38328a3f060SToms Atteka 		+ nla_total_size(28)  /* OVS_KEY_ATTR_ND */
38428a3f060SToms Atteka 		+ nla_total_size(2);  /* OVS_KEY_ATTR_IPV6_EXTHDRS */
38541af73e9SJoe Stringer }
38641af73e9SJoe Stringer 
387982b5270SJesse Gross static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
388982b5270SJesse Gross 	[OVS_VXLAN_EXT_GBP]	    = { .len = sizeof(u32) },
389982b5270SJesse Gross };
390982b5270SJesse Gross 
39181bfe3c3SThomas Graf static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
39281bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_ID]	    = { .len = sizeof(u64) },
39381bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]	    = { .len = sizeof(u32) },
39481bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_IPV4_DST]	    = { .len = sizeof(u32) },
39581bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TOS]	    = { .len = 1 },
39681bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TTL]	    = { .len = 1 },
39781bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = { .len = 0 },
39881bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_CSUM]	    = { .len = 0 },
39981bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TP_SRC]	    = { .len = sizeof(u16) },
40081bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TP_DST]	    = { .len = sizeof(u16) },
40181bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_OAM]	    = { .len = 0 },
402982b5270SJesse Gross 	[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = OVS_ATTR_VARIABLE },
403982b5270SJesse Gross 	[OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = OVS_ATTR_NESTED,
404982b5270SJesse Gross 						.next = ovs_vxlan_ext_key_lens },
4056b26ba3aSJiri Benc 	[OVS_TUNNEL_KEY_ATTR_IPV6_SRC]      = { .len = sizeof(struct in6_addr) },
4066b26ba3aSJiri Benc 	[OVS_TUNNEL_KEY_ATTR_IPV6_DST]      = { .len = sizeof(struct in6_addr) },
407fc1372f8SWilliam Tu 	[OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS]   = { .len = OVS_ATTR_VARIABLE },
40818b6f717Swenxu 	[OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE]   = { .len = 0 },
40981bfe3c3SThomas Graf };
41081bfe3c3SThomas Graf 
411b2d0f5d5SYi Yang static const struct ovs_len_tbl
412b2d0f5d5SYi Yang ovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
413b2d0f5d5SYi Yang 	[OVS_NSH_KEY_ATTR_BASE] = { .len = sizeof(struct ovs_nsh_key_base) },
414b2d0f5d5SYi Yang 	[OVS_NSH_KEY_ATTR_MD1]  = { .len = sizeof(struct ovs_nsh_key_md1) },
415b2d0f5d5SYi Yang 	[OVS_NSH_KEY_ATTR_MD2]  = { .len = OVS_ATTR_VARIABLE },
416b2d0f5d5SYi Yang };
417b2d0f5d5SYi Yang 
418e6445719SPravin B Shelar /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
41981bfe3c3SThomas Graf static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
42081bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ENCAP]	 = { .len = OVS_ATTR_NESTED },
42181bfe3c3SThomas Graf 	[OVS_KEY_ATTR_PRIORITY]	 = { .len = sizeof(u32) },
42281bfe3c3SThomas Graf 	[OVS_KEY_ATTR_IN_PORT]	 = { .len = sizeof(u32) },
42381bfe3c3SThomas Graf 	[OVS_KEY_ATTR_SKB_MARK]	 = { .len = sizeof(u32) },
42481bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ETHERNET]	 = { .len = sizeof(struct ovs_key_ethernet) },
42581bfe3c3SThomas Graf 	[OVS_KEY_ATTR_VLAN]	 = { .len = sizeof(__be16) },
42681bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
42781bfe3c3SThomas Graf 	[OVS_KEY_ATTR_IPV4]	 = { .len = sizeof(struct ovs_key_ipv4) },
42881bfe3c3SThomas Graf 	[OVS_KEY_ATTR_IPV6]	 = { .len = sizeof(struct ovs_key_ipv6) },
42981bfe3c3SThomas Graf 	[OVS_KEY_ATTR_TCP]	 = { .len = sizeof(struct ovs_key_tcp) },
43081bfe3c3SThomas Graf 	[OVS_KEY_ATTR_TCP_FLAGS] = { .len = sizeof(__be16) },
43181bfe3c3SThomas Graf 	[OVS_KEY_ATTR_UDP]	 = { .len = sizeof(struct ovs_key_udp) },
43281bfe3c3SThomas Graf 	[OVS_KEY_ATTR_SCTP]	 = { .len = sizeof(struct ovs_key_sctp) },
43381bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ICMP]	 = { .len = sizeof(struct ovs_key_icmp) },
43481bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ICMPV6]	 = { .len = sizeof(struct ovs_key_icmpv6) },
43581bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ARP]	 = { .len = sizeof(struct ovs_key_arp) },
43681bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ND]	 = { .len = sizeof(struct ovs_key_nd) },
43781bfe3c3SThomas Graf 	[OVS_KEY_ATTR_RECIRC_ID] = { .len = sizeof(u32) },
43881bfe3c3SThomas Graf 	[OVS_KEY_ATTR_DP_HASH]	 = { .len = sizeof(u32) },
43981bfe3c3SThomas Graf 	[OVS_KEY_ATTR_TUNNEL]	 = { .len = OVS_ATTR_NESTED,
44081bfe3c3SThomas Graf 				     .next = ovs_tunnel_key_lens, },
441fbdcdd78SMartin Varghese 	[OVS_KEY_ATTR_MPLS]	 = { .len = OVS_ATTR_VARIABLE },
442fbccce59SJoe Stringer 	[OVS_KEY_ATTR_CT_STATE]	 = { .len = sizeof(u32) },
4437f8a436eSJoe Stringer 	[OVS_KEY_ATTR_CT_ZONE]	 = { .len = sizeof(u16) },
444182e3042SJoe Stringer 	[OVS_KEY_ATTR_CT_MARK]	 = { .len = sizeof(u32) },
44533db4125SJoe Stringer 	[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
4469dd7f890SJarno Rajahalme 	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4] = {
4479dd7f890SJarno Rajahalme 		.len = sizeof(struct ovs_key_ct_tuple_ipv4) },
4489dd7f890SJarno Rajahalme 	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {
4499dd7f890SJarno Rajahalme 		.len = sizeof(struct ovs_key_ct_tuple_ipv6) },
450b2d0f5d5SYi Yang 	[OVS_KEY_ATTR_NSH]       = { .len = OVS_ATTR_NESTED,
451b2d0f5d5SYi Yang 				     .next = ovs_nsh_key_attr_lens, },
45228a3f060SToms Atteka 	[OVS_KEY_ATTR_IPV6_EXTHDRS] = {
45328a3f060SToms Atteka 		.len = sizeof(struct ovs_key_ipv6_exthdrs) },
454e6445719SPravin B Shelar };
455e6445719SPravin B Shelar 
check_attr_len(unsigned int attr_len,unsigned int expected_len)456982b5270SJesse Gross static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
457982b5270SJesse Gross {
458982b5270SJesse Gross 	return expected_len == attr_len ||
459982b5270SJesse Gross 	       expected_len == OVS_ATTR_NESTED ||
460982b5270SJesse Gross 	       expected_len == OVS_ATTR_VARIABLE;
461982b5270SJesse Gross }
462982b5270SJesse Gross 
is_all_zero(const u8 * fp,size_t size)463e6445719SPravin B Shelar static bool is_all_zero(const u8 *fp, size_t size)
464e6445719SPravin B Shelar {
465e6445719SPravin B Shelar 	int i;
466e6445719SPravin B Shelar 
467e6445719SPravin B Shelar 	if (!fp)
468e6445719SPravin B Shelar 		return false;
469e6445719SPravin B Shelar 
470e6445719SPravin B Shelar 	for (i = 0; i < size; i++)
471e6445719SPravin B Shelar 		if (fp[i])
472e6445719SPravin B Shelar 			return false;
473e6445719SPravin B Shelar 
474e6445719SPravin B Shelar 	return true;
475e6445719SPravin B Shelar }
476e6445719SPravin B Shelar 
__parse_flow_nlattrs(const struct nlattr * attr,const struct nlattr * a[],u64 * attrsp,bool log,bool nz)477e6445719SPravin B Shelar static int __parse_flow_nlattrs(const struct nlattr *attr,
478e6445719SPravin B Shelar 				const struct nlattr *a[],
47905da5898SJarno Rajahalme 				u64 *attrsp, bool log, bool nz)
480e6445719SPravin B Shelar {
481e6445719SPravin B Shelar 	const struct nlattr *nla;
482e6445719SPravin B Shelar 	u64 attrs;
483e6445719SPravin B Shelar 	int rem;
484e6445719SPravin B Shelar 
485e6445719SPravin B Shelar 	attrs = *attrsp;
486e6445719SPravin B Shelar 	nla_for_each_nested(nla, attr, rem) {
487e6445719SPravin B Shelar 		u16 type = nla_type(nla);
488e6445719SPravin B Shelar 		int expected_len;
489e6445719SPravin B Shelar 
490e6445719SPravin B Shelar 		if (type > OVS_KEY_ATTR_MAX) {
49105da5898SJarno Rajahalme 			OVS_NLERR(log, "Key type %d is out of range max %d",
492e6445719SPravin B Shelar 				  type, OVS_KEY_ATTR_MAX);
493e6445719SPravin B Shelar 			return -EINVAL;
494e6445719SPravin B Shelar 		}
495e6445719SPravin B Shelar 
4961926407aSIlya Maximets 		if (type == OVS_KEY_ATTR_PACKET_TYPE ||
4971926407aSIlya Maximets 		    type == OVS_KEY_ATTR_ND_EXTENSIONS ||
4981926407aSIlya Maximets 		    type == OVS_KEY_ATTR_TUNNEL_INFO) {
4991926407aSIlya Maximets 			OVS_NLERR(log, "Key type %d is not supported", type);
5001926407aSIlya Maximets 			return -EINVAL;
5011926407aSIlya Maximets 		}
5021926407aSIlya Maximets 
5031926407aSIlya Maximets 		if (attrs & (1ULL << type)) {
50405da5898SJarno Rajahalme 			OVS_NLERR(log, "Duplicate key (type %d).", type);
505e6445719SPravin B Shelar 			return -EINVAL;
506e6445719SPravin B Shelar 		}
507e6445719SPravin B Shelar 
50881bfe3c3SThomas Graf 		expected_len = ovs_key_lens[type].len;
509982b5270SJesse Gross 		if (!check_attr_len(nla_len(nla), expected_len)) {
51005da5898SJarno Rajahalme 			OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
51105da5898SJarno Rajahalme 				  type, nla_len(nla), expected_len);
512e6445719SPravin B Shelar 			return -EINVAL;
513e6445719SPravin B Shelar 		}
514e6445719SPravin B Shelar 
51504a4af33SRoss Lagerwall 		if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
5161926407aSIlya Maximets 			attrs |= 1ULL << type;
517e6445719SPravin B Shelar 			a[type] = nla;
518e6445719SPravin B Shelar 		}
519e6445719SPravin B Shelar 	}
520e6445719SPravin B Shelar 	if (rem) {
52105da5898SJarno Rajahalme 		OVS_NLERR(log, "Message has %d unknown bytes.", rem);
522e6445719SPravin B Shelar 		return -EINVAL;
523e6445719SPravin B Shelar 	}
524e6445719SPravin B Shelar 
525e6445719SPravin B Shelar 	*attrsp = attrs;
526e6445719SPravin B Shelar 	return 0;
527e6445719SPravin B Shelar }
528e6445719SPravin B Shelar 
parse_flow_mask_nlattrs(const struct nlattr * attr,const struct nlattr * a[],u64 * attrsp,bool log)529e6445719SPravin B Shelar static int parse_flow_mask_nlattrs(const struct nlattr *attr,
53005da5898SJarno Rajahalme 				   const struct nlattr *a[], u64 *attrsp,
53105da5898SJarno Rajahalme 				   bool log)
532e6445719SPravin B Shelar {
53305da5898SJarno Rajahalme 	return __parse_flow_nlattrs(attr, a, attrsp, log, true);
534e6445719SPravin B Shelar }
535e6445719SPravin B Shelar 
parse_flow_nlattrs(const struct nlattr * attr,const struct nlattr * a[],u64 * attrsp,bool log)5369dd7f890SJarno Rajahalme int parse_flow_nlattrs(const struct nlattr *attr, const struct nlattr *a[],
5379dd7f890SJarno Rajahalme 		       u64 *attrsp, bool log)
538e6445719SPravin B Shelar {
53905da5898SJarno Rajahalme 	return __parse_flow_nlattrs(attr, a, attrsp, log, false);
54005da5898SJarno Rajahalme }
54105da5898SJarno Rajahalme 
genev_tun_opt_from_nlattr(const struct nlattr * a,struct sw_flow_match * match,bool is_mask,bool log)54205da5898SJarno Rajahalme static int genev_tun_opt_from_nlattr(const struct nlattr *a,
54305da5898SJarno Rajahalme 				     struct sw_flow_match *match, bool is_mask,
54405da5898SJarno Rajahalme 				     bool log)
54505da5898SJarno Rajahalme {
54605da5898SJarno Rajahalme 	unsigned long opt_key_offset;
54705da5898SJarno Rajahalme 
54805da5898SJarno Rajahalme 	if (nla_len(a) > sizeof(match->key->tun_opts)) {
54905da5898SJarno Rajahalme 		OVS_NLERR(log, "Geneve option length err (len %d, max %zu).",
55005da5898SJarno Rajahalme 			  nla_len(a), sizeof(match->key->tun_opts));
55105da5898SJarno Rajahalme 		return -EINVAL;
55205da5898SJarno Rajahalme 	}
55305da5898SJarno Rajahalme 
55405da5898SJarno Rajahalme 	if (nla_len(a) % 4 != 0) {
55505da5898SJarno Rajahalme 		OVS_NLERR(log, "Geneve opt len %d is not a multiple of 4.",
55605da5898SJarno Rajahalme 			  nla_len(a));
55705da5898SJarno Rajahalme 		return -EINVAL;
55805da5898SJarno Rajahalme 	}
55905da5898SJarno Rajahalme 
56005da5898SJarno Rajahalme 	/* We need to record the length of the options passed
56105da5898SJarno Rajahalme 	 * down, otherwise packets with the same format but
56205da5898SJarno Rajahalme 	 * additional options will be silently matched.
56305da5898SJarno Rajahalme 	 */
56405da5898SJarno Rajahalme 	if (!is_mask) {
56505da5898SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
56605da5898SJarno Rajahalme 				false);
56705da5898SJarno Rajahalme 	} else {
56805da5898SJarno Rajahalme 		/* This is somewhat unusual because it looks at
56905da5898SJarno Rajahalme 		 * both the key and mask while parsing the
57005da5898SJarno Rajahalme 		 * attributes (and by extension assumes the key
57105da5898SJarno Rajahalme 		 * is parsed first). Normally, we would verify
57205da5898SJarno Rajahalme 		 * that each is the correct length and that the
57305da5898SJarno Rajahalme 		 * attributes line up in the validate function.
57405da5898SJarno Rajahalme 		 * However, that is difficult because this is
57505da5898SJarno Rajahalme 		 * variable length and we won't have the
57605da5898SJarno Rajahalme 		 * information later.
57705da5898SJarno Rajahalme 		 */
57805da5898SJarno Rajahalme 		if (match->key->tun_opts_len != nla_len(a)) {
57905da5898SJarno Rajahalme 			OVS_NLERR(log, "Geneve option len %d != mask len %d",
58005da5898SJarno Rajahalme 				  match->key->tun_opts_len, nla_len(a));
58105da5898SJarno Rajahalme 			return -EINVAL;
58205da5898SJarno Rajahalme 		}
58305da5898SJarno Rajahalme 
58405da5898SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
58505da5898SJarno Rajahalme 	}
58605da5898SJarno Rajahalme 
587d91641d9SThomas Graf 	opt_key_offset = TUN_METADATA_OFFSET(nla_len(a));
58805da5898SJarno Rajahalme 	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
58905da5898SJarno Rajahalme 				  nla_len(a), is_mask);
59005da5898SJarno Rajahalme 	return 0;
591e6445719SPravin B Shelar }
592e6445719SPravin B Shelar 
vxlan_tun_opt_from_nlattr(const struct nlattr * attr,struct sw_flow_match * match,bool is_mask,bool log)593982b5270SJesse Gross static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
5941dd144cfSThomas Graf 				     struct sw_flow_match *match, bool is_mask,
5951dd144cfSThomas Graf 				     bool log)
5961dd144cfSThomas Graf {
597982b5270SJesse Gross 	struct nlattr *a;
598982b5270SJesse Gross 	int rem;
5991dd144cfSThomas Graf 	unsigned long opt_key_offset;
600614732eaSThomas Graf 	struct vxlan_metadata opts;
6011dd144cfSThomas Graf 
6021dd144cfSThomas Graf 	BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
6031dd144cfSThomas Graf 
6041dd144cfSThomas Graf 	memset(&opts, 0, sizeof(opts));
605982b5270SJesse Gross 	nla_for_each_nested(a, attr, rem) {
606982b5270SJesse Gross 		int type = nla_type(a);
6071dd144cfSThomas Graf 
608982b5270SJesse Gross 		if (type > OVS_VXLAN_EXT_MAX) {
609982b5270SJesse Gross 			OVS_NLERR(log, "VXLAN extension %d out of range max %d",
610982b5270SJesse Gross 				  type, OVS_VXLAN_EXT_MAX);
611982b5270SJesse Gross 			return -EINVAL;
612982b5270SJesse Gross 		}
613982b5270SJesse Gross 
614982b5270SJesse Gross 		if (!check_attr_len(nla_len(a),
615982b5270SJesse Gross 				    ovs_vxlan_ext_key_lens[type].len)) {
616982b5270SJesse Gross 			OVS_NLERR(log, "VXLAN extension %d has unexpected len %d expected %d",
617982b5270SJesse Gross 				  type, nla_len(a),
618982b5270SJesse Gross 				  ovs_vxlan_ext_key_lens[type].len);
619982b5270SJesse Gross 			return -EINVAL;
620982b5270SJesse Gross 		}
621982b5270SJesse Gross 
622982b5270SJesse Gross 		switch (type) {
623982b5270SJesse Gross 		case OVS_VXLAN_EXT_GBP:
624982b5270SJesse Gross 			opts.gbp = nla_get_u32(a);
625982b5270SJesse Gross 			break;
626982b5270SJesse Gross 		default:
627982b5270SJesse Gross 			OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
628982b5270SJesse Gross 				  type);
629982b5270SJesse Gross 			return -EINVAL;
630982b5270SJesse Gross 		}
631982b5270SJesse Gross 	}
632982b5270SJesse Gross 	if (rem) {
633982b5270SJesse Gross 		OVS_NLERR(log, "VXLAN extension message has %d unknown bytes.",
634982b5270SJesse Gross 			  rem);
635982b5270SJesse Gross 		return -EINVAL;
636982b5270SJesse Gross 	}
6371dd144cfSThomas Graf 
6381dd144cfSThomas Graf 	if (!is_mask)
6391dd144cfSThomas Graf 		SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), false);
6401dd144cfSThomas Graf 	else
6411dd144cfSThomas Graf 		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
6421dd144cfSThomas Graf 
6431dd144cfSThomas Graf 	opt_key_offset = TUN_METADATA_OFFSET(sizeof(opts));
6441dd144cfSThomas Graf 	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, &opts, sizeof(opts),
6451dd144cfSThomas Graf 				  is_mask);
6461dd144cfSThomas Graf 	return 0;
6471dd144cfSThomas Graf }
6481dd144cfSThomas Graf 
erspan_tun_opt_from_nlattr(const struct nlattr * a,struct sw_flow_match * match,bool is_mask,bool log)649fc1372f8SWilliam Tu static int erspan_tun_opt_from_nlattr(const struct nlattr *a,
650fc1372f8SWilliam Tu 				      struct sw_flow_match *match, bool is_mask,
651fc1372f8SWilliam Tu 				      bool log)
652fc1372f8SWilliam Tu {
653fc1372f8SWilliam Tu 	unsigned long opt_key_offset;
654fc1372f8SWilliam Tu 
655fc1372f8SWilliam Tu 	BUILD_BUG_ON(sizeof(struct erspan_metadata) >
656fc1372f8SWilliam Tu 		     sizeof(match->key->tun_opts));
657fc1372f8SWilliam Tu 
658fc1372f8SWilliam Tu 	if (nla_len(a) > sizeof(match->key->tun_opts)) {
659fc1372f8SWilliam Tu 		OVS_NLERR(log, "ERSPAN option length err (len %d, max %zu).",
660fc1372f8SWilliam Tu 			  nla_len(a), sizeof(match->key->tun_opts));
661fc1372f8SWilliam Tu 		return -EINVAL;
662fc1372f8SWilliam Tu 	}
663fc1372f8SWilliam Tu 
664fc1372f8SWilliam Tu 	if (!is_mask)
665fc1372f8SWilliam Tu 		SW_FLOW_KEY_PUT(match, tun_opts_len,
666fc1372f8SWilliam Tu 				sizeof(struct erspan_metadata), false);
667fc1372f8SWilliam Tu 	else
668fc1372f8SWilliam Tu 		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
669fc1372f8SWilliam Tu 
670fc1372f8SWilliam Tu 	opt_key_offset = TUN_METADATA_OFFSET(nla_len(a));
671fc1372f8SWilliam Tu 	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
672fc1372f8SWilliam Tu 				  nla_len(a), is_mask);
673fc1372f8SWilliam Tu 	return 0;
674fc1372f8SWilliam Tu }
675fc1372f8SWilliam Tu 
ip_tun_from_nlattr(const struct nlattr * attr,struct sw_flow_match * match,bool is_mask,bool log)6766b26ba3aSJiri Benc static int ip_tun_from_nlattr(const struct nlattr *attr,
67705da5898SJarno Rajahalme 			      struct sw_flow_match *match, bool is_mask,
67805da5898SJarno Rajahalme 			      bool log)
679e6445719SPravin B Shelar {
68099e28f18SPravin B Shelar 	bool ttl = false, ipv4 = false, ipv6 = false;
6815832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(tun_flags) = { };
68218b6f717Swenxu 	bool info_bridge_mode = false;
68399e28f18SPravin B Shelar 	int opts_type = 0;
684e6445719SPravin B Shelar 	struct nlattr *a;
685e6445719SPravin B Shelar 	int rem;
686e6445719SPravin B Shelar 
687e6445719SPravin B Shelar 	nla_for_each_nested(a, attr, rem) {
688e6445719SPravin B Shelar 		int type = nla_type(a);
68905da5898SJarno Rajahalme 		int err;
69005da5898SJarno Rajahalme 
691e6445719SPravin B Shelar 		if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
69205da5898SJarno Rajahalme 			OVS_NLERR(log, "Tunnel attr %d out of range max %d",
693e6445719SPravin B Shelar 				  type, OVS_TUNNEL_KEY_ATTR_MAX);
694e6445719SPravin B Shelar 			return -EINVAL;
695e6445719SPravin B Shelar 		}
696e6445719SPravin B Shelar 
697982b5270SJesse Gross 		if (!check_attr_len(nla_len(a),
698982b5270SJesse Gross 				    ovs_tunnel_key_lens[type].len)) {
69905da5898SJarno Rajahalme 			OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
70081bfe3c3SThomas Graf 				  type, nla_len(a), ovs_tunnel_key_lens[type].len);
701e6445719SPravin B Shelar 			return -EINVAL;
702e6445719SPravin B Shelar 		}
703e6445719SPravin B Shelar 
704e6445719SPravin B Shelar 		switch (type) {
705e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_ID:
706e6445719SPravin B Shelar 			SW_FLOW_KEY_PUT(match, tun_key.tun_id,
707e6445719SPravin B Shelar 					nla_get_be64(a), is_mask);
7085832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_KEY_BIT, tun_flags);
709e6445719SPravin B Shelar 			break;
710e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
711c1ea5d67SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src,
71267b61f6cSJiri Benc 					nla_get_in_addr(a), is_mask);
7136b26ba3aSJiri Benc 			ipv4 = true;
714e6445719SPravin B Shelar 			break;
715e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
716c1ea5d67SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst,
71767b61f6cSJiri Benc 					nla_get_in_addr(a), is_mask);
7186b26ba3aSJiri Benc 			ipv4 = true;
7196b26ba3aSJiri Benc 			break;
7206b26ba3aSJiri Benc 		case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
7213d20f1f7SOr Gerlitz 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src,
7226b26ba3aSJiri Benc 					nla_get_in6_addr(a), is_mask);
7236b26ba3aSJiri Benc 			ipv6 = true;
7246b26ba3aSJiri Benc 			break;
7256b26ba3aSJiri Benc 		case OVS_TUNNEL_KEY_ATTR_IPV6_DST:
7266b26ba3aSJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
7276b26ba3aSJiri Benc 					nla_get_in6_addr(a), is_mask);
7286b26ba3aSJiri Benc 			ipv6 = true;
729e6445719SPravin B Shelar 			break;
730e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_TOS:
7317c383fb2SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.tos,
732e6445719SPravin B Shelar 					nla_get_u8(a), is_mask);
733e6445719SPravin B Shelar 			break;
734e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_TTL:
7357c383fb2SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.ttl,
736e6445719SPravin B Shelar 					nla_get_u8(a), is_mask);
737e6445719SPravin B Shelar 			ttl = true;
738e6445719SPravin B Shelar 			break;
739e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
7405832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, tun_flags);
741e6445719SPravin B Shelar 			break;
742e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_CSUM:
7435832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_CSUM_BIT, tun_flags);
744e6445719SPravin B Shelar 			break;
7458f0aad6fSWenyu Zhang 		case OVS_TUNNEL_KEY_ATTR_TP_SRC:
7468f0aad6fSWenyu Zhang 			SW_FLOW_KEY_PUT(match, tun_key.tp_src,
7478f0aad6fSWenyu Zhang 					nla_get_be16(a), is_mask);
7488f0aad6fSWenyu Zhang 			break;
7498f0aad6fSWenyu Zhang 		case OVS_TUNNEL_KEY_ATTR_TP_DST:
7508f0aad6fSWenyu Zhang 			SW_FLOW_KEY_PUT(match, tun_key.tp_dst,
7518f0aad6fSWenyu Zhang 					nla_get_be16(a), is_mask);
7528f0aad6fSWenyu Zhang 			break;
75367fa0341SJesse Gross 		case OVS_TUNNEL_KEY_ATTR_OAM:
7545832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_OAM_BIT, tun_flags);
75567fa0341SJesse Gross 			break;
756f5796684SJesse Gross 		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
7571dd144cfSThomas Graf 			if (opts_type) {
7581dd144cfSThomas Graf 				OVS_NLERR(log, "Multiple metadata blocks provided");
7591dd144cfSThomas Graf 				return -EINVAL;
7601dd144cfSThomas Graf 			}
7611dd144cfSThomas Graf 
76205da5898SJarno Rajahalme 			err = genev_tun_opt_from_nlattr(a, match, is_mask, log);
76305da5898SJarno Rajahalme 			if (err)
76405da5898SJarno Rajahalme 				return err;
76505da5898SJarno Rajahalme 
7665832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_GENEVE_OPT_BIT, tun_flags);
7671dd144cfSThomas Graf 			opts_type = type;
7681dd144cfSThomas Graf 			break;
7691dd144cfSThomas Graf 		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
7701dd144cfSThomas Graf 			if (opts_type) {
7711dd144cfSThomas Graf 				OVS_NLERR(log, "Multiple metadata blocks provided");
7721dd144cfSThomas Graf 				return -EINVAL;
7731dd144cfSThomas Graf 			}
7741dd144cfSThomas Graf 
7751dd144cfSThomas Graf 			err = vxlan_tun_opt_from_nlattr(a, match, is_mask, log);
7761dd144cfSThomas Graf 			if (err)
7771dd144cfSThomas Graf 				return err;
7781dd144cfSThomas Graf 
7795832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_VXLAN_OPT_BIT, tun_flags);
7801dd144cfSThomas Graf 			opts_type = type;
781f5796684SJesse Gross 			break;
7828f3dbfd7SKris Murphy 		case OVS_TUNNEL_KEY_ATTR_PAD:
7838f3dbfd7SKris Murphy 			break;
784fc1372f8SWilliam Tu 		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
785fc1372f8SWilliam Tu 			if (opts_type) {
786fc1372f8SWilliam Tu 				OVS_NLERR(log, "Multiple metadata blocks provided");
787fc1372f8SWilliam Tu 				return -EINVAL;
788fc1372f8SWilliam Tu 			}
789fc1372f8SWilliam Tu 
790fc1372f8SWilliam Tu 			err = erspan_tun_opt_from_nlattr(a, match, is_mask,
791fc1372f8SWilliam Tu 							 log);
792fc1372f8SWilliam Tu 			if (err)
793fc1372f8SWilliam Tu 				return err;
794fc1372f8SWilliam Tu 
7955832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_flags);
796fc1372f8SWilliam Tu 			opts_type = type;
797fc1372f8SWilliam Tu 			break;
79818b6f717Swenxu 		case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE:
79918b6f717Swenxu 			info_bridge_mode = true;
80018b6f717Swenxu 			ipv4 = true;
80118b6f717Swenxu 			break;
802e6445719SPravin B Shelar 		default:
8036b26ba3aSJiri Benc 			OVS_NLERR(log, "Unknown IP tunnel attribute %d",
804f5796684SJesse Gross 				  type);
805e6445719SPravin B Shelar 			return -EINVAL;
806e6445719SPravin B Shelar 		}
807e6445719SPravin B Shelar 	}
808e6445719SPravin B Shelar 
8095832c4a7SAlexander Lobakin 	SW_FLOW_KEY_BITMAP_COPY(match, tun_key.tun_flags, tun_flags,
8105832c4a7SAlexander Lobakin 				__IP_TUNNEL_FLAG_NUM, is_mask);
81100a93babSJiri Benc 	if (is_mask)
81200a93babSJiri Benc 		SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true);
81300a93babSJiri Benc 	else
8146b26ba3aSJiri Benc 		SW_FLOW_KEY_PUT(match, tun_proto, ipv6 ? AF_INET6 : AF_INET,
8156b26ba3aSJiri Benc 				false);
816e6445719SPravin B Shelar 
817e6445719SPravin B Shelar 	if (rem > 0) {
8186b26ba3aSJiri Benc 		OVS_NLERR(log, "IP tunnel attribute has %d unknown bytes.",
81905da5898SJarno Rajahalme 			  rem);
820e6445719SPravin B Shelar 		return -EINVAL;
821e6445719SPravin B Shelar 	}
822e6445719SPravin B Shelar 
8236b26ba3aSJiri Benc 	if (ipv4 && ipv6) {
8246b26ba3aSJiri Benc 		OVS_NLERR(log, "Mixed IPv4 and IPv6 tunnel attributes");
8256b26ba3aSJiri Benc 		return -EINVAL;
8266b26ba3aSJiri Benc 	}
8276b26ba3aSJiri Benc 
828e6445719SPravin B Shelar 	if (!is_mask) {
8296b26ba3aSJiri Benc 		if (!ipv4 && !ipv6) {
8306b26ba3aSJiri Benc 			OVS_NLERR(log, "IP tunnel dst address not specified");
8316b26ba3aSJiri Benc 			return -EINVAL;
8326b26ba3aSJiri Benc 		}
83318b6f717Swenxu 		if (ipv4) {
83418b6f717Swenxu 			if (info_bridge_mode) {
8355832c4a7SAlexander Lobakin 				__clear_bit(IP_TUNNEL_KEY_BIT, tun_flags);
8365832c4a7SAlexander Lobakin 
83718b6f717Swenxu 				if (match->key->tun_key.u.ipv4.src ||
83818b6f717Swenxu 				    match->key->tun_key.u.ipv4.dst ||
83918b6f717Swenxu 				    match->key->tun_key.tp_src ||
84018b6f717Swenxu 				    match->key->tun_key.tp_dst ||
84118b6f717Swenxu 				    match->key->tun_key.ttl ||
84218b6f717Swenxu 				    match->key->tun_key.tos ||
8435832c4a7SAlexander Lobakin 				    !ip_tunnel_flags_empty(tun_flags)) {
84418b6f717Swenxu 					OVS_NLERR(log, "IPv4 tun info is not correct");
84518b6f717Swenxu 					return -EINVAL;
84618b6f717Swenxu 				}
84718b6f717Swenxu 			} else if (!match->key->tun_key.u.ipv4.dst) {
84805da5898SJarno Rajahalme 				OVS_NLERR(log, "IPv4 tunnel dst address is zero");
849e6445719SPravin B Shelar 				return -EINVAL;
850e6445719SPravin B Shelar 			}
85118b6f717Swenxu 		}
8526b26ba3aSJiri Benc 		if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) {
8536b26ba3aSJiri Benc 			OVS_NLERR(log, "IPv6 tunnel dst address is zero");
8546b26ba3aSJiri Benc 			return -EINVAL;
8556b26ba3aSJiri Benc 		}
856e6445719SPravin B Shelar 
85718b6f717Swenxu 		if (!ttl && !info_bridge_mode) {
8586b26ba3aSJiri Benc 			OVS_NLERR(log, "IP tunnel TTL not specified.");
859e6445719SPravin B Shelar 			return -EINVAL;
860e6445719SPravin B Shelar 		}
861e6445719SPravin B Shelar 	}
862e6445719SPravin B Shelar 
8631dd144cfSThomas Graf 	return opts_type;
8641dd144cfSThomas Graf }
8651dd144cfSThomas Graf 
vxlan_opt_to_nlattr(struct sk_buff * skb,const void * tun_opts,int swkey_tun_opts_len)8661dd144cfSThomas Graf static int vxlan_opt_to_nlattr(struct sk_buff *skb,
8671dd144cfSThomas Graf 			       const void *tun_opts, int swkey_tun_opts_len)
8681dd144cfSThomas Graf {
869614732eaSThomas Graf 	const struct vxlan_metadata *opts = tun_opts;
8701dd144cfSThomas Graf 	struct nlattr *nla;
8711dd144cfSThomas Graf 
872ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
8731dd144cfSThomas Graf 	if (!nla)
8741dd144cfSThomas Graf 		return -EMSGSIZE;
8751dd144cfSThomas Graf 
8761dd144cfSThomas Graf 	if (nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
8771dd144cfSThomas Graf 		return -EMSGSIZE;
8781dd144cfSThomas Graf 
8791dd144cfSThomas Graf 	nla_nest_end(skb, nla);
880e6445719SPravin B Shelar 	return 0;
881e6445719SPravin B Shelar }
882e6445719SPravin B Shelar 
__ip_tun_to_nlattr(struct sk_buff * skb,const struct ip_tunnel_key * output,const void * tun_opts,int swkey_tun_opts_len,unsigned short tun_proto,u8 mode)8836b26ba3aSJiri Benc static int __ip_tun_to_nlattr(struct sk_buff *skb,
8841d8fff90SThomas Graf 			      const struct ip_tunnel_key *output,
8856b26ba3aSJiri Benc 			      const void *tun_opts, int swkey_tun_opts_len,
88618b6f717Swenxu 			      unsigned short tun_proto, u8 mode)
887e6445719SPravin B Shelar {
8885832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_KEY_BIT, output->tun_flags) &&
889b46f6dedSNicolas Dichtel 	    nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id,
890b46f6dedSNicolas Dichtel 			 OVS_TUNNEL_KEY_ATTR_PAD))
891e6445719SPravin B Shelar 		return -EMSGSIZE;
89218b6f717Swenxu 
89318b6f717Swenxu 	if (mode & IP_TUNNEL_INFO_BRIDGE)
89418b6f717Swenxu 		return nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE)
89518b6f717Swenxu 		       ? -EMSGSIZE : 0;
89618b6f717Swenxu 
8976b26ba3aSJiri Benc 	switch (tun_proto) {
8986b26ba3aSJiri Benc 	case AF_INET:
899c1ea5d67SJiri Benc 		if (output->u.ipv4.src &&
900930345eaSJiri Benc 		    nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
901c1ea5d67SJiri Benc 				    output->u.ipv4.src))
902e6445719SPravin B Shelar 			return -EMSGSIZE;
903c1ea5d67SJiri Benc 		if (output->u.ipv4.dst &&
904930345eaSJiri Benc 		    nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
905c1ea5d67SJiri Benc 				    output->u.ipv4.dst))
906e6445719SPravin B Shelar 			return -EMSGSIZE;
9076b26ba3aSJiri Benc 		break;
9086b26ba3aSJiri Benc 	case AF_INET6:
9096b26ba3aSJiri Benc 		if (!ipv6_addr_any(&output->u.ipv6.src) &&
9106b26ba3aSJiri Benc 		    nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,
9116b26ba3aSJiri Benc 				     &output->u.ipv6.src))
9126b26ba3aSJiri Benc 			return -EMSGSIZE;
9136b26ba3aSJiri Benc 		if (!ipv6_addr_any(&output->u.ipv6.dst) &&
9146b26ba3aSJiri Benc 		    nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_DST,
9156b26ba3aSJiri Benc 				     &output->u.ipv6.dst))
9166b26ba3aSJiri Benc 			return -EMSGSIZE;
9176b26ba3aSJiri Benc 		break;
9186b26ba3aSJiri Benc 	}
9197c383fb2SJiri Benc 	if (output->tos &&
9207c383fb2SJiri Benc 	    nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos))
921e6445719SPravin B Shelar 		return -EMSGSIZE;
9227c383fb2SJiri Benc 	if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, output->ttl))
923e6445719SPravin B Shelar 		return -EMSGSIZE;
9245832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, output->tun_flags) &&
925e6445719SPravin B Shelar 	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
926e6445719SPravin B Shelar 		return -EMSGSIZE;
9275832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_CSUM_BIT, output->tun_flags) &&
928e6445719SPravin B Shelar 	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
929e6445719SPravin B Shelar 		return -EMSGSIZE;
9308f0aad6fSWenyu Zhang 	if (output->tp_src &&
9318f0aad6fSWenyu Zhang 	    nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
9328f0aad6fSWenyu Zhang 		return -EMSGSIZE;
9338f0aad6fSWenyu Zhang 	if (output->tp_dst &&
9348f0aad6fSWenyu Zhang 	    nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
9358f0aad6fSWenyu Zhang 		return -EMSGSIZE;
9365832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_OAM_BIT, output->tun_flags) &&
93767fa0341SJesse Gross 	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
93867fa0341SJesse Gross 		return -EMSGSIZE;
939fc4099f1SPravin B Shelar 	if (swkey_tun_opts_len) {
9405832c4a7SAlexander Lobakin 		if (test_bit(IP_TUNNEL_GENEVE_OPT_BIT, output->tun_flags) &&
941f5796684SJesse Gross 		    nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
942f5796684SJesse Gross 			    swkey_tun_opts_len, tun_opts))
943f5796684SJesse Gross 			return -EMSGSIZE;
9445832c4a7SAlexander Lobakin 		else if (test_bit(IP_TUNNEL_VXLAN_OPT_BIT,
9455832c4a7SAlexander Lobakin 				  output->tun_flags) &&
9461dd144cfSThomas Graf 			 vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len))
9471dd144cfSThomas Graf 			return -EMSGSIZE;
9485832c4a7SAlexander Lobakin 		else if (test_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
9495832c4a7SAlexander Lobakin 				  output->tun_flags) &&
950fc1372f8SWilliam Tu 			 nla_put(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
951fc1372f8SWilliam Tu 				 swkey_tun_opts_len, tun_opts))
952fc1372f8SWilliam Tu 			return -EMSGSIZE;
9531dd144cfSThomas Graf 	}
954f5796684SJesse Gross 
955f5796684SJesse Gross 	return 0;
956f5796684SJesse Gross }
957f5796684SJesse Gross 
ip_tun_to_nlattr(struct sk_buff * skb,const struct ip_tunnel_key * output,const void * tun_opts,int swkey_tun_opts_len,unsigned short tun_proto,u8 mode)9586b26ba3aSJiri Benc static int ip_tun_to_nlattr(struct sk_buff *skb,
9591d8fff90SThomas Graf 			    const struct ip_tunnel_key *output,
9606b26ba3aSJiri Benc 			    const void *tun_opts, int swkey_tun_opts_len,
96118b6f717Swenxu 			    unsigned short tun_proto, u8 mode)
962f5796684SJesse Gross {
963f5796684SJesse Gross 	struct nlattr *nla;
964f5796684SJesse Gross 	int err;
965f5796684SJesse Gross 
966ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_KEY_ATTR_TUNNEL);
967f5796684SJesse Gross 	if (!nla)
968f5796684SJesse Gross 		return -EMSGSIZE;
969f5796684SJesse Gross 
9706b26ba3aSJiri Benc 	err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len,
97118b6f717Swenxu 				 tun_proto, mode);
972f5796684SJesse Gross 	if (err)
973f5796684SJesse Gross 		return err;
974e6445719SPravin B Shelar 
975e6445719SPravin B Shelar 	nla_nest_end(skb, nla);
976e6445719SPravin B Shelar 	return 0;
977e6445719SPravin B Shelar }
978e6445719SPravin B Shelar 
ovs_nla_put_tunnel_info(struct sk_buff * skb,struct ip_tunnel_info * tun_info)979fc4099f1SPravin B Shelar int ovs_nla_put_tunnel_info(struct sk_buff *skb,
980fc4099f1SPravin B Shelar 			    struct ip_tunnel_info *tun_info)
9818f0aad6fSWenyu Zhang {
982ba3e2084SDavid S. Miller 	return __ip_tun_to_nlattr(skb, &tun_info->key,
983fc4099f1SPravin B Shelar 				  ip_tunnel_info_opts(tun_info),
984ba3e2084SDavid S. Miller 				  tun_info->options_len,
98518b6f717Swenxu 				  ip_tunnel_info_af(tun_info), tun_info->mode);
9868f0aad6fSWenyu Zhang }
9878f0aad6fSWenyu Zhang 
encode_vlan_from_nlattrs(struct sw_flow_match * match,const struct nlattr * a[],bool is_mask,bool inner)988018c1ddaSEric Garver static int encode_vlan_from_nlattrs(struct sw_flow_match *match,
989018c1ddaSEric Garver 				    const struct nlattr *a[],
990018c1ddaSEric Garver 				    bool is_mask, bool inner)
991018c1ddaSEric Garver {
992018c1ddaSEric Garver 	__be16 tci = 0;
993018c1ddaSEric Garver 	__be16 tpid = 0;
994018c1ddaSEric Garver 
995018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_VLAN])
996018c1ddaSEric Garver 		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
997018c1ddaSEric Garver 
998018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_ETHERTYPE])
999018c1ddaSEric Garver 		tpid = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
1000018c1ddaSEric Garver 
1001018c1ddaSEric Garver 	if (likely(!inner)) {
1002018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.vlan.tpid, tpid, is_mask);
1003018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.vlan.tci, tci, is_mask);
1004018c1ddaSEric Garver 	} else {
1005018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.cvlan.tpid, tpid, is_mask);
1006018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.cvlan.tci, tci, is_mask);
1007018c1ddaSEric Garver 	}
1008018c1ddaSEric Garver 	return 0;
1009018c1ddaSEric Garver }
1010018c1ddaSEric Garver 
validate_vlan_from_nlattrs(const struct sw_flow_match * match,u64 key_attrs,bool inner,const struct nlattr ** a,bool log)1011018c1ddaSEric Garver static int validate_vlan_from_nlattrs(const struct sw_flow_match *match,
1012018c1ddaSEric Garver 				      u64 key_attrs, bool inner,
1013018c1ddaSEric Garver 				      const struct nlattr **a, bool log)
1014018c1ddaSEric Garver {
1015018c1ddaSEric Garver 	__be16 tci = 0;
1016018c1ddaSEric Garver 
1017018c1ddaSEric Garver 	if (!((key_attrs & (1 << OVS_KEY_ATTR_ETHERNET)) &&
1018018c1ddaSEric Garver 	      (key_attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) &&
1019018c1ddaSEric Garver 	       eth_type_vlan(nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE])))) {
1020018c1ddaSEric Garver 		/* Not a VLAN. */
1021018c1ddaSEric Garver 		return 0;
1022018c1ddaSEric Garver 	}
1023018c1ddaSEric Garver 
1024018c1ddaSEric Garver 	if (!((key_attrs & (1 << OVS_KEY_ATTR_VLAN)) &&
1025018c1ddaSEric Garver 	      (key_attrs & (1 << OVS_KEY_ATTR_ENCAP)))) {
1026018c1ddaSEric Garver 		OVS_NLERR(log, "Invalid %s frame", (inner) ? "C-VLAN" : "VLAN");
1027018c1ddaSEric Garver 		return -EINVAL;
1028018c1ddaSEric Garver 	}
1029018c1ddaSEric Garver 
1030018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_VLAN])
1031018c1ddaSEric Garver 		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
1032018c1ddaSEric Garver 
10339df46aefSMichał Mirosław 	if (!(tci & htons(VLAN_CFI_MASK))) {
1034018c1ddaSEric Garver 		if (tci) {
10359df46aefSMichał Mirosław 			OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit set.",
1036018c1ddaSEric Garver 				  (inner) ? "C-VLAN" : "VLAN");
1037018c1ddaSEric Garver 			return -EINVAL;
1038018c1ddaSEric Garver 		} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
1039018c1ddaSEric Garver 			/* Corner case for truncated VLAN header. */
1040018c1ddaSEric Garver 			OVS_NLERR(log, "Truncated %s header has non-zero encap attribute.",
1041018c1ddaSEric Garver 				  (inner) ? "C-VLAN" : "VLAN");
1042018c1ddaSEric Garver 			return -EINVAL;
1043018c1ddaSEric Garver 		}
1044018c1ddaSEric Garver 	}
1045018c1ddaSEric Garver 
1046018c1ddaSEric Garver 	return 1;
1047018c1ddaSEric Garver }
1048018c1ddaSEric Garver 
validate_vlan_mask_from_nlattrs(const struct sw_flow_match * match,u64 key_attrs,bool inner,const struct nlattr ** a,bool log)1049018c1ddaSEric Garver static int validate_vlan_mask_from_nlattrs(const struct sw_flow_match *match,
1050018c1ddaSEric Garver 					   u64 key_attrs, bool inner,
1051018c1ddaSEric Garver 					   const struct nlattr **a, bool log)
1052018c1ddaSEric Garver {
1053018c1ddaSEric Garver 	__be16 tci = 0;
1054018c1ddaSEric Garver 	__be16 tpid = 0;
1055018c1ddaSEric Garver 	bool encap_valid = !!(match->key->eth.vlan.tci &
10569df46aefSMichał Mirosław 			      htons(VLAN_CFI_MASK));
1057018c1ddaSEric Garver 	bool i_encap_valid = !!(match->key->eth.cvlan.tci &
10589df46aefSMichał Mirosław 				htons(VLAN_CFI_MASK));
1059018c1ddaSEric Garver 
1060018c1ddaSEric Garver 	if (!(key_attrs & (1 << OVS_KEY_ATTR_ENCAP))) {
1061018c1ddaSEric Garver 		/* Not a VLAN. */
1062018c1ddaSEric Garver 		return 0;
1063018c1ddaSEric Garver 	}
1064018c1ddaSEric Garver 
1065018c1ddaSEric Garver 	if ((!inner && !encap_valid) || (inner && !i_encap_valid)) {
1066018c1ddaSEric Garver 		OVS_NLERR(log, "Encap mask attribute is set for non-%s frame.",
1067018c1ddaSEric Garver 			  (inner) ? "C-VLAN" : "VLAN");
1068018c1ddaSEric Garver 		return -EINVAL;
1069018c1ddaSEric Garver 	}
1070018c1ddaSEric Garver 
1071018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_VLAN])
1072018c1ddaSEric Garver 		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
1073018c1ddaSEric Garver 
1074018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_ETHERTYPE])
1075018c1ddaSEric Garver 		tpid = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
1076018c1ddaSEric Garver 
1077018c1ddaSEric Garver 	if (tpid != htons(0xffff)) {
1078018c1ddaSEric Garver 		OVS_NLERR(log, "Must have an exact match on %s TPID (mask=%x).",
1079018c1ddaSEric Garver 			  (inner) ? "C-VLAN" : "VLAN", ntohs(tpid));
1080018c1ddaSEric Garver 		return -EINVAL;
1081018c1ddaSEric Garver 	}
10829df46aefSMichał Mirosław 	if (!(tci & htons(VLAN_CFI_MASK))) {
10839df46aefSMichał Mirosław 		OVS_NLERR(log, "%s TCI mask does not have exact match for VLAN_CFI_MASK bit.",
1084018c1ddaSEric Garver 			  (inner) ? "C-VLAN" : "VLAN");
1085018c1ddaSEric Garver 		return -EINVAL;
1086018c1ddaSEric Garver 	}
1087018c1ddaSEric Garver 
1088018c1ddaSEric Garver 	return 1;
1089018c1ddaSEric Garver }
1090018c1ddaSEric Garver 
__parse_vlan_from_nlattrs(struct sw_flow_match * match,u64 * key_attrs,bool inner,const struct nlattr ** a,bool is_mask,bool log)1091018c1ddaSEric Garver static int __parse_vlan_from_nlattrs(struct sw_flow_match *match,
1092018c1ddaSEric Garver 				     u64 *key_attrs, bool inner,
1093018c1ddaSEric Garver 				     const struct nlattr **a, bool is_mask,
1094018c1ddaSEric Garver 				     bool log)
1095018c1ddaSEric Garver {
1096018c1ddaSEric Garver 	int err;
1097018c1ddaSEric Garver 	const struct nlattr *encap;
1098018c1ddaSEric Garver 
1099018c1ddaSEric Garver 	if (!is_mask)
1100018c1ddaSEric Garver 		err = validate_vlan_from_nlattrs(match, *key_attrs, inner,
1101018c1ddaSEric Garver 						 a, log);
1102018c1ddaSEric Garver 	else
1103018c1ddaSEric Garver 		err = validate_vlan_mask_from_nlattrs(match, *key_attrs, inner,
1104018c1ddaSEric Garver 						      a, log);
1105018c1ddaSEric Garver 	if (err <= 0)
1106018c1ddaSEric Garver 		return err;
1107018c1ddaSEric Garver 
1108018c1ddaSEric Garver 	err = encode_vlan_from_nlattrs(match, a, is_mask, inner);
1109018c1ddaSEric Garver 	if (err)
1110018c1ddaSEric Garver 		return err;
1111018c1ddaSEric Garver 
1112018c1ddaSEric Garver 	*key_attrs &= ~(1 << OVS_KEY_ATTR_ENCAP);
1113018c1ddaSEric Garver 	*key_attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
1114018c1ddaSEric Garver 	*key_attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
1115018c1ddaSEric Garver 
1116018c1ddaSEric Garver 	encap = a[OVS_KEY_ATTR_ENCAP];
1117018c1ddaSEric Garver 
1118018c1ddaSEric Garver 	if (!is_mask)
1119018c1ddaSEric Garver 		err = parse_flow_nlattrs(encap, a, key_attrs, log);
1120018c1ddaSEric Garver 	else
1121018c1ddaSEric Garver 		err = parse_flow_mask_nlattrs(encap, a, key_attrs, log);
1122018c1ddaSEric Garver 
1123018c1ddaSEric Garver 	return err;
1124018c1ddaSEric Garver }
1125018c1ddaSEric Garver 
parse_vlan_from_nlattrs(struct sw_flow_match * match,u64 * key_attrs,const struct nlattr ** a,bool is_mask,bool log)1126018c1ddaSEric Garver static int parse_vlan_from_nlattrs(struct sw_flow_match *match,
1127018c1ddaSEric Garver 				   u64 *key_attrs, const struct nlattr **a,
1128018c1ddaSEric Garver 				   bool is_mask, bool log)
1129018c1ddaSEric Garver {
1130018c1ddaSEric Garver 	int err;
1131018c1ddaSEric Garver 	bool encap_valid = false;
1132018c1ddaSEric Garver 
1133018c1ddaSEric Garver 	err = __parse_vlan_from_nlattrs(match, key_attrs, false, a,
1134018c1ddaSEric Garver 					is_mask, log);
1135018c1ddaSEric Garver 	if (err)
1136018c1ddaSEric Garver 		return err;
1137018c1ddaSEric Garver 
11389df46aefSMichał Mirosław 	encap_valid = !!(match->key->eth.vlan.tci & htons(VLAN_CFI_MASK));
1139018c1ddaSEric Garver 	if (encap_valid) {
1140018c1ddaSEric Garver 		err = __parse_vlan_from_nlattrs(match, key_attrs, true, a,
1141018c1ddaSEric Garver 						is_mask, log);
1142018c1ddaSEric Garver 		if (err)
1143018c1ddaSEric Garver 			return err;
1144018c1ddaSEric Garver 	}
1145018c1ddaSEric Garver 
1146018c1ddaSEric Garver 	return 0;
1147018c1ddaSEric Garver }
1148018c1ddaSEric Garver 
parse_eth_type_from_nlattrs(struct sw_flow_match * match,u64 * attrs,const struct nlattr ** a,bool is_mask,bool log)11490a6410fbSJiri Benc static int parse_eth_type_from_nlattrs(struct sw_flow_match *match,
11500a6410fbSJiri Benc 				       u64 *attrs, const struct nlattr **a,
11510a6410fbSJiri Benc 				       bool is_mask, bool log)
11520a6410fbSJiri Benc {
11530a6410fbSJiri Benc 	__be16 eth_type;
11540a6410fbSJiri Benc 
11550a6410fbSJiri Benc 	eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
11560a6410fbSJiri Benc 	if (is_mask) {
11570a6410fbSJiri Benc 		/* Always exact match EtherType. */
11580a6410fbSJiri Benc 		eth_type = htons(0xffff);
11590a6410fbSJiri Benc 	} else if (!eth_proto_is_802_3(eth_type)) {
11600a6410fbSJiri Benc 		OVS_NLERR(log, "EtherType %x is less than min %x",
11610a6410fbSJiri Benc 				ntohs(eth_type), ETH_P_802_3_MIN);
11620a6410fbSJiri Benc 		return -EINVAL;
11630a6410fbSJiri Benc 	}
11640a6410fbSJiri Benc 
11650a6410fbSJiri Benc 	SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
11660a6410fbSJiri Benc 	*attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
11670a6410fbSJiri Benc 	return 0;
11680a6410fbSJiri Benc }
11690a6410fbSJiri Benc 
metadata_from_nlattrs(struct net * net,struct sw_flow_match * match,u64 * attrs,const struct nlattr ** a,bool is_mask,bool log)1170c2ac6673SJoe Stringer static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
1171c2ac6673SJoe Stringer 				 u64 *attrs, const struct nlattr **a,
1172c2ac6673SJoe Stringer 				 bool is_mask, bool log)
1173e6445719SPravin B Shelar {
11740a6410fbSJiri Benc 	u8 mac_proto = MAC_PROTO_ETHERNET;
11750a6410fbSJiri Benc 
1176971427f3SAndy Zhou 	if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
1177971427f3SAndy Zhou 		u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
1178971427f3SAndy Zhou 
1179971427f3SAndy Zhou 		SW_FLOW_KEY_PUT(match, ovs_flow_hash, hash_val, is_mask);
1180971427f3SAndy Zhou 		*attrs &= ~(1 << OVS_KEY_ATTR_DP_HASH);
1181971427f3SAndy Zhou 	}
1182971427f3SAndy Zhou 
1183971427f3SAndy Zhou 	if (*attrs & (1 << OVS_KEY_ATTR_RECIRC_ID)) {
1184971427f3SAndy Zhou 		u32 recirc_id = nla_get_u32(a[OVS_KEY_ATTR_RECIRC_ID]);
1185971427f3SAndy Zhou 
1186971427f3SAndy Zhou 		SW_FLOW_KEY_PUT(match, recirc_id, recirc_id, is_mask);
1187971427f3SAndy Zhou 		*attrs &= ~(1 << OVS_KEY_ATTR_RECIRC_ID);
1188971427f3SAndy Zhou 	}
1189971427f3SAndy Zhou 
1190e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
1191e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.priority,
1192e6445719SPravin B Shelar 			  nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask);
1193e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_PRIORITY);
1194e6445719SPravin B Shelar 	}
1195e6445719SPravin B Shelar 
1196e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_IN_PORT)) {
1197e6445719SPravin B Shelar 		u32 in_port = nla_get_u32(a[OVS_KEY_ATTR_IN_PORT]);
1198e6445719SPravin B Shelar 
1199426cda5cSJesse Gross 		if (is_mask) {
1200e6445719SPravin B Shelar 			in_port = 0xffffffff; /* Always exact match in_port. */
1201426cda5cSJesse Gross 		} else if (in_port >= DP_MAX_PORTS) {
120205da5898SJarno Rajahalme 			OVS_NLERR(log, "Port %d exceeds max allowable %d",
1203426cda5cSJesse Gross 				  in_port, DP_MAX_PORTS);
1204e6445719SPravin B Shelar 			return -EINVAL;
1205426cda5cSJesse Gross 		}
1206e6445719SPravin B Shelar 
1207e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.in_port, in_port, is_mask);
1208e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_IN_PORT);
1209e6445719SPravin B Shelar 	} else if (!is_mask) {
1210e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.in_port, DP_MAX_PORTS, is_mask);
1211e6445719SPravin B Shelar 	}
1212e6445719SPravin B Shelar 
1213e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
1214e6445719SPravin B Shelar 		uint32_t mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
1215e6445719SPravin B Shelar 
1216e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.skb_mark, mark, is_mask);
1217e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
1218e6445719SPravin B Shelar 	}
1219e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
12206b26ba3aSJiri Benc 		if (ip_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
12211dd144cfSThomas Graf 				       is_mask, log) < 0)
1222e6445719SPravin B Shelar 			return -EINVAL;
1223e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
1224e6445719SPravin B Shelar 	}
12257f8a436eSJoe Stringer 
12267f8a436eSJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
1227c2ac6673SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
1228fbccce59SJoe Stringer 		u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
12297f8a436eSJoe Stringer 
12309e384715SJoe Stringer 		if (ct_state & ~CT_SUPPORTED_MASK) {
1231fbccce59SJoe Stringer 			OVS_NLERR(log, "ct_state flags %08x unsupported",
12326f225952SJoe Stringer 				  ct_state);
12336f225952SJoe Stringer 			return -EINVAL;
12346f225952SJoe Stringer 		}
12357f8a436eSJoe Stringer 
1236316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_state, ct_state, is_mask);
12377f8a436eSJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
12387f8a436eSJoe Stringer 	}
12397f8a436eSJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) &&
1240c2ac6673SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_ZONE)) {
12417f8a436eSJoe Stringer 		u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]);
12427f8a436eSJoe Stringer 
1243316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_zone, ct_zone, is_mask);
12447f8a436eSJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE);
12457f8a436eSJoe Stringer 	}
1246182e3042SJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) &&
1247c2ac6673SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_MARK)) {
1248182e3042SJoe Stringer 		u32 mark = nla_get_u32(a[OVS_KEY_ATTR_CT_MARK]);
1249182e3042SJoe Stringer 
1250182e3042SJoe Stringer 		SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
1251182e3042SJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
1252182e3042SJoe Stringer 	}
125333db4125SJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
125433db4125SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
125533db4125SJoe Stringer 		const struct ovs_key_ct_labels *cl;
1256c2ac6673SJoe Stringer 
125733db4125SJoe Stringer 		cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
125833db4125SJoe Stringer 		SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
1259c2ac6673SJoe Stringer 				   sizeof(*cl), is_mask);
126033db4125SJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
1261c2ac6673SJoe Stringer 	}
12629dd7f890SJarno Rajahalme 	if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)) {
12639dd7f890SJarno Rajahalme 		const struct ovs_key_ct_tuple_ipv4 *ct;
12649dd7f890SJarno Rajahalme 
12659dd7f890SJarno Rajahalme 		ct = nla_data(a[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]);
12669dd7f890SJarno Rajahalme 
12679dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ipv4.ct_orig.src, ct->ipv4_src, is_mask);
12689dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ipv4.ct_orig.dst, ct->ipv4_dst, is_mask);
12699dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
12709dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
1271316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv4_proto, is_mask);
12729dd7f890SJarno Rajahalme 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4);
12739dd7f890SJarno Rajahalme 	}
12749dd7f890SJarno Rajahalme 	if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)) {
12759dd7f890SJarno Rajahalme 		const struct ovs_key_ct_tuple_ipv6 *ct;
12769dd7f890SJarno Rajahalme 
12779dd7f890SJarno Rajahalme 		ct = nla_data(a[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);
12789dd7f890SJarno Rajahalme 
12799dd7f890SJarno Rajahalme 		SW_FLOW_KEY_MEMCPY(match, ipv6.ct_orig.src, &ct->ipv6_src,
12809dd7f890SJarno Rajahalme 				   sizeof(match->key->ipv6.ct_orig.src),
12819dd7f890SJarno Rajahalme 				   is_mask);
12829dd7f890SJarno Rajahalme 		SW_FLOW_KEY_MEMCPY(match, ipv6.ct_orig.dst, &ct->ipv6_dst,
12839dd7f890SJarno Rajahalme 				   sizeof(match->key->ipv6.ct_orig.dst),
12849dd7f890SJarno Rajahalme 				   is_mask);
12859dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
12869dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
1287316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv6_proto, is_mask);
12889dd7f890SJarno Rajahalme 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
12899dd7f890SJarno Rajahalme 	}
1290329f45bcSJiri Benc 
12910a6410fbSJiri Benc 	/* For layer 3 packets the Ethernet type is provided
12920a6410fbSJiri Benc 	 * and treated as metadata but no MAC addresses are provided.
12930a6410fbSJiri Benc 	 */
12940a6410fbSJiri Benc 	if (!(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) &&
12950a6410fbSJiri Benc 	    (*attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE)))
12960a6410fbSJiri Benc 		mac_proto = MAC_PROTO_NONE;
12970a6410fbSJiri Benc 
1298329f45bcSJiri Benc 	/* Always exact match mac_proto */
12990a6410fbSJiri Benc 	SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : mac_proto, is_mask);
13000a6410fbSJiri Benc 
13010a6410fbSJiri Benc 	if (mac_proto == MAC_PROTO_NONE)
13020a6410fbSJiri Benc 		return parse_eth_type_from_nlattrs(match, attrs, a, is_mask,
13030a6410fbSJiri Benc 						   log);
1304329f45bcSJiri Benc 
1305e6445719SPravin B Shelar 	return 0;
1306e6445719SPravin B Shelar }
1307e6445719SPravin B Shelar 
nsh_hdr_from_nlattr(const struct nlattr * attr,struct nshhdr * nh,size_t size)1308b2d0f5d5SYi Yang int nsh_hdr_from_nlattr(const struct nlattr *attr,
1309b2d0f5d5SYi Yang 			struct nshhdr *nh, size_t size)
1310b2d0f5d5SYi Yang {
1311b2d0f5d5SYi Yang 	struct nlattr *a;
1312b2d0f5d5SYi Yang 	int rem;
1313b2d0f5d5SYi Yang 	u8 flags = 0;
1314b2d0f5d5SYi Yang 	u8 ttl = 0;
1315b2d0f5d5SYi Yang 	int mdlen = 0;
1316b2d0f5d5SYi Yang 
1317b2d0f5d5SYi Yang 	/* validate_nsh has check this, so we needn't do duplicate check here
1318b2d0f5d5SYi Yang 	 */
1319b2d0f5d5SYi Yang 	if (size < NSH_BASE_HDR_LEN)
1320b2d0f5d5SYi Yang 		return -ENOBUFS;
1321b2d0f5d5SYi Yang 
1322b2d0f5d5SYi Yang 	nla_for_each_nested(a, attr, rem) {
1323b2d0f5d5SYi Yang 		int type = nla_type(a);
1324b2d0f5d5SYi Yang 
1325b2d0f5d5SYi Yang 		switch (type) {
1326b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_BASE: {
1327b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base = nla_data(a);
1328b2d0f5d5SYi Yang 
1329b2d0f5d5SYi Yang 			flags = base->flags;
1330b2d0f5d5SYi Yang 			ttl = base->ttl;
1331b2d0f5d5SYi Yang 			nh->np = base->np;
1332b2d0f5d5SYi Yang 			nh->mdtype = base->mdtype;
1333b2d0f5d5SYi Yang 			nh->path_hdr = base->path_hdr;
1334b2d0f5d5SYi Yang 			break;
1335b2d0f5d5SYi Yang 		}
1336b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD1:
1337b2d0f5d5SYi Yang 			mdlen = nla_len(a);
1338b2d0f5d5SYi Yang 			if (mdlen > size - NSH_BASE_HDR_LEN)
1339b2d0f5d5SYi Yang 				return -ENOBUFS;
1340b2d0f5d5SYi Yang 			memcpy(&nh->md1, nla_data(a), mdlen);
1341b2d0f5d5SYi Yang 			break;
1342b2d0f5d5SYi Yang 
1343b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD2:
1344b2d0f5d5SYi Yang 			mdlen = nla_len(a);
1345b2d0f5d5SYi Yang 			if (mdlen > size - NSH_BASE_HDR_LEN)
1346b2d0f5d5SYi Yang 				return -ENOBUFS;
1347b2d0f5d5SYi Yang 			memcpy(&nh->md2, nla_data(a), mdlen);
1348b2d0f5d5SYi Yang 			break;
1349b2d0f5d5SYi Yang 
1350b2d0f5d5SYi Yang 		default:
1351b2d0f5d5SYi Yang 			return -EINVAL;
1352b2d0f5d5SYi Yang 		}
1353b2d0f5d5SYi Yang 	}
1354b2d0f5d5SYi Yang 
1355b2d0f5d5SYi Yang 	/* nsh header length  = NSH_BASE_HDR_LEN + mdlen */
1356b2d0f5d5SYi Yang 	nh->ver_flags_ttl_len = 0;
1357b2d0f5d5SYi Yang 	nsh_set_flags_ttl_len(nh, flags, ttl, NSH_BASE_HDR_LEN + mdlen);
1358b2d0f5d5SYi Yang 
1359b2d0f5d5SYi Yang 	return 0;
1360b2d0f5d5SYi Yang }
1361b2d0f5d5SYi Yang 
nsh_key_from_nlattr(const struct nlattr * attr,struct ovs_key_nsh * nsh,struct ovs_key_nsh * nsh_mask)1362b2d0f5d5SYi Yang int nsh_key_from_nlattr(const struct nlattr *attr,
1363b2d0f5d5SYi Yang 			struct ovs_key_nsh *nsh, struct ovs_key_nsh *nsh_mask)
1364b2d0f5d5SYi Yang {
1365b2d0f5d5SYi Yang 	struct nlattr *a;
1366b2d0f5d5SYi Yang 	int rem;
1367b2d0f5d5SYi Yang 
1368b2d0f5d5SYi Yang 	/* validate_nsh has check this, so we needn't do duplicate check here
1369b2d0f5d5SYi Yang 	 */
1370b2d0f5d5SYi Yang 	nla_for_each_nested(a, attr, rem) {
1371b2d0f5d5SYi Yang 		int type = nla_type(a);
1372b2d0f5d5SYi Yang 
1373b2d0f5d5SYi Yang 		switch (type) {
1374b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_BASE: {
1375b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base = nla_data(a);
1376b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base_mask = base + 1;
1377b2d0f5d5SYi Yang 
1378b2d0f5d5SYi Yang 			nsh->base = *base;
1379b2d0f5d5SYi Yang 			nsh_mask->base = *base_mask;
1380b2d0f5d5SYi Yang 			break;
1381b2d0f5d5SYi Yang 		}
1382b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD1: {
1383b2d0f5d5SYi Yang 			const struct ovs_nsh_key_md1 *md1 = nla_data(a);
1384b2d0f5d5SYi Yang 			const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
1385b2d0f5d5SYi Yang 
1386b2d0f5d5SYi Yang 			memcpy(nsh->context, md1->context, sizeof(*md1));
1387b2d0f5d5SYi Yang 			memcpy(nsh_mask->context, md1_mask->context,
1388b2d0f5d5SYi Yang 			       sizeof(*md1_mask));
1389b2d0f5d5SYi Yang 			break;
1390b2d0f5d5SYi Yang 		}
1391b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD2:
1392b2d0f5d5SYi Yang 			/* Not supported yet */
1393b2d0f5d5SYi Yang 			return -ENOTSUPP;
1394b2d0f5d5SYi Yang 		default:
1395b2d0f5d5SYi Yang 			return -EINVAL;
1396b2d0f5d5SYi Yang 		}
1397b2d0f5d5SYi Yang 	}
1398b2d0f5d5SYi Yang 
1399b2d0f5d5SYi Yang 	return 0;
1400b2d0f5d5SYi Yang }
1401b2d0f5d5SYi Yang 
nsh_key_put_from_nlattr(const struct nlattr * attr,struct sw_flow_match * match,bool is_mask,bool is_push_nsh,bool log)1402b2d0f5d5SYi Yang static int nsh_key_put_from_nlattr(const struct nlattr *attr,
1403b2d0f5d5SYi Yang 				   struct sw_flow_match *match, bool is_mask,
1404b2d0f5d5SYi Yang 				   bool is_push_nsh, bool log)
1405b2d0f5d5SYi Yang {
1406b2d0f5d5SYi Yang 	struct nlattr *a;
1407b2d0f5d5SYi Yang 	int rem;
1408b2d0f5d5SYi Yang 	bool has_base = false;
1409b2d0f5d5SYi Yang 	bool has_md1 = false;
1410b2d0f5d5SYi Yang 	bool has_md2 = false;
1411b2d0f5d5SYi Yang 	u8 mdtype = 0;
1412b2d0f5d5SYi Yang 	int mdlen = 0;
1413b2d0f5d5SYi Yang 
1414b2d0f5d5SYi Yang 	if (WARN_ON(is_push_nsh && is_mask))
1415b2d0f5d5SYi Yang 		return -EINVAL;
1416b2d0f5d5SYi Yang 
1417b2d0f5d5SYi Yang 	nla_for_each_nested(a, attr, rem) {
1418b2d0f5d5SYi Yang 		int type = nla_type(a);
1419b2d0f5d5SYi Yang 		int i;
1420b2d0f5d5SYi Yang 
1421b2d0f5d5SYi Yang 		if (type > OVS_NSH_KEY_ATTR_MAX) {
1422b2d0f5d5SYi Yang 			OVS_NLERR(log, "nsh attr %d is out of range max %d",
1423b2d0f5d5SYi Yang 				  type, OVS_NSH_KEY_ATTR_MAX);
1424b2d0f5d5SYi Yang 			return -EINVAL;
1425b2d0f5d5SYi Yang 		}
1426b2d0f5d5SYi Yang 
1427b2d0f5d5SYi Yang 		if (!check_attr_len(nla_len(a),
1428b2d0f5d5SYi Yang 				    ovs_nsh_key_attr_lens[type].len)) {
1429b2d0f5d5SYi Yang 			OVS_NLERR(
1430b2d0f5d5SYi Yang 			    log,
1431b2d0f5d5SYi Yang 			    "nsh attr %d has unexpected len %d expected %d",
1432b2d0f5d5SYi Yang 			    type,
1433b2d0f5d5SYi Yang 			    nla_len(a),
1434b2d0f5d5SYi Yang 			    ovs_nsh_key_attr_lens[type].len
1435b2d0f5d5SYi Yang 			);
1436b2d0f5d5SYi Yang 			return -EINVAL;
1437b2d0f5d5SYi Yang 		}
1438b2d0f5d5SYi Yang 
1439b2d0f5d5SYi Yang 		switch (type) {
1440b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_BASE: {
1441b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base = nla_data(a);
1442b2d0f5d5SYi Yang 
1443b2d0f5d5SYi Yang 			has_base = true;
1444b2d0f5d5SYi Yang 			mdtype = base->mdtype;
1445b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.flags,
1446b2d0f5d5SYi Yang 					base->flags, is_mask);
1447b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.ttl,
1448b2d0f5d5SYi Yang 					base->ttl, is_mask);
1449b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.mdtype,
1450b2d0f5d5SYi Yang 					base->mdtype, is_mask);
1451b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.np,
1452b2d0f5d5SYi Yang 					base->np, is_mask);
1453b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.path_hdr,
1454b2d0f5d5SYi Yang 					base->path_hdr, is_mask);
1455b2d0f5d5SYi Yang 			break;
1456b2d0f5d5SYi Yang 		}
1457b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD1: {
1458b2d0f5d5SYi Yang 			const struct ovs_nsh_key_md1 *md1 = nla_data(a);
1459b2d0f5d5SYi Yang 
1460b2d0f5d5SYi Yang 			has_md1 = true;
1461b2d0f5d5SYi Yang 			for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)
1462b2d0f5d5SYi Yang 				SW_FLOW_KEY_PUT(match, nsh.context[i],
1463b2d0f5d5SYi Yang 						md1->context[i], is_mask);
1464b2d0f5d5SYi Yang 			break;
1465b2d0f5d5SYi Yang 		}
1466b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD2:
1467b2d0f5d5SYi Yang 			if (!is_push_nsh) /* Not supported MD type 2 yet */
1468b2d0f5d5SYi Yang 				return -ENOTSUPP;
1469b2d0f5d5SYi Yang 
1470b2d0f5d5SYi Yang 			has_md2 = true;
1471b2d0f5d5SYi Yang 			mdlen = nla_len(a);
1472b2d0f5d5SYi Yang 			if (mdlen > NSH_CTX_HDRS_MAX_LEN || mdlen <= 0) {
1473b2d0f5d5SYi Yang 				OVS_NLERR(
1474b2d0f5d5SYi Yang 				    log,
1475b2d0f5d5SYi Yang 				    "Invalid MD length %d for MD type %d",
1476b2d0f5d5SYi Yang 				    mdlen,
1477b2d0f5d5SYi Yang 				    mdtype
1478b2d0f5d5SYi Yang 				);
1479b2d0f5d5SYi Yang 				return -EINVAL;
1480b2d0f5d5SYi Yang 			}
1481b2d0f5d5SYi Yang 			break;
1482b2d0f5d5SYi Yang 		default:
1483b2d0f5d5SYi Yang 			OVS_NLERR(log, "Unknown nsh attribute %d",
1484b2d0f5d5SYi Yang 				  type);
1485b2d0f5d5SYi Yang 			return -EINVAL;
1486b2d0f5d5SYi Yang 		}
1487b2d0f5d5SYi Yang 	}
1488b2d0f5d5SYi Yang 
1489b2d0f5d5SYi Yang 	if (rem > 0) {
1490b2d0f5d5SYi Yang 		OVS_NLERR(log, "nsh attribute has %d unknown bytes.", rem);
1491b2d0f5d5SYi Yang 		return -EINVAL;
1492b2d0f5d5SYi Yang 	}
1493b2d0f5d5SYi Yang 
1494b2d0f5d5SYi Yang 	if (has_md1 && has_md2) {
1495b2d0f5d5SYi Yang 		OVS_NLERR(
1496b2d0f5d5SYi Yang 		    1,
1497b2d0f5d5SYi Yang 		    "invalid nsh attribute: md1 and md2 are exclusive."
1498b2d0f5d5SYi Yang 		);
1499b2d0f5d5SYi Yang 		return -EINVAL;
1500b2d0f5d5SYi Yang 	}
1501b2d0f5d5SYi Yang 
1502b2d0f5d5SYi Yang 	if (!is_mask) {
1503b2d0f5d5SYi Yang 		if ((has_md1 && mdtype != NSH_M_TYPE1) ||
1504b2d0f5d5SYi Yang 		    (has_md2 && mdtype != NSH_M_TYPE2)) {
1505b2d0f5d5SYi Yang 			OVS_NLERR(1, "nsh attribute has unmatched MD type %d.",
1506b2d0f5d5SYi Yang 				  mdtype);
1507b2d0f5d5SYi Yang 			return -EINVAL;
1508b2d0f5d5SYi Yang 		}
1509b2d0f5d5SYi Yang 
1510b2d0f5d5SYi Yang 		if (is_push_nsh &&
1511b2d0f5d5SYi Yang 		    (!has_base || (!has_md1 && !has_md2))) {
1512b2d0f5d5SYi Yang 			OVS_NLERR(
1513b2d0f5d5SYi Yang 			    1,
1514b2d0f5d5SYi Yang 			    "push_nsh: missing base or metadata attributes"
1515b2d0f5d5SYi Yang 			);
1516b2d0f5d5SYi Yang 			return -EINVAL;
1517b2d0f5d5SYi Yang 		}
1518b2d0f5d5SYi Yang 	}
1519b2d0f5d5SYi Yang 
1520b2d0f5d5SYi Yang 	return 0;
1521b2d0f5d5SYi Yang }
1522b2d0f5d5SYi Yang 
ovs_key_from_nlattrs(struct net * net,struct sw_flow_match * match,u64 attrs,const struct nlattr ** a,bool is_mask,bool log)1523c2ac6673SJoe Stringer static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
1524c2ac6673SJoe Stringer 				u64 attrs, const struct nlattr **a,
1525c2ac6673SJoe Stringer 				bool is_mask, bool log)
1526e6445719SPravin B Shelar {
1527e6445719SPravin B Shelar 	int err;
1528e6445719SPravin B Shelar 
1529c2ac6673SJoe Stringer 	err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log);
1530e6445719SPravin B Shelar 	if (err)
1531e6445719SPravin B Shelar 		return err;
1532e6445719SPravin B Shelar 
1533e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ETHERNET)) {
1534e6445719SPravin B Shelar 		const struct ovs_key_ethernet *eth_key;
1535e6445719SPravin B Shelar 
1536e6445719SPravin B Shelar 		eth_key = nla_data(a[OVS_KEY_ATTR_ETHERNET]);
1537e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, eth.src,
1538e6445719SPravin B Shelar 				eth_key->eth_src, ETH_ALEN, is_mask);
1539e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, eth.dst,
1540e6445719SPravin B Shelar 				eth_key->eth_dst, ETH_ALEN, is_mask);
1541e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
1542e6445719SPravin B Shelar 
1543e6445719SPravin B Shelar 		if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
1544018c1ddaSEric Garver 			/* VLAN attribute is always parsed before getting here since it
1545018c1ddaSEric Garver 			 * may occur multiple times.
1546018c1ddaSEric Garver 			 */
1547018c1ddaSEric Garver 			OVS_NLERR(log, "VLAN attribute unexpected.");
1548e6445719SPravin B Shelar 			return -EINVAL;
1549e6445719SPravin B Shelar 		}
1550e6445719SPravin B Shelar 
1551e6445719SPravin B Shelar 		if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
15520a6410fbSJiri Benc 			err = parse_eth_type_from_nlattrs(match, &attrs, a, is_mask,
15530a6410fbSJiri Benc 							  log);
15540a6410fbSJiri Benc 			if (err)
15550a6410fbSJiri Benc 				return err;
1556e6445719SPravin B Shelar 		} else if (!is_mask) {
1557e6445719SPravin B Shelar 			SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
1558e6445719SPravin B Shelar 		}
15590a6410fbSJiri Benc 	} else if (!match->key->eth.type) {
15600a6410fbSJiri Benc 		OVS_NLERR(log, "Either Ethernet header or EtherType is required.");
15610a6410fbSJiri Benc 		return -EINVAL;
15620a6410fbSJiri Benc 	}
1563e6445719SPravin B Shelar 
1564e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
1565e6445719SPravin B Shelar 		const struct ovs_key_ipv4 *ipv4_key;
1566e6445719SPravin B Shelar 
1567e6445719SPravin B Shelar 		ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
1568e6445719SPravin B Shelar 		if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
156905da5898SJarno Rajahalme 			OVS_NLERR(log, "IPv4 frag type %d is out of range max %d",
1570e6445719SPravin B Shelar 				  ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
1571e6445719SPravin B Shelar 			return -EINVAL;
1572e6445719SPravin B Shelar 		}
1573e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.proto,
1574e6445719SPravin B Shelar 				ipv4_key->ipv4_proto, is_mask);
1575e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.tos,
1576e6445719SPravin B Shelar 				ipv4_key->ipv4_tos, is_mask);
1577e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.ttl,
1578e6445719SPravin B Shelar 				ipv4_key->ipv4_ttl, is_mask);
1579e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.frag,
1580e6445719SPravin B Shelar 				ipv4_key->ipv4_frag, is_mask);
1581e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
1582e6445719SPravin B Shelar 				ipv4_key->ipv4_src, is_mask);
1583e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
1584e6445719SPravin B Shelar 				ipv4_key->ipv4_dst, is_mask);
1585e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
1586e6445719SPravin B Shelar 	}
1587e6445719SPravin B Shelar 
1588e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
1589e6445719SPravin B Shelar 		const struct ovs_key_ipv6 *ipv6_key;
1590e6445719SPravin B Shelar 
1591e6445719SPravin B Shelar 		ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
1592e6445719SPravin B Shelar 		if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
159305da5898SJarno Rajahalme 			OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
1594e6445719SPravin B Shelar 				  ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
1595e6445719SPravin B Shelar 			return -EINVAL;
1596e6445719SPravin B Shelar 		}
1597fecaef85SJarno Rajahalme 
1598d3052bb5SJoe Stringer 		if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
15990ed80da5SJoe Perches 			OVS_NLERR(log, "IPv6 flow label %x is out of range (max=%x)",
1600fecaef85SJarno Rajahalme 				  ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
1601fecaef85SJarno Rajahalme 			return -EINVAL;
1602fecaef85SJarno Rajahalme 		}
1603fecaef85SJarno Rajahalme 
1604e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv6.label,
1605e6445719SPravin B Shelar 				ipv6_key->ipv6_label, is_mask);
1606e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.proto,
1607e6445719SPravin B Shelar 				ipv6_key->ipv6_proto, is_mask);
1608e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.tos,
1609e6445719SPravin B Shelar 				ipv6_key->ipv6_tclass, is_mask);
1610e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.ttl,
1611e6445719SPravin B Shelar 				ipv6_key->ipv6_hlimit, is_mask);
1612e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.frag,
1613e6445719SPravin B Shelar 				ipv6_key->ipv6_frag, is_mask);
1614e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.src,
1615e6445719SPravin B Shelar 				ipv6_key->ipv6_src,
1616e6445719SPravin B Shelar 				sizeof(match->key->ipv6.addr.src),
1617e6445719SPravin B Shelar 				is_mask);
1618e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.dst,
1619e6445719SPravin B Shelar 				ipv6_key->ipv6_dst,
1620e6445719SPravin B Shelar 				sizeof(match->key->ipv6.addr.dst),
1621e6445719SPravin B Shelar 				is_mask);
1622e6445719SPravin B Shelar 
1623e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
1624e6445719SPravin B Shelar 	}
1625e6445719SPravin B Shelar 
162628a3f060SToms Atteka 	if (attrs & (1ULL << OVS_KEY_ATTR_IPV6_EXTHDRS)) {
162728a3f060SToms Atteka 		const struct ovs_key_ipv6_exthdrs *ipv6_exthdrs_key;
162828a3f060SToms Atteka 
162928a3f060SToms Atteka 		ipv6_exthdrs_key = nla_data(a[OVS_KEY_ATTR_IPV6_EXTHDRS]);
163028a3f060SToms Atteka 
163128a3f060SToms Atteka 		SW_FLOW_KEY_PUT(match, ipv6.exthdrs,
163228a3f060SToms Atteka 				ipv6_exthdrs_key->hdrs, is_mask);
163328a3f060SToms Atteka 
163428a3f060SToms Atteka 		attrs &= ~(1ULL << OVS_KEY_ATTR_IPV6_EXTHDRS);
163528a3f060SToms Atteka 	}
163628a3f060SToms Atteka 
1637e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
1638e6445719SPravin B Shelar 		const struct ovs_key_arp *arp_key;
1639e6445719SPravin B Shelar 
1640e6445719SPravin B Shelar 		arp_key = nla_data(a[OVS_KEY_ATTR_ARP]);
1641e6445719SPravin B Shelar 		if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
164205da5898SJarno Rajahalme 			OVS_NLERR(log, "Unknown ARP opcode (opcode=%d).",
1643e6445719SPravin B Shelar 				  arp_key->arp_op);
1644e6445719SPravin B Shelar 			return -EINVAL;
1645e6445719SPravin B Shelar 		}
1646e6445719SPravin B Shelar 
1647e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
1648e6445719SPravin B Shelar 				arp_key->arp_sip, is_mask);
1649e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
1650e6445719SPravin B Shelar 			arp_key->arp_tip, is_mask);
1651e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.proto,
1652e6445719SPravin B Shelar 				ntohs(arp_key->arp_op), is_mask);
1653e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.sha,
1654e6445719SPravin B Shelar 				arp_key->arp_sha, ETH_ALEN, is_mask);
1655e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.tha,
1656e6445719SPravin B Shelar 				arp_key->arp_tha, ETH_ALEN, is_mask);
1657e6445719SPravin B Shelar 
1658e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ARP);
1659e6445719SPravin B Shelar 	}
1660e6445719SPravin B Shelar 
1661b2d0f5d5SYi Yang 	if (attrs & (1 << OVS_KEY_ATTR_NSH)) {
1662b2d0f5d5SYi Yang 		if (nsh_key_put_from_nlattr(a[OVS_KEY_ATTR_NSH], match,
1663b2d0f5d5SYi Yang 					    is_mask, false, log) < 0)
1664b2d0f5d5SYi Yang 			return -EINVAL;
1665b2d0f5d5SYi Yang 		attrs &= ~(1 << OVS_KEY_ATTR_NSH);
1666b2d0f5d5SYi Yang 	}
1667b2d0f5d5SYi Yang 
166825cd9ba0SSimon Horman 	if (attrs & (1 << OVS_KEY_ATTR_MPLS)) {
166925cd9ba0SSimon Horman 		const struct ovs_key_mpls *mpls_key;
1670fbdcdd78SMartin Varghese 		u32 hdr_len;
1671fbdcdd78SMartin Varghese 		u32 label_count, label_count_mask, i;
167225cd9ba0SSimon Horman 
167325cd9ba0SSimon Horman 		mpls_key = nla_data(a[OVS_KEY_ATTR_MPLS]);
1674fbdcdd78SMartin Varghese 		hdr_len = nla_len(a[OVS_KEY_ATTR_MPLS]);
1675fbdcdd78SMartin Varghese 		label_count = hdr_len / sizeof(struct ovs_key_mpls);
1676fbdcdd78SMartin Varghese 
1677fbdcdd78SMartin Varghese 		if (label_count == 0 || label_count > MPLS_LABEL_DEPTH ||
1678fbdcdd78SMartin Varghese 		    hdr_len % sizeof(struct ovs_key_mpls))
1679fbdcdd78SMartin Varghese 			return -EINVAL;
1680fbdcdd78SMartin Varghese 
1681fbdcdd78SMartin Varghese 		label_count_mask =  GENMASK(label_count - 1, 0);
1682fbdcdd78SMartin Varghese 
1683fbdcdd78SMartin Varghese 		for (i = 0 ; i < label_count; i++)
1684fbdcdd78SMartin Varghese 			SW_FLOW_KEY_PUT(match, mpls.lse[i],
1685fbdcdd78SMartin Varghese 					mpls_key[i].mpls_lse, is_mask);
1686fbdcdd78SMartin Varghese 
1687fbdcdd78SMartin Varghese 		SW_FLOW_KEY_PUT(match, mpls.num_labels_mask,
1688fbdcdd78SMartin Varghese 				label_count_mask, is_mask);
168925cd9ba0SSimon Horman 
169025cd9ba0SSimon Horman 		attrs &= ~(1 << OVS_KEY_ATTR_MPLS);
169125cd9ba0SSimon Horman 	 }
169225cd9ba0SSimon Horman 
1693e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_TCP)) {
1694e6445719SPravin B Shelar 		const struct ovs_key_tcp *tcp_key;
1695e6445719SPravin B Shelar 
1696e6445719SPravin B Shelar 		tcp_key = nla_data(a[OVS_KEY_ATTR_TCP]);
16971139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src, tcp_key->tcp_src, is_mask);
16981139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst, tcp_key->tcp_dst, is_mask);
1699e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_TCP);
1700e6445719SPravin B Shelar 	}
1701e6445719SPravin B Shelar 
17025eb26b15SJarno Rajahalme 	if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
17031139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.flags,
17045eb26b15SJarno Rajahalme 				nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
17055eb26b15SJarno Rajahalme 				is_mask);
17065eb26b15SJarno Rajahalme 		attrs &= ~(1 << OVS_KEY_ATTR_TCP_FLAGS);
17075eb26b15SJarno Rajahalme 	}
17085eb26b15SJarno Rajahalme 
1709e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_UDP)) {
1710e6445719SPravin B Shelar 		const struct ovs_key_udp *udp_key;
1711e6445719SPravin B Shelar 
1712e6445719SPravin B Shelar 		udp_key = nla_data(a[OVS_KEY_ATTR_UDP]);
17131139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src, udp_key->udp_src, is_mask);
17141139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst, udp_key->udp_dst, is_mask);
1715e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_UDP);
1716e6445719SPravin B Shelar 	}
1717e6445719SPravin B Shelar 
1718e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
1719e6445719SPravin B Shelar 		const struct ovs_key_sctp *sctp_key;
1720e6445719SPravin B Shelar 
1721e6445719SPravin B Shelar 		sctp_key = nla_data(a[OVS_KEY_ATTR_SCTP]);
17221139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src, sctp_key->sctp_src, is_mask);
17231139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst, sctp_key->sctp_dst, is_mask);
1724e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_SCTP);
1725e6445719SPravin B Shelar 	}
1726e6445719SPravin B Shelar 
1727e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ICMP)) {
1728e6445719SPravin B Shelar 		const struct ovs_key_icmp *icmp_key;
1729e6445719SPravin B Shelar 
1730e6445719SPravin B Shelar 		icmp_key = nla_data(a[OVS_KEY_ATTR_ICMP]);
17311139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src,
1732e6445719SPravin B Shelar 				htons(icmp_key->icmp_type), is_mask);
17331139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst,
1734e6445719SPravin B Shelar 				htons(icmp_key->icmp_code), is_mask);
1735e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ICMP);
1736e6445719SPravin B Shelar 	}
1737e6445719SPravin B Shelar 
1738e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ICMPV6)) {
1739e6445719SPravin B Shelar 		const struct ovs_key_icmpv6 *icmpv6_key;
1740e6445719SPravin B Shelar 
1741e6445719SPravin B Shelar 		icmpv6_key = nla_data(a[OVS_KEY_ATTR_ICMPV6]);
17421139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src,
1743e6445719SPravin B Shelar 				htons(icmpv6_key->icmpv6_type), is_mask);
17441139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst,
1745e6445719SPravin B Shelar 				htons(icmpv6_key->icmpv6_code), is_mask);
1746e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ICMPV6);
1747e6445719SPravin B Shelar 	}
1748e6445719SPravin B Shelar 
1749e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ND)) {
1750e6445719SPravin B Shelar 		const struct ovs_key_nd *nd_key;
1751e6445719SPravin B Shelar 
1752e6445719SPravin B Shelar 		nd_key = nla_data(a[OVS_KEY_ATTR_ND]);
1753e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.target,
1754e6445719SPravin B Shelar 			nd_key->nd_target,
1755e6445719SPravin B Shelar 			sizeof(match->key->ipv6.nd.target),
1756e6445719SPravin B Shelar 			is_mask);
1757e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.sll,
1758e6445719SPravin B Shelar 			nd_key->nd_sll, ETH_ALEN, is_mask);
1759e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.tll,
1760e6445719SPravin B Shelar 				nd_key->nd_tll, ETH_ALEN, is_mask);
1761e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ND);
1762e6445719SPravin B Shelar 	}
1763e6445719SPravin B Shelar 
1764426cda5cSJesse Gross 	if (attrs != 0) {
176505da5898SJarno Rajahalme 		OVS_NLERR(log, "Unknown key attributes %llx",
1766426cda5cSJesse Gross 			  (unsigned long long)attrs);
1767e6445719SPravin B Shelar 		return -EINVAL;
1768426cda5cSJesse Gross 	}
1769e6445719SPravin B Shelar 
1770e6445719SPravin B Shelar 	return 0;
1771e6445719SPravin B Shelar }
1772e6445719SPravin B Shelar 
nlattr_set(struct nlattr * attr,u8 val,const struct ovs_len_tbl * tbl)177381bfe3c3SThomas Graf static void nlattr_set(struct nlattr *attr, u8 val,
177481bfe3c3SThomas Graf 		       const struct ovs_len_tbl *tbl)
1775e6445719SPravin B Shelar {
1776f47de068SPravin B Shelar 	struct nlattr *nla;
1777f47de068SPravin B Shelar 	int rem;
1778e6445719SPravin B Shelar 
1779f47de068SPravin B Shelar 	/* The nlattr stream should already have been validated */
1780f47de068SPravin B Shelar 	nla_for_each_nested(nla, attr, rem) {
178172f17bafSStefano Brivio 		if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
178272f17bafSStefano Brivio 			nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl);
178372f17bafSStefano Brivio 		else
1784f47de068SPravin B Shelar 			memset(nla_data(nla), val, nla_len(nla));
17859e384715SJoe Stringer 
17869e384715SJoe Stringer 		if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
17879e384715SJoe Stringer 			*(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
1788f47de068SPravin B Shelar 	}
1789982b5270SJesse Gross }
1790f47de068SPravin B Shelar 
mask_set_nlattr(struct nlattr * attr,u8 val)1791f47de068SPravin B Shelar static void mask_set_nlattr(struct nlattr *attr, u8 val)
1792f47de068SPravin B Shelar {
179381bfe3c3SThomas Graf 	nlattr_set(attr, val, ovs_key_lens);
1794e6445719SPravin B Shelar }
1795e6445719SPravin B Shelar 
1796e6445719SPravin B Shelar /**
1797e6445719SPravin B Shelar  * ovs_nla_get_match - parses Netlink attributes into a flow key and
1798e6445719SPravin B Shelar  * mask. In case the 'mask' is NULL, the flow is treated as exact match
1799e6445719SPravin B Shelar  * flow. Otherwise, it is treated as a wildcarded flow, except the mask
1800e6445719SPravin B Shelar  * does not include any don't care bit.
1801c2ac6673SJoe Stringer  * @net: Used to determine per-namespace field support.
1802e6445719SPravin B Shelar  * @match: receives the extracted flow match information.
180396678514SAndrew Lunn  * @nla_key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
1804e6445719SPravin B Shelar  * sequence. The fields should of the packet that triggered the creation
1805e6445719SPravin B Shelar  * of this flow.
180696678514SAndrew Lunn  * @nla_mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_*
180796678514SAndrew Lunn  * Netlink attribute specifies the mask field of the wildcarded flow.
180805da5898SJarno Rajahalme  * @log: Boolean to allow kernel error logging.  Normally true, but when
180905da5898SJarno Rajahalme  * probing for feature compatibility this should be passed in as false to
181005da5898SJarno Rajahalme  * suppress unnecessary error logging.
1811e6445719SPravin B Shelar  */
ovs_nla_get_match(struct net * net,struct sw_flow_match * match,const struct nlattr * nla_key,const struct nlattr * nla_mask,bool log)1812c2ac6673SJoe Stringer int ovs_nla_get_match(struct net *net, struct sw_flow_match *match,
1813a85311bfSPravin B Shelar 		      const struct nlattr *nla_key,
181405da5898SJarno Rajahalme 		      const struct nlattr *nla_mask,
181505da5898SJarno Rajahalme 		      bool log)
1816e6445719SPravin B Shelar {
1817e6445719SPravin B Shelar 	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
1818f47de068SPravin B Shelar 	struct nlattr *newmask = NULL;
1819e6445719SPravin B Shelar 	u64 key_attrs = 0;
1820e6445719SPravin B Shelar 	u64 mask_attrs = 0;
1821e6445719SPravin B Shelar 	int err;
1822e6445719SPravin B Shelar 
182305da5898SJarno Rajahalme 	err = parse_flow_nlattrs(nla_key, a, &key_attrs, log);
1824e6445719SPravin B Shelar 	if (err)
1825e6445719SPravin B Shelar 		return err;
1826e6445719SPravin B Shelar 
1827018c1ddaSEric Garver 	err = parse_vlan_from_nlattrs(match, &key_attrs, a, false, log);
1828e6445719SPravin B Shelar 	if (err)
1829e6445719SPravin B Shelar 		return err;
1830e6445719SPravin B Shelar 
1831c2ac6673SJoe Stringer 	err = ovs_key_from_nlattrs(net, match, key_attrs, a, false, log);
1832e6445719SPravin B Shelar 	if (err)
1833e6445719SPravin B Shelar 		return err;
1834e6445719SPravin B Shelar 
1835a85311bfSPravin B Shelar 	if (match->mask) {
1836a85311bfSPravin B Shelar 		if (!nla_mask) {
1837a85311bfSPravin B Shelar 			/* Create an exact match mask. We need to set to 0xff
1838a85311bfSPravin B Shelar 			 * all the 'match->mask' fields that have been touched
1839a85311bfSPravin B Shelar 			 * in 'match->key'. We cannot simply memset
1840a85311bfSPravin B Shelar 			 * 'match->mask', because padding bytes and fields not
1841a85311bfSPravin B Shelar 			 * specified in 'match->key' should be left to 0.
1842a85311bfSPravin B Shelar 			 * Instead, we use a stream of netlink attributes,
1843a85311bfSPravin B Shelar 			 * copied from 'key' and set to 0xff.
1844a85311bfSPravin B Shelar 			 * ovs_key_from_nlattrs() will take care of filling
1845a85311bfSPravin B Shelar 			 * 'match->mask' appropriately.
1846f47de068SPravin B Shelar 			 */
1847a85311bfSPravin B Shelar 			newmask = kmemdup(nla_key,
1848a85311bfSPravin B Shelar 					  nla_total_size(nla_len(nla_key)),
1849f47de068SPravin B Shelar 					  GFP_KERNEL);
1850f47de068SPravin B Shelar 			if (!newmask)
1851f47de068SPravin B Shelar 				return -ENOMEM;
1852f47de068SPravin B Shelar 
1853f47de068SPravin B Shelar 			mask_set_nlattr(newmask, 0xff);
1854f47de068SPravin B Shelar 
1855a85311bfSPravin B Shelar 			/* The userspace does not send tunnel attributes that
1856a85311bfSPravin B Shelar 			 * are 0, but we should not wildcard them nonetheless.
1857f47de068SPravin B Shelar 			 */
185800a93babSJiri Benc 			if (match->key->tun_proto)
1859a85311bfSPravin B Shelar 				SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
1860a85311bfSPravin B Shelar 							 0xff, true);
1861f47de068SPravin B Shelar 
1862a85311bfSPravin B Shelar 			nla_mask = newmask;
1863f47de068SPravin B Shelar 		}
1864f47de068SPravin B Shelar 
186505da5898SJarno Rajahalme 		err = parse_flow_mask_nlattrs(nla_mask, a, &mask_attrs, log);
1866e6445719SPravin B Shelar 		if (err)
1867f47de068SPravin B Shelar 			goto free_newmask;
1868e6445719SPravin B Shelar 
1869a85311bfSPravin B Shelar 		/* Always match on tci. */
1870018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.vlan.tci, htons(0xffff), true);
1871018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.cvlan.tci, htons(0xffff), true);
1872a85311bfSPravin B Shelar 
1873018c1ddaSEric Garver 		err = parse_vlan_from_nlattrs(match, &mask_attrs, a, true, log);
1874f47de068SPravin B Shelar 		if (err)
1875f47de068SPravin B Shelar 			goto free_newmask;
1876e6445719SPravin B Shelar 
1877c2ac6673SJoe Stringer 		err = ovs_key_from_nlattrs(net, match, mask_attrs, a, true,
1878c2ac6673SJoe Stringer 					   log);
1879e6445719SPravin B Shelar 		if (err)
1880f47de068SPravin B Shelar 			goto free_newmask;
1881e6445719SPravin B Shelar 	}
1882e6445719SPravin B Shelar 
188305da5898SJarno Rajahalme 	if (!match_validate(match, key_attrs, mask_attrs, log))
1884f47de068SPravin B Shelar 		err = -EINVAL;
1885e6445719SPravin B Shelar 
1886f47de068SPravin B Shelar free_newmask:
1887f47de068SPravin B Shelar 	kfree(newmask);
1888f47de068SPravin B Shelar 	return err;
1889e6445719SPravin B Shelar }
1890e6445719SPravin B Shelar 
get_ufid_len(const struct nlattr * attr,bool log)189174ed7ab9SJoe Stringer static size_t get_ufid_len(const struct nlattr *attr, bool log)
189274ed7ab9SJoe Stringer {
189374ed7ab9SJoe Stringer 	size_t len;
189474ed7ab9SJoe Stringer 
189574ed7ab9SJoe Stringer 	if (!attr)
189674ed7ab9SJoe Stringer 		return 0;
189774ed7ab9SJoe Stringer 
189874ed7ab9SJoe Stringer 	len = nla_len(attr);
189974ed7ab9SJoe Stringer 	if (len < 1 || len > MAX_UFID_LENGTH) {
190074ed7ab9SJoe Stringer 		OVS_NLERR(log, "ufid size %u bytes exceeds the range (1, %d)",
190174ed7ab9SJoe Stringer 			  nla_len(attr), MAX_UFID_LENGTH);
190274ed7ab9SJoe Stringer 		return 0;
190374ed7ab9SJoe Stringer 	}
190474ed7ab9SJoe Stringer 
190574ed7ab9SJoe Stringer 	return len;
190674ed7ab9SJoe Stringer }
190774ed7ab9SJoe Stringer 
190874ed7ab9SJoe Stringer /* Initializes 'flow->ufid', returning true if 'attr' contains a valid UFID,
190974ed7ab9SJoe Stringer  * or false otherwise.
191074ed7ab9SJoe Stringer  */
ovs_nla_get_ufid(struct sw_flow_id * sfid,const struct nlattr * attr,bool log)191174ed7ab9SJoe Stringer bool ovs_nla_get_ufid(struct sw_flow_id *sfid, const struct nlattr *attr,
191274ed7ab9SJoe Stringer 		      bool log)
191374ed7ab9SJoe Stringer {
191474ed7ab9SJoe Stringer 	sfid->ufid_len = get_ufid_len(attr, log);
191574ed7ab9SJoe Stringer 	if (sfid->ufid_len)
191674ed7ab9SJoe Stringer 		memcpy(sfid->ufid, nla_data(attr), sfid->ufid_len);
191774ed7ab9SJoe Stringer 
191874ed7ab9SJoe Stringer 	return sfid->ufid_len;
191974ed7ab9SJoe Stringer }
192074ed7ab9SJoe Stringer 
ovs_nla_get_identifier(struct sw_flow_id * sfid,const struct nlattr * ufid,const struct sw_flow_key * key,bool log)192174ed7ab9SJoe Stringer int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
192274ed7ab9SJoe Stringer 			   const struct sw_flow_key *key, bool log)
192374ed7ab9SJoe Stringer {
192474ed7ab9SJoe Stringer 	struct sw_flow_key *new_key;
192574ed7ab9SJoe Stringer 
192674ed7ab9SJoe Stringer 	if (ovs_nla_get_ufid(sfid, ufid, log))
192774ed7ab9SJoe Stringer 		return 0;
192874ed7ab9SJoe Stringer 
192974ed7ab9SJoe Stringer 	/* If UFID was not provided, use unmasked key. */
193074ed7ab9SJoe Stringer 	new_key = kmalloc(sizeof(*new_key), GFP_KERNEL);
193174ed7ab9SJoe Stringer 	if (!new_key)
193274ed7ab9SJoe Stringer 		return -ENOMEM;
193374ed7ab9SJoe Stringer 	memcpy(new_key, key, sizeof(*key));
193474ed7ab9SJoe Stringer 	sfid->unmasked_key = new_key;
193574ed7ab9SJoe Stringer 
193674ed7ab9SJoe Stringer 	return 0;
193774ed7ab9SJoe Stringer }
193874ed7ab9SJoe Stringer 
ovs_nla_get_ufid_flags(const struct nlattr * attr)193974ed7ab9SJoe Stringer u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
194074ed7ab9SJoe Stringer {
194174ed7ab9SJoe Stringer 	return attr ? nla_get_u32(attr) : 0;
194274ed7ab9SJoe Stringer }
194374ed7ab9SJoe Stringer 
1944e6445719SPravin B Shelar /**
1945e6445719SPravin B Shelar  * ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
19469dd7f890SJarno Rajahalme  * @net: Network namespace.
19479dd7f890SJarno Rajahalme  * @key: Receives extracted in_port, priority, tun_key, skb_mark and conntrack
19489dd7f890SJarno Rajahalme  * metadata.
19499dd7f890SJarno Rajahalme  * @a: Array of netlink attributes holding parsed %OVS_KEY_ATTR_* Netlink
19509dd7f890SJarno Rajahalme  * attributes.
19519dd7f890SJarno Rajahalme  * @attrs: Bit mask for the netlink attributes included in @a.
195205da5898SJarno Rajahalme  * @log: Boolean to allow kernel error logging.  Normally true, but when
195305da5898SJarno Rajahalme  * probing for feature compatibility this should be passed in as false to
195405da5898SJarno Rajahalme  * suppress unnecessary error logging.
1955e6445719SPravin B Shelar  *
1956e6445719SPravin B Shelar  * This parses a series of Netlink attributes that form a flow key, which must
1957e6445719SPravin B Shelar  * take the same form accepted by flow_from_nlattrs(), but only enough of it to
1958e6445719SPravin B Shelar  * get the metadata, that is, the parts of the flow key that cannot be
1959e6445719SPravin B Shelar  * extracted from the packet itself.
19609dd7f890SJarno Rajahalme  *
19619dd7f890SJarno Rajahalme  * This must be called before the packet key fields are filled in 'key'.
1962e6445719SPravin B Shelar  */
1963e6445719SPravin B Shelar 
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)19649dd7f890SJarno Rajahalme int ovs_nla_get_flow_metadata(struct net *net,
19659dd7f890SJarno Rajahalme 			      const struct nlattr *a[OVS_KEY_ATTR_MAX + 1],
19669dd7f890SJarno Rajahalme 			      u64 attrs, struct sw_flow_key *key, bool log)
1967e6445719SPravin B Shelar {
196883c8df26SPravin B Shelar 	struct sw_flow_match match;
1969e6445719SPravin B Shelar 
1970e6445719SPravin B Shelar 	memset(&match, 0, sizeof(match));
197183c8df26SPravin B Shelar 	match.key = key;
1972e6445719SPravin B Shelar 
1973316d4d78SJarno Rajahalme 	key->ct_state = 0;
1974316d4d78SJarno Rajahalme 	key->ct_zone = 0;
1975316d4d78SJarno Rajahalme 	key->ct_orig_proto = 0;
19767f8a436eSJoe Stringer 	memset(&key->ct, 0, sizeof(key->ct));
19779dd7f890SJarno Rajahalme 	memset(&key->ipv4.ct_orig, 0, sizeof(key->ipv4.ct_orig));
19789dd7f890SJarno Rajahalme 	memset(&key->ipv6.ct_orig, 0, sizeof(key->ipv6.ct_orig));
19799dd7f890SJarno Rajahalme 
198083c8df26SPravin B Shelar 	key->phy.in_port = DP_MAX_PORTS;
1981e6445719SPravin B Shelar 
1982c2ac6673SJoe Stringer 	return metadata_from_nlattrs(net, &match, &attrs, a, false, log);
1983e6445719SPravin B Shelar }
1984e6445719SPravin B Shelar 
ovs_nla_put_vlan(struct sk_buff * skb,const struct vlan_head * vh,bool is_mask)1985018c1ddaSEric Garver static int ovs_nla_put_vlan(struct sk_buff *skb, const struct vlan_head *vh,
1986018c1ddaSEric Garver 			    bool is_mask)
1987018c1ddaSEric Garver {
1988018c1ddaSEric Garver 	__be16 eth_type = !is_mask ? vh->tpid : htons(0xffff);
1989018c1ddaSEric Garver 
1990018c1ddaSEric Garver 	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
1991018c1ddaSEric Garver 	    nla_put_be16(skb, OVS_KEY_ATTR_VLAN, vh->tci))
1992018c1ddaSEric Garver 		return -EMSGSIZE;
1993018c1ddaSEric Garver 	return 0;
1994018c1ddaSEric Garver }
1995018c1ddaSEric Garver 
nsh_key_to_nlattr(const struct ovs_key_nsh * nsh,bool is_mask,struct sk_buff * skb)1996b2d0f5d5SYi Yang static int nsh_key_to_nlattr(const struct ovs_key_nsh *nsh, bool is_mask,
1997b2d0f5d5SYi Yang 			     struct sk_buff *skb)
1998b2d0f5d5SYi Yang {
1999b2d0f5d5SYi Yang 	struct nlattr *start;
2000b2d0f5d5SYi Yang 
2001ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_KEY_ATTR_NSH);
2002b2d0f5d5SYi Yang 	if (!start)
2003b2d0f5d5SYi Yang 		return -EMSGSIZE;
2004b2d0f5d5SYi Yang 
2005b2d0f5d5SYi Yang 	if (nla_put(skb, OVS_NSH_KEY_ATTR_BASE, sizeof(nsh->base), &nsh->base))
2006b2d0f5d5SYi Yang 		goto nla_put_failure;
2007b2d0f5d5SYi Yang 
2008b2d0f5d5SYi Yang 	if (is_mask || nsh->base.mdtype == NSH_M_TYPE1) {
2009b2d0f5d5SYi Yang 		if (nla_put(skb, OVS_NSH_KEY_ATTR_MD1,
2010b2d0f5d5SYi Yang 			    sizeof(nsh->context), nsh->context))
2011b2d0f5d5SYi Yang 			goto nla_put_failure;
2012b2d0f5d5SYi Yang 	}
2013b2d0f5d5SYi Yang 
2014b2d0f5d5SYi Yang 	/* Don't support MD type 2 yet */
2015b2d0f5d5SYi Yang 
2016b2d0f5d5SYi Yang 	nla_nest_end(skb, start);
2017b2d0f5d5SYi Yang 
2018b2d0f5d5SYi Yang 	return 0;
2019b2d0f5d5SYi Yang 
2020b2d0f5d5SYi Yang nla_put_failure:
2021b2d0f5d5SYi Yang 	return -EMSGSIZE;
2022b2d0f5d5SYi Yang }
2023b2d0f5d5SYi Yang 
__ovs_nla_put_key(const struct sw_flow_key * swkey,const struct sw_flow_key * output,bool is_mask,struct sk_buff * skb)20245b4237bbSJoe Stringer static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
20255b4237bbSJoe Stringer 			     const struct sw_flow_key *output, bool is_mask,
20265b4237bbSJoe Stringer 			     struct sk_buff *skb)
2027e6445719SPravin B Shelar {
2028e6445719SPravin B Shelar 	struct ovs_key_ethernet *eth_key;
2029018c1ddaSEric Garver 	struct nlattr *nla;
2030018c1ddaSEric Garver 	struct nlattr *encap = NULL;
2031018c1ddaSEric Garver 	struct nlattr *in_encap = NULL;
2032e6445719SPravin B Shelar 
2033971427f3SAndy Zhou 	if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
2034971427f3SAndy Zhou 		goto nla_put_failure;
2035971427f3SAndy Zhou 
2036971427f3SAndy Zhou 	if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash))
2037971427f3SAndy Zhou 		goto nla_put_failure;
2038971427f3SAndy Zhou 
2039e6445719SPravin B Shelar 	if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
2040e6445719SPravin B Shelar 		goto nla_put_failure;
2041e6445719SPravin B Shelar 
204200a93babSJiri Benc 	if ((swkey->tun_proto || is_mask)) {
2043d91641d9SThomas Graf 		const void *opts = NULL;
2044f5796684SJesse Gross 
20455832c4a7SAlexander Lobakin 		if (ip_tunnel_is_options_present(output->tun_key.tun_flags))
2046d91641d9SThomas Graf 			opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len);
2047f5796684SJesse Gross 
20486b26ba3aSJiri Benc 		if (ip_tun_to_nlattr(skb, &output->tun_key, opts,
204918b6f717Swenxu 				     swkey->tun_opts_len, swkey->tun_proto, 0))
2050e6445719SPravin B Shelar 			goto nla_put_failure;
2051f5796684SJesse Gross 	}
2052e6445719SPravin B Shelar 
2053e6445719SPravin B Shelar 	if (swkey->phy.in_port == DP_MAX_PORTS) {
2054e6445719SPravin B Shelar 		if (is_mask && (output->phy.in_port == 0xffff))
2055e6445719SPravin B Shelar 			if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, 0xffffffff))
2056e6445719SPravin B Shelar 				goto nla_put_failure;
2057e6445719SPravin B Shelar 	} else {
2058e6445719SPravin B Shelar 		u16 upper_u16;
2059e6445719SPravin B Shelar 		upper_u16 = !is_mask ? 0 : 0xffff;
2060e6445719SPravin B Shelar 
2061e6445719SPravin B Shelar 		if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT,
2062e6445719SPravin B Shelar 				(upper_u16 << 16) | output->phy.in_port))
2063e6445719SPravin B Shelar 			goto nla_put_failure;
2064e6445719SPravin B Shelar 	}
2065e6445719SPravin B Shelar 
2066e6445719SPravin B Shelar 	if (nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark))
2067e6445719SPravin B Shelar 		goto nla_put_failure;
2068e6445719SPravin B Shelar 
20699dd7f890SJarno Rajahalme 	if (ovs_ct_put_key(swkey, output, skb))
20707f8a436eSJoe Stringer 		goto nla_put_failure;
20717f8a436eSJoe Stringer 
20720a6410fbSJiri Benc 	if (ovs_key_mac_proto(swkey) == MAC_PROTO_ETHERNET) {
2073e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
2074e6445719SPravin B Shelar 		if (!nla)
2075e6445719SPravin B Shelar 			goto nla_put_failure;
2076e6445719SPravin B Shelar 
2077e6445719SPravin B Shelar 		eth_key = nla_data(nla);
20788c63ff09SJoe Perches 		ether_addr_copy(eth_key->eth_src, output->eth.src);
20798c63ff09SJoe Perches 		ether_addr_copy(eth_key->eth_dst, output->eth.dst);
2080e6445719SPravin B Shelar 
2081018c1ddaSEric Garver 		if (swkey->eth.vlan.tci || eth_type_vlan(swkey->eth.type)) {
2082018c1ddaSEric Garver 			if (ovs_nla_put_vlan(skb, &output->eth.vlan, is_mask))
2083e6445719SPravin B Shelar 				goto nla_put_failure;
2084ae0be8deSMichal Kubecek 			encap = nla_nest_start_noflag(skb, OVS_KEY_ATTR_ENCAP);
2085018c1ddaSEric Garver 			if (!swkey->eth.vlan.tci)
2086e6445719SPravin B Shelar 				goto unencap;
2087018c1ddaSEric Garver 
2088018c1ddaSEric Garver 			if (swkey->eth.cvlan.tci || eth_type_vlan(swkey->eth.type)) {
2089018c1ddaSEric Garver 				if (ovs_nla_put_vlan(skb, &output->eth.cvlan, is_mask))
2090018c1ddaSEric Garver 					goto nla_put_failure;
2091ae0be8deSMichal Kubecek 				in_encap = nla_nest_start_noflag(skb,
2092ae0be8deSMichal Kubecek 								 OVS_KEY_ATTR_ENCAP);
2093018c1ddaSEric Garver 				if (!swkey->eth.cvlan.tci)
2094018c1ddaSEric Garver 					goto unencap;
2095018c1ddaSEric Garver 			}
2096018c1ddaSEric Garver 		}
2097e6445719SPravin B Shelar 
2098e6445719SPravin B Shelar 		if (swkey->eth.type == htons(ETH_P_802_2)) {
2099e6445719SPravin B Shelar 			/*
2100e6445719SPravin B Shelar 			* Ethertype 802.2 is represented in the netlink with omitted
2101e6445719SPravin B Shelar 			* OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
2102e6445719SPravin B Shelar 			* 0xffff in the mask attribute.  Ethertype can also
2103e6445719SPravin B Shelar 			* be wildcarded.
2104e6445719SPravin B Shelar 			*/
2105e6445719SPravin B Shelar 			if (is_mask && output->eth.type)
2106e6445719SPravin B Shelar 				if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
2107e6445719SPravin B Shelar 							output->eth.type))
2108e6445719SPravin B Shelar 					goto nla_put_failure;
2109e6445719SPravin B Shelar 			goto unencap;
2110e6445719SPravin B Shelar 		}
21110a6410fbSJiri Benc 	}
2112e6445719SPravin B Shelar 
2113e6445719SPravin B Shelar 	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
2114e6445719SPravin B Shelar 		goto nla_put_failure;
2115e6445719SPravin B Shelar 
2116018c1ddaSEric Garver 	if (eth_type_vlan(swkey->eth.type)) {
2117018c1ddaSEric Garver 		/* There are 3 VLAN tags, we don't know anything about the rest
2118018c1ddaSEric Garver 		 * of the packet, so truncate here.
2119018c1ddaSEric Garver 		 */
2120018c1ddaSEric Garver 		WARN_ON_ONCE(!(encap && in_encap));
2121018c1ddaSEric Garver 		goto unencap;
2122018c1ddaSEric Garver 	}
2123018c1ddaSEric Garver 
2124e6445719SPravin B Shelar 	if (swkey->eth.type == htons(ETH_P_IP)) {
2125e6445719SPravin B Shelar 		struct ovs_key_ipv4 *ipv4_key;
2126e6445719SPravin B Shelar 
2127e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV4, sizeof(*ipv4_key));
2128e6445719SPravin B Shelar 		if (!nla)
2129e6445719SPravin B Shelar 			goto nla_put_failure;
2130e6445719SPravin B Shelar 		ipv4_key = nla_data(nla);
2131e6445719SPravin B Shelar 		ipv4_key->ipv4_src = output->ipv4.addr.src;
2132e6445719SPravin B Shelar 		ipv4_key->ipv4_dst = output->ipv4.addr.dst;
2133e6445719SPravin B Shelar 		ipv4_key->ipv4_proto = output->ip.proto;
2134e6445719SPravin B Shelar 		ipv4_key->ipv4_tos = output->ip.tos;
2135e6445719SPravin B Shelar 		ipv4_key->ipv4_ttl = output->ip.ttl;
2136e6445719SPravin B Shelar 		ipv4_key->ipv4_frag = output->ip.frag;
2137e6445719SPravin B Shelar 	} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
2138e6445719SPravin B Shelar 		struct ovs_key_ipv6 *ipv6_key;
213928a3f060SToms Atteka 		struct ovs_key_ipv6_exthdrs *ipv6_exthdrs_key;
2140e6445719SPravin B Shelar 
2141e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6, sizeof(*ipv6_key));
2142e6445719SPravin B Shelar 		if (!nla)
2143e6445719SPravin B Shelar 			goto nla_put_failure;
2144e6445719SPravin B Shelar 		ipv6_key = nla_data(nla);
2145e6445719SPravin B Shelar 		memcpy(ipv6_key->ipv6_src, &output->ipv6.addr.src,
2146e6445719SPravin B Shelar 				sizeof(ipv6_key->ipv6_src));
2147e6445719SPravin B Shelar 		memcpy(ipv6_key->ipv6_dst, &output->ipv6.addr.dst,
2148e6445719SPravin B Shelar 				sizeof(ipv6_key->ipv6_dst));
2149e6445719SPravin B Shelar 		ipv6_key->ipv6_label = output->ipv6.label;
2150e6445719SPravin B Shelar 		ipv6_key->ipv6_proto = output->ip.proto;
2151e6445719SPravin B Shelar 		ipv6_key->ipv6_tclass = output->ip.tos;
2152e6445719SPravin B Shelar 		ipv6_key->ipv6_hlimit = output->ip.ttl;
2153e6445719SPravin B Shelar 		ipv6_key->ipv6_frag = output->ip.frag;
215428a3f060SToms Atteka 
215528a3f060SToms Atteka 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6_EXTHDRS,
215628a3f060SToms Atteka 				  sizeof(*ipv6_exthdrs_key));
215728a3f060SToms Atteka 		if (!nla)
215828a3f060SToms Atteka 			goto nla_put_failure;
215928a3f060SToms Atteka 		ipv6_exthdrs_key = nla_data(nla);
216028a3f060SToms Atteka 		ipv6_exthdrs_key->hdrs = output->ipv6.exthdrs;
2161b2d0f5d5SYi Yang 	} else if (swkey->eth.type == htons(ETH_P_NSH)) {
2162b2d0f5d5SYi Yang 		if (nsh_key_to_nlattr(&output->nsh, is_mask, skb))
2163b2d0f5d5SYi Yang 			goto nla_put_failure;
2164e6445719SPravin B Shelar 	} else if (swkey->eth.type == htons(ETH_P_ARP) ||
2165e6445719SPravin B Shelar 		   swkey->eth.type == htons(ETH_P_RARP)) {
2166e6445719SPravin B Shelar 		struct ovs_key_arp *arp_key;
2167e6445719SPravin B Shelar 
2168e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
2169e6445719SPravin B Shelar 		if (!nla)
2170e6445719SPravin B Shelar 			goto nla_put_failure;
2171e6445719SPravin B Shelar 		arp_key = nla_data(nla);
2172e6445719SPravin B Shelar 		memset(arp_key, 0, sizeof(struct ovs_key_arp));
2173e6445719SPravin B Shelar 		arp_key->arp_sip = output->ipv4.addr.src;
2174e6445719SPravin B Shelar 		arp_key->arp_tip = output->ipv4.addr.dst;
2175e6445719SPravin B Shelar 		arp_key->arp_op = htons(output->ip.proto);
21768c63ff09SJoe Perches 		ether_addr_copy(arp_key->arp_sha, output->ipv4.arp.sha);
21778c63ff09SJoe Perches 		ether_addr_copy(arp_key->arp_tha, output->ipv4.arp.tha);
217825cd9ba0SSimon Horman 	} else if (eth_p_mpls(swkey->eth.type)) {
2179fbdcdd78SMartin Varghese 		u8 i, num_labels;
218025cd9ba0SSimon Horman 		struct ovs_key_mpls *mpls_key;
218125cd9ba0SSimon Horman 
2182fbdcdd78SMartin Varghese 		num_labels = hweight_long(output->mpls.num_labels_mask);
2183fbdcdd78SMartin Varghese 		nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS,
2184fbdcdd78SMartin Varghese 				  num_labels * sizeof(*mpls_key));
218525cd9ba0SSimon Horman 		if (!nla)
218625cd9ba0SSimon Horman 			goto nla_put_failure;
2187fbdcdd78SMartin Varghese 
218825cd9ba0SSimon Horman 		mpls_key = nla_data(nla);
2189fbdcdd78SMartin Varghese 		for (i = 0; i < num_labels; i++)
2190fbdcdd78SMartin Varghese 			mpls_key[i].mpls_lse = output->mpls.lse[i];
2191e6445719SPravin B Shelar 	}
2192e6445719SPravin B Shelar 
2193e6445719SPravin B Shelar 	if ((swkey->eth.type == htons(ETH_P_IP) ||
2194e6445719SPravin B Shelar 	     swkey->eth.type == htons(ETH_P_IPV6)) &&
2195e6445719SPravin B Shelar 	     swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
2196e6445719SPravin B Shelar 
2197e6445719SPravin B Shelar 		if (swkey->ip.proto == IPPROTO_TCP) {
2198e6445719SPravin B Shelar 			struct ovs_key_tcp *tcp_key;
2199e6445719SPravin B Shelar 
2200e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_TCP, sizeof(*tcp_key));
2201e6445719SPravin B Shelar 			if (!nla)
2202e6445719SPravin B Shelar 				goto nla_put_failure;
2203e6445719SPravin B Shelar 			tcp_key = nla_data(nla);
22041139e241SJarno Rajahalme 			tcp_key->tcp_src = output->tp.src;
22051139e241SJarno Rajahalme 			tcp_key->tcp_dst = output->tp.dst;
22065eb26b15SJarno Rajahalme 			if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS,
22071139e241SJarno Rajahalme 					 output->tp.flags))
22085eb26b15SJarno Rajahalme 				goto nla_put_failure;
2209e6445719SPravin B Shelar 		} else if (swkey->ip.proto == IPPROTO_UDP) {
2210e6445719SPravin B Shelar 			struct ovs_key_udp *udp_key;
2211e6445719SPravin B Shelar 
2212e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_UDP, sizeof(*udp_key));
2213e6445719SPravin B Shelar 			if (!nla)
2214e6445719SPravin B Shelar 				goto nla_put_failure;
2215e6445719SPravin B Shelar 			udp_key = nla_data(nla);
22161139e241SJarno Rajahalme 			udp_key->udp_src = output->tp.src;
22171139e241SJarno Rajahalme 			udp_key->udp_dst = output->tp.dst;
2218e6445719SPravin B Shelar 		} else if (swkey->ip.proto == IPPROTO_SCTP) {
2219e6445719SPravin B Shelar 			struct ovs_key_sctp *sctp_key;
2220e6445719SPravin B Shelar 
2221e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_SCTP, sizeof(*sctp_key));
2222e6445719SPravin B Shelar 			if (!nla)
2223e6445719SPravin B Shelar 				goto nla_put_failure;
2224e6445719SPravin B Shelar 			sctp_key = nla_data(nla);
22251139e241SJarno Rajahalme 			sctp_key->sctp_src = output->tp.src;
22261139e241SJarno Rajahalme 			sctp_key->sctp_dst = output->tp.dst;
2227e6445719SPravin B Shelar 		} else if (swkey->eth.type == htons(ETH_P_IP) &&
2228e6445719SPravin B Shelar 			   swkey->ip.proto == IPPROTO_ICMP) {
2229e6445719SPravin B Shelar 			struct ovs_key_icmp *icmp_key;
2230e6445719SPravin B Shelar 
2231e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMP, sizeof(*icmp_key));
2232e6445719SPravin B Shelar 			if (!nla)
2233e6445719SPravin B Shelar 				goto nla_put_failure;
2234e6445719SPravin B Shelar 			icmp_key = nla_data(nla);
22351139e241SJarno Rajahalme 			icmp_key->icmp_type = ntohs(output->tp.src);
22361139e241SJarno Rajahalme 			icmp_key->icmp_code = ntohs(output->tp.dst);
2237e6445719SPravin B Shelar 		} else if (swkey->eth.type == htons(ETH_P_IPV6) &&
2238e6445719SPravin B Shelar 			   swkey->ip.proto == IPPROTO_ICMPV6) {
2239e6445719SPravin B Shelar 			struct ovs_key_icmpv6 *icmpv6_key;
2240e6445719SPravin B Shelar 
2241e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMPV6,
2242e6445719SPravin B Shelar 						sizeof(*icmpv6_key));
2243e6445719SPravin B Shelar 			if (!nla)
2244e6445719SPravin B Shelar 				goto nla_put_failure;
2245e6445719SPravin B Shelar 			icmpv6_key = nla_data(nla);
22461139e241SJarno Rajahalme 			icmpv6_key->icmpv6_type = ntohs(output->tp.src);
22471139e241SJarno Rajahalme 			icmpv6_key->icmpv6_code = ntohs(output->tp.dst);
2248e6445719SPravin B Shelar 
2249f19c4445SMartin Varghese 			if (swkey->tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
2250f19c4445SMartin Varghese 			    swkey->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
2251e6445719SPravin B Shelar 				struct ovs_key_nd *nd_key;
2252e6445719SPravin B Shelar 
2253e6445719SPravin B Shelar 				nla = nla_reserve(skb, OVS_KEY_ATTR_ND, sizeof(*nd_key));
2254e6445719SPravin B Shelar 				if (!nla)
2255e6445719SPravin B Shelar 					goto nla_put_failure;
2256e6445719SPravin B Shelar 				nd_key = nla_data(nla);
2257e6445719SPravin B Shelar 				memcpy(nd_key->nd_target, &output->ipv6.nd.target,
2258e6445719SPravin B Shelar 							sizeof(nd_key->nd_target));
22598c63ff09SJoe Perches 				ether_addr_copy(nd_key->nd_sll, output->ipv6.nd.sll);
22608c63ff09SJoe Perches 				ether_addr_copy(nd_key->nd_tll, output->ipv6.nd.tll);
2261e6445719SPravin B Shelar 			}
2262e6445719SPravin B Shelar 		}
2263e6445719SPravin B Shelar 	}
2264e6445719SPravin B Shelar 
2265e6445719SPravin B Shelar unencap:
2266018c1ddaSEric Garver 	if (in_encap)
2267018c1ddaSEric Garver 		nla_nest_end(skb, in_encap);
2268e6445719SPravin B Shelar 	if (encap)
2269e6445719SPravin B Shelar 		nla_nest_end(skb, encap);
2270e6445719SPravin B Shelar 
2271e6445719SPravin B Shelar 	return 0;
2272e6445719SPravin B Shelar 
2273e6445719SPravin B Shelar nla_put_failure:
2274e6445719SPravin B Shelar 	return -EMSGSIZE;
2275e6445719SPravin B Shelar }
2276e6445719SPravin B Shelar 
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)22775b4237bbSJoe Stringer int ovs_nla_put_key(const struct sw_flow_key *swkey,
22785b4237bbSJoe Stringer 		    const struct sw_flow_key *output, int attr, bool is_mask,
22795b4237bbSJoe Stringer 		    struct sk_buff *skb)
22805b4237bbSJoe Stringer {
22815b4237bbSJoe Stringer 	int err;
22825b4237bbSJoe Stringer 	struct nlattr *nla;
22835b4237bbSJoe Stringer 
2284ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, attr);
22855b4237bbSJoe Stringer 	if (!nla)
22865b4237bbSJoe Stringer 		return -EMSGSIZE;
22875b4237bbSJoe Stringer 	err = __ovs_nla_put_key(swkey, output, is_mask, skb);
22885b4237bbSJoe Stringer 	if (err)
22895b4237bbSJoe Stringer 		return err;
22905b4237bbSJoe Stringer 	nla_nest_end(skb, nla);
22915b4237bbSJoe Stringer 
22925b4237bbSJoe Stringer 	return 0;
22935b4237bbSJoe Stringer }
22945b4237bbSJoe Stringer 
22955b4237bbSJoe Stringer /* Called with ovs_mutex or RCU read lock. */
ovs_nla_put_identifier(const struct sw_flow * flow,struct sk_buff * skb)229674ed7ab9SJoe Stringer int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb)
22975b4237bbSJoe Stringer {
229874ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&flow->id))
229974ed7ab9SJoe Stringer 		return nla_put(skb, OVS_FLOW_ATTR_UFID, flow->id.ufid_len,
230074ed7ab9SJoe Stringer 			       flow->id.ufid);
230174ed7ab9SJoe Stringer 
230274ed7ab9SJoe Stringer 	return ovs_nla_put_key(flow->id.unmasked_key, flow->id.unmasked_key,
230374ed7ab9SJoe Stringer 			       OVS_FLOW_ATTR_KEY, false, skb);
230474ed7ab9SJoe Stringer }
230574ed7ab9SJoe Stringer 
230674ed7ab9SJoe Stringer /* Called with ovs_mutex or RCU read lock. */
ovs_nla_put_masked_key(const struct sw_flow * flow,struct sk_buff * skb)230774ed7ab9SJoe Stringer int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb)
230874ed7ab9SJoe Stringer {
230926ad0b83SPravin B Shelar 	return ovs_nla_put_key(&flow->key, &flow->key,
23105b4237bbSJoe Stringer 				OVS_FLOW_ATTR_KEY, false, skb);
23115b4237bbSJoe Stringer }
23125b4237bbSJoe Stringer 
23135b4237bbSJoe Stringer /* Called with ovs_mutex or RCU read lock. */
ovs_nla_put_mask(const struct sw_flow * flow,struct sk_buff * skb)23145b4237bbSJoe Stringer int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb)
23155b4237bbSJoe Stringer {
23165b4237bbSJoe Stringer 	return ovs_nla_put_key(&flow->key, &flow->mask->key,
23175b4237bbSJoe Stringer 				OVS_FLOW_ATTR_MASK, true, skb);
23185b4237bbSJoe Stringer }
23195b4237bbSJoe Stringer 
2320e6445719SPravin B Shelar #define MAX_ACTIONS_BUFSIZE	(32 * 1024)
2321e6445719SPravin B Shelar 
nla_alloc_flow_actions(int size)232267c8d22aSzhangliping static struct sw_flow_actions *nla_alloc_flow_actions(int size)
2323e6445719SPravin B Shelar {
2324e6445719SPravin B Shelar 	struct sw_flow_actions *sfa;
2325e6445719SPravin B Shelar 
232667c8d22aSzhangliping 	WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE);
2327e6445719SPravin B Shelar 
2328ab3f7828SKees Cook 	sfa = kmalloc(kmalloc_size_roundup(sizeof(*sfa) + size), GFP_KERNEL);
2329e6445719SPravin B Shelar 	if (!sfa)
2330e6445719SPravin B Shelar 		return ERR_PTR(-ENOMEM);
2331e6445719SPravin B Shelar 
2332e6445719SPravin B Shelar 	sfa->actions_len = 0;
2333e6445719SPravin B Shelar 	return sfa;
2334e6445719SPravin B Shelar }
2335e6445719SPravin B Shelar 
23361f30fb91SIlya Maximets static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len);
23371f30fb91SIlya Maximets 
ovs_nla_free_check_pkt_len_action(const struct nlattr * action)23381f30fb91SIlya Maximets static void ovs_nla_free_check_pkt_len_action(const struct nlattr *action)
23391f30fb91SIlya Maximets {
23401f30fb91SIlya Maximets 	const struct nlattr *a;
23411f30fb91SIlya Maximets 	int rem;
23421f30fb91SIlya Maximets 
23431f30fb91SIlya Maximets 	nla_for_each_nested(a, action, rem) {
23441f30fb91SIlya Maximets 		switch (nla_type(a)) {
23451f30fb91SIlya Maximets 		case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL:
23461f30fb91SIlya Maximets 		case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER:
23471f30fb91SIlya Maximets 			ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
23481f30fb91SIlya Maximets 			break;
23491f30fb91SIlya Maximets 		}
23501f30fb91SIlya Maximets 	}
23511f30fb91SIlya Maximets }
23521f30fb91SIlya Maximets 
ovs_nla_free_clone_action(const struct nlattr * action)23531f30fb91SIlya Maximets static void ovs_nla_free_clone_action(const struct nlattr *action)
23541f30fb91SIlya Maximets {
23551f30fb91SIlya Maximets 	const struct nlattr *a = nla_data(action);
23561f30fb91SIlya Maximets 	int rem = nla_len(action);
23571f30fb91SIlya Maximets 
23581f30fb91SIlya Maximets 	switch (nla_type(a)) {
23591f30fb91SIlya Maximets 	case OVS_CLONE_ATTR_EXEC:
23601f30fb91SIlya Maximets 		/* The real list of actions follows this attribute. */
23611f30fb91SIlya Maximets 		a = nla_next(a, &rem);
23621f30fb91SIlya Maximets 		ovs_nla_free_nested_actions(a, rem);
23631f30fb91SIlya Maximets 		break;
23641f30fb91SIlya Maximets 	}
23651f30fb91SIlya Maximets }
23661f30fb91SIlya Maximets 
ovs_nla_free_dec_ttl_action(const struct nlattr * action)23671f30fb91SIlya Maximets static void ovs_nla_free_dec_ttl_action(const struct nlattr *action)
23681f30fb91SIlya Maximets {
23691f30fb91SIlya Maximets 	const struct nlattr *a = nla_data(action);
23701f30fb91SIlya Maximets 
23711f30fb91SIlya Maximets 	switch (nla_type(a)) {
23721f30fb91SIlya Maximets 	case OVS_DEC_TTL_ATTR_ACTION:
23731f30fb91SIlya Maximets 		ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
23741f30fb91SIlya Maximets 		break;
23751f30fb91SIlya Maximets 	}
23761f30fb91SIlya Maximets }
23771f30fb91SIlya Maximets 
ovs_nla_free_sample_action(const struct nlattr * action)23781f30fb91SIlya Maximets static void ovs_nla_free_sample_action(const struct nlattr *action)
23791f30fb91SIlya Maximets {
23801f30fb91SIlya Maximets 	const struct nlattr *a = nla_data(action);
23811f30fb91SIlya Maximets 	int rem = nla_len(action);
23821f30fb91SIlya Maximets 
23831f30fb91SIlya Maximets 	switch (nla_type(a)) {
23841f30fb91SIlya Maximets 	case OVS_SAMPLE_ATTR_ARG:
23851f30fb91SIlya Maximets 		/* The real list of actions follows this attribute. */
23861f30fb91SIlya Maximets 		a = nla_next(a, &rem);
23871f30fb91SIlya Maximets 		ovs_nla_free_nested_actions(a, rem);
23881f30fb91SIlya Maximets 		break;
23891f30fb91SIlya Maximets 	}
23901f30fb91SIlya Maximets }
23911f30fb91SIlya Maximets 
ovs_nla_free_set_action(const struct nlattr * a)239234ae932aSThomas Graf static void ovs_nla_free_set_action(const struct nlattr *a)
239334ae932aSThomas Graf {
239434ae932aSThomas Graf 	const struct nlattr *ovs_key = nla_data(a);
239534ae932aSThomas Graf 	struct ovs_tunnel_info *ovs_tun;
239634ae932aSThomas Graf 
239734ae932aSThomas Graf 	switch (nla_type(ovs_key)) {
239834ae932aSThomas Graf 	case OVS_KEY_ATTR_TUNNEL_INFO:
239934ae932aSThomas Graf 		ovs_tun = nla_data(ovs_key);
240034ae932aSThomas Graf 		dst_release((struct dst_entry *)ovs_tun->tun_dst);
240134ae932aSThomas Graf 		break;
240234ae932aSThomas Graf 	}
240334ae932aSThomas Graf }
240434ae932aSThomas Graf 
ovs_nla_free_nested_actions(const struct nlattr * actions,int len)24051f30fb91SIlya Maximets static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
2406e6445719SPravin B Shelar {
240734ae932aSThomas Graf 	const struct nlattr *a;
240834ae932aSThomas Graf 	int rem;
240934ae932aSThomas Graf 
24101f30fb91SIlya Maximets 	/* Whenever new actions are added, the need to update this
24111f30fb91SIlya Maximets 	 * function should be considered.
24121f30fb91SIlya Maximets 	 */
2413aae0b82bSAdrian Moreno 	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 25);
24141f30fb91SIlya Maximets 
24151f30fb91SIlya Maximets 	if (!actions)
241634ae932aSThomas Graf 		return;
241734ae932aSThomas Graf 
24181f30fb91SIlya Maximets 	nla_for_each_attr(a, actions, len, rem) {
241934ae932aSThomas Graf 		switch (nla_type(a)) {
24201f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
24211f30fb91SIlya Maximets 			ovs_nla_free_check_pkt_len_action(a);
242234ae932aSThomas Graf 			break;
24231f30fb91SIlya Maximets 
24241f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_CLONE:
24251f30fb91SIlya Maximets 			ovs_nla_free_clone_action(a);
24261f30fb91SIlya Maximets 			break;
24271f30fb91SIlya Maximets 
24287f8a436eSJoe Stringer 		case OVS_ACTION_ATTR_CT:
24297f8a436eSJoe Stringer 			ovs_ct_free_action(a);
24307f8a436eSJoe Stringer 			break;
24311f30fb91SIlya Maximets 
24321f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_DEC_TTL:
24331f30fb91SIlya Maximets 			ovs_nla_free_dec_ttl_action(a);
24341f30fb91SIlya Maximets 			break;
24351f30fb91SIlya Maximets 
24361f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_SAMPLE:
24371f30fb91SIlya Maximets 			ovs_nla_free_sample_action(a);
24381f30fb91SIlya Maximets 			break;
24391f30fb91SIlya Maximets 
24401f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_SET:
24411f30fb91SIlya Maximets 			ovs_nla_free_set_action(a);
24421f30fb91SIlya Maximets 			break;
24431f30fb91SIlya Maximets 		}
244434ae932aSThomas Graf 	}
244534ae932aSThomas Graf }
244634ae932aSThomas Graf 
ovs_nla_free_flow_actions(struct sw_flow_actions * sf_acts)24471f30fb91SIlya Maximets void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
24481f30fb91SIlya Maximets {
24491f30fb91SIlya Maximets 	if (!sf_acts)
24501f30fb91SIlya Maximets 		return;
24511f30fb91SIlya Maximets 
24521f30fb91SIlya Maximets 	ovs_nla_free_nested_actions(sf_acts->actions, sf_acts->actions_len);
245334ae932aSThomas Graf 	kfree(sf_acts);
245434ae932aSThomas Graf }
245534ae932aSThomas Graf 
__ovs_nla_free_flow_actions(struct rcu_head * head)245634ae932aSThomas Graf static void __ovs_nla_free_flow_actions(struct rcu_head *head)
245734ae932aSThomas Graf {
245834ae932aSThomas Graf 	ovs_nla_free_flow_actions(container_of(head, struct sw_flow_actions, rcu));
245934ae932aSThomas Graf }
246034ae932aSThomas Graf 
246134ae932aSThomas Graf /* Schedules 'sf_acts' to be freed after the next RCU grace period.
246234ae932aSThomas Graf  * The caller must hold rcu_read_lock for this to be sensible. */
ovs_nla_free_flow_actions_rcu(struct sw_flow_actions * sf_acts)246334ae932aSThomas Graf void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *sf_acts)
246434ae932aSThomas Graf {
246534ae932aSThomas Graf 	call_rcu(&sf_acts->rcu, __ovs_nla_free_flow_actions);
2466e6445719SPravin B Shelar }
2467e6445719SPravin B Shelar 
reserve_sfa_size(struct sw_flow_actions ** sfa,int attr_len,bool log)2468e6445719SPravin B Shelar static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
246905da5898SJarno Rajahalme 				       int attr_len, bool log)
2470e6445719SPravin B Shelar {
2471e6445719SPravin B Shelar 
2472e6445719SPravin B Shelar 	struct sw_flow_actions *acts;
2473e6445719SPravin B Shelar 	int new_acts_size;
2474f28cd2afSAndrea Righi 	size_t req_size = NLA_ALIGN(attr_len);
2475e6445719SPravin B Shelar 	int next_offset = offsetof(struct sw_flow_actions, actions) +
2476e6445719SPravin B Shelar 					(*sfa)->actions_len;
2477e6445719SPravin B Shelar 
2478e6445719SPravin B Shelar 	if (req_size <= (ksize(*sfa) - next_offset))
2479e6445719SPravin B Shelar 		goto out;
2480e6445719SPravin B Shelar 
2481f28cd2afSAndrea Righi 	new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
2482e6445719SPravin B Shelar 
2483e6445719SPravin B Shelar 	if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
2484cefa91b2SPaolo Valerio 		if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) {
248567c8d22aSzhangliping 			OVS_NLERR(log, "Flow action size exceeds max %u",
248667c8d22aSzhangliping 				  MAX_ACTIONS_BUFSIZE);
2487e6445719SPravin B Shelar 			return ERR_PTR(-EMSGSIZE);
248867c8d22aSzhangliping 		}
2489e6445719SPravin B Shelar 		new_acts_size = MAX_ACTIONS_BUFSIZE;
2490e6445719SPravin B Shelar 	}
2491e6445719SPravin B Shelar 
249267c8d22aSzhangliping 	acts = nla_alloc_flow_actions(new_acts_size);
2493e6445719SPravin B Shelar 	if (IS_ERR(acts))
2494*b26b6449SYan Zhen 		return ERR_CAST(acts);
2495e6445719SPravin B Shelar 
2496e6445719SPravin B Shelar 	memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len);
2497e6445719SPravin B Shelar 	acts->actions_len = (*sfa)->actions_len;
24988e2fed1cSJoe Stringer 	acts->orig_len = (*sfa)->orig_len;
2499e6445719SPravin B Shelar 	kfree(*sfa);
2500e6445719SPravin B Shelar 	*sfa = acts;
2501e6445719SPravin B Shelar 
2502e6445719SPravin B Shelar out:
2503e6445719SPravin B Shelar 	(*sfa)->actions_len += req_size;
2504e6445719SPravin B Shelar 	return  (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
2505e6445719SPravin B Shelar }
2506e6445719SPravin B Shelar 
__add_action(struct sw_flow_actions ** sfa,int attrtype,void * data,int len,bool log)2507f0b128c1SJesse Gross static struct nlattr *__add_action(struct sw_flow_actions **sfa,
250805da5898SJarno Rajahalme 				   int attrtype, void *data, int len, bool log)
2509e6445719SPravin B Shelar {
2510e6445719SPravin B Shelar 	struct nlattr *a;
2511e6445719SPravin B Shelar 
251205da5898SJarno Rajahalme 	a = reserve_sfa_size(sfa, nla_attr_size(len), log);
2513e6445719SPravin B Shelar 	if (IS_ERR(a))
2514f0b128c1SJesse Gross 		return a;
2515e6445719SPravin B Shelar 
2516e6445719SPravin B Shelar 	a->nla_type = attrtype;
2517e6445719SPravin B Shelar 	a->nla_len = nla_attr_size(len);
2518e6445719SPravin B Shelar 
2519e6445719SPravin B Shelar 	if (data)
2520e6445719SPravin B Shelar 		memcpy(nla_data(a), data, len);
2521e6445719SPravin B Shelar 	memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));
2522e6445719SPravin B Shelar 
2523f0b128c1SJesse Gross 	return a;
2524f0b128c1SJesse Gross }
2525f0b128c1SJesse Gross 
ovs_nla_add_action(struct sw_flow_actions ** sfa,int attrtype,void * data,int len,bool log)25267f8a436eSJoe Stringer int ovs_nla_add_action(struct sw_flow_actions **sfa, int attrtype, void *data,
25277f8a436eSJoe Stringer 		       int len, bool log)
2528f0b128c1SJesse Gross {
2529f0b128c1SJesse Gross 	struct nlattr *a;
2530f0b128c1SJesse Gross 
253105da5898SJarno Rajahalme 	a = __add_action(sfa, attrtype, data, len, log);
2532f0b128c1SJesse Gross 
2533f35423c1SFabian Frederick 	return PTR_ERR_OR_ZERO(a);
2534e6445719SPravin B Shelar }
2535e6445719SPravin B Shelar 
add_nested_action_start(struct sw_flow_actions ** sfa,int attrtype,bool log)2536e6445719SPravin B Shelar static inline int add_nested_action_start(struct sw_flow_actions **sfa,
253705da5898SJarno Rajahalme 					  int attrtype, bool log)
2538e6445719SPravin B Shelar {
2539e6445719SPravin B Shelar 	int used = (*sfa)->actions_len;
2540e6445719SPravin B Shelar 	int err;
2541e6445719SPravin B Shelar 
25427f8a436eSJoe Stringer 	err = ovs_nla_add_action(sfa, attrtype, NULL, 0, log);
2543e6445719SPravin B Shelar 	if (err)
2544e6445719SPravin B Shelar 		return err;
2545e6445719SPravin B Shelar 
2546e6445719SPravin B Shelar 	return used;
2547e6445719SPravin B Shelar }
2548e6445719SPravin B Shelar 
add_nested_action_end(struct sw_flow_actions * sfa,int st_offset)2549e6445719SPravin B Shelar static inline void add_nested_action_end(struct sw_flow_actions *sfa,
2550e6445719SPravin B Shelar 					 int st_offset)
2551e6445719SPravin B Shelar {
2552e6445719SPravin B Shelar 	struct nlattr *a = (struct nlattr *) ((unsigned char *)sfa->actions +
2553e6445719SPravin B Shelar 							       st_offset);
2554e6445719SPravin B Shelar 
2555e6445719SPravin B Shelar 	a->nla_len = sfa->actions_len - st_offset;
2556e6445719SPravin B Shelar }
2557e6445719SPravin B Shelar 
25587f8a436eSJoe Stringer static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
255925cd9ba0SSimon Horman 				  const struct sw_flow_key *key,
2560798c1661Sandy zhou 				  struct sw_flow_actions **sfa,
2561fbdcdd78SMartin Varghese 				  __be16 eth_type, __be16 vlan_tci,
25626e2f90d3SAaron Conole 				  u32 mpls_label_count, bool log,
25636e2f90d3SAaron Conole 				  u32 depth);
256425cd9ba0SSimon Horman 
validate_and_copy_sample(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,bool last,u32 depth)25657f8a436eSJoe Stringer static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
2566798c1661Sandy zhou 				    const struct sw_flow_key *key,
256725cd9ba0SSimon Horman 				    struct sw_flow_actions **sfa,
2568798c1661Sandy zhou 				    __be16 eth_type, __be16 vlan_tci,
25696e2f90d3SAaron Conole 				    u32 mpls_label_count, bool log, bool last,
25706e2f90d3SAaron Conole 				    u32 depth)
2571e6445719SPravin B Shelar {
2572e6445719SPravin B Shelar 	const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
2573e6445719SPravin B Shelar 	const struct nlattr *probability, *actions;
2574e6445719SPravin B Shelar 	const struct nlattr *a;
2575798c1661Sandy zhou 	int rem, start, err;
2576798c1661Sandy zhou 	struct sample_arg arg;
2577e6445719SPravin B Shelar 
2578e6445719SPravin B Shelar 	memset(attrs, 0, sizeof(attrs));
2579e6445719SPravin B Shelar 	nla_for_each_nested(a, attr, rem) {
2580e6445719SPravin B Shelar 		int type = nla_type(a);
2581e6445719SPravin B Shelar 		if (!type || type > OVS_SAMPLE_ATTR_MAX || attrs[type])
2582e6445719SPravin B Shelar 			return -EINVAL;
2583e6445719SPravin B Shelar 		attrs[type] = a;
2584e6445719SPravin B Shelar 	}
2585e6445719SPravin B Shelar 	if (rem)
2586e6445719SPravin B Shelar 		return -EINVAL;
2587e6445719SPravin B Shelar 
2588e6445719SPravin B Shelar 	probability = attrs[OVS_SAMPLE_ATTR_PROBABILITY];
2589e6445719SPravin B Shelar 	if (!probability || nla_len(probability) != sizeof(u32))
2590e6445719SPravin B Shelar 		return -EINVAL;
2591e6445719SPravin B Shelar 
2592e6445719SPravin B Shelar 	actions = attrs[OVS_SAMPLE_ATTR_ACTIONS];
2593e6445719SPravin B Shelar 	if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
2594e6445719SPravin B Shelar 		return -EINVAL;
2595e6445719SPravin B Shelar 
2596e6445719SPravin B Shelar 	/* validation done, copy sample action. */
259705da5898SJarno Rajahalme 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE, log);
2598e6445719SPravin B Shelar 	if (start < 0)
2599e6445719SPravin B Shelar 		return start;
2600798c1661Sandy zhou 
2601798c1661Sandy zhou 	/* When both skb and flow may be changed, put the sample
2602798c1661Sandy zhou 	 * into a deferred fifo. On the other hand, if only skb
2603798c1661Sandy zhou 	 * may be modified, the actions can be executed in place.
2604798c1661Sandy zhou 	 *
2605798c1661Sandy zhou 	 * Do this analysis at the flow installation time.
2606798c1661Sandy zhou 	 * Set 'clone_action->exec' to true if the actions can be
2607798c1661Sandy zhou 	 * executed without being deferred.
2608798c1661Sandy zhou 	 *
2609798c1661Sandy zhou 	 * If the sample is the last action, it can always be excuted
2610798c1661Sandy zhou 	 * rather than deferred.
2611798c1661Sandy zhou 	 */
2612798c1661Sandy zhou 	arg.exec = last || !actions_may_change_flow(actions);
2613798c1661Sandy zhou 	arg.probability = nla_get_u32(probability);
2614798c1661Sandy zhou 
2615798c1661Sandy zhou 	err = ovs_nla_add_action(sfa, OVS_SAMPLE_ATTR_ARG, &arg, sizeof(arg),
2616798c1661Sandy zhou 				 log);
2617e6445719SPravin B Shelar 	if (err)
2618e6445719SPravin B Shelar 		return err;
2619e6445719SPravin B Shelar 
2620798c1661Sandy zhou 	err = __ovs_nla_copy_actions(net, actions, key, sfa,
26216e2f90d3SAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
26226e2f90d3SAaron Conole 				     depth + 1);
2623798c1661Sandy zhou 
2624e6445719SPravin B Shelar 	if (err)
2625e6445719SPravin B Shelar 		return err;
2626e6445719SPravin B Shelar 
2627e6445719SPravin B Shelar 	add_nested_action_end(*sfa, start);
2628e6445719SPravin B Shelar 
2629e6445719SPravin B Shelar 	return 0;
2630e6445719SPravin B Shelar }
2631e6445719SPravin B Shelar 
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,u32 depth)2632744676e7SMatteo Croce static int validate_and_copy_dec_ttl(struct net *net,
2633744676e7SMatteo Croce 				     const struct nlattr *attr,
2634744676e7SMatteo Croce 				     const struct sw_flow_key *key,
2635744676e7SMatteo Croce 				     struct sw_flow_actions **sfa,
2636744676e7SMatteo Croce 				     __be16 eth_type, __be16 vlan_tci,
26376e2f90d3SAaron Conole 				     u32 mpls_label_count, bool log,
26386e2f90d3SAaron Conole 				     u32 depth)
2639744676e7SMatteo Croce {
264069929d4cSEelco Chaudron 	const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1];
264169929d4cSEelco Chaudron 	int start, action_start, err, rem;
264269929d4cSEelco Chaudron 	const struct nlattr *a, *actions;
2643744676e7SMatteo Croce 
264469929d4cSEelco Chaudron 	memset(attrs, 0, sizeof(attrs));
264569929d4cSEelco Chaudron 	nla_for_each_nested(a, attr, rem) {
264669929d4cSEelco Chaudron 		int type = nla_type(a);
264769929d4cSEelco Chaudron 
264869929d4cSEelco Chaudron 		/* Ignore unknown attributes to be future proof. */
264969929d4cSEelco Chaudron 		if (type > OVS_DEC_TTL_ATTR_MAX)
265069929d4cSEelco Chaudron 			continue;
265169929d4cSEelco Chaudron 
2652a5317f3bSEelco Chaudron 		if (!type || attrs[type]) {
2653a5317f3bSEelco Chaudron 			OVS_NLERR(log, "Duplicate or invalid key (type %d).",
2654a5317f3bSEelco Chaudron 				  type);
265569929d4cSEelco Chaudron 			return -EINVAL;
2656a5317f3bSEelco Chaudron 		}
265769929d4cSEelco Chaudron 
265869929d4cSEelco Chaudron 		attrs[type] = a;
265969929d4cSEelco Chaudron 	}
266069929d4cSEelco Chaudron 
2661a5317f3bSEelco Chaudron 	if (rem) {
2662a5317f3bSEelco Chaudron 		OVS_NLERR(log, "Message has %d unknown bytes.", rem);
266369929d4cSEelco Chaudron 		return -EINVAL;
2664a5317f3bSEelco Chaudron 	}
2665a5317f3bSEelco Chaudron 
2666a5317f3bSEelco Chaudron 	actions = attrs[OVS_DEC_TTL_ATTR_ACTION];
2667a5317f3bSEelco Chaudron 	if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN)) {
2668a5317f3bSEelco Chaudron 		OVS_NLERR(log, "Missing valid actions attribute.");
2669a5317f3bSEelco Chaudron 		return -EINVAL;
2670a5317f3bSEelco Chaudron 	}
2671744676e7SMatteo Croce 
2672744676e7SMatteo Croce 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log);
2673744676e7SMatteo Croce 	if (start < 0)
2674744676e7SMatteo Croce 		return start;
2675744676e7SMatteo Croce 
267669929d4cSEelco Chaudron 	action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log);
267769929d4cSEelco Chaudron 	if (action_start < 0)
2678bb2da765SWang Hai 		return action_start;
2679744676e7SMatteo Croce 
268069929d4cSEelco Chaudron 	err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
26816e2f90d3SAaron Conole 				     vlan_tci, mpls_label_count, log,
26826e2f90d3SAaron Conole 				     depth + 1);
2683744676e7SMatteo Croce 	if (err)
2684744676e7SMatteo Croce 		return err;
2685744676e7SMatteo Croce 
268669929d4cSEelco Chaudron 	add_nested_action_end(*sfa, action_start);
2687744676e7SMatteo Croce 	add_nested_action_end(*sfa, start);
2688744676e7SMatteo Croce 	return 0;
2689744676e7SMatteo Croce }
2690744676e7SMatteo Croce 
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,u32 mpls_label_count,bool log,bool last,u32 depth)2691b2335040SYifeng Sun static int validate_and_copy_clone(struct net *net,
2692b2335040SYifeng Sun 				   const struct nlattr *attr,
2693b2335040SYifeng Sun 				   const struct sw_flow_key *key,
2694b2335040SYifeng Sun 				   struct sw_flow_actions **sfa,
2695b2335040SYifeng Sun 				   __be16 eth_type, __be16 vlan_tci,
26966e2f90d3SAaron Conole 				   u32 mpls_label_count, bool log, bool last,
26976e2f90d3SAaron Conole 				   u32 depth)
2698b2335040SYifeng Sun {
2699b2335040SYifeng Sun 	int start, err;
2700b2335040SYifeng Sun 	u32 exec;
2701b2335040SYifeng Sun 
2702b2335040SYifeng Sun 	if (nla_len(attr) && nla_len(attr) < NLA_HDRLEN)
2703b2335040SYifeng Sun 		return -EINVAL;
2704b2335040SYifeng Sun 
2705b2335040SYifeng Sun 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CLONE, log);
2706b2335040SYifeng Sun 	if (start < 0)
2707b2335040SYifeng Sun 		return start;
2708b2335040SYifeng Sun 
2709b2335040SYifeng Sun 	exec = last || !actions_may_change_flow(attr);
2710b2335040SYifeng Sun 
2711b2335040SYifeng Sun 	err = ovs_nla_add_action(sfa, OVS_CLONE_ATTR_EXEC, &exec,
2712b2335040SYifeng Sun 				 sizeof(exec), log);
2713b2335040SYifeng Sun 	if (err)
2714b2335040SYifeng Sun 		return err;
2715b2335040SYifeng Sun 
2716b2335040SYifeng Sun 	err = __ovs_nla_copy_actions(net, attr, key, sfa,
27176e2f90d3SAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
27186e2f90d3SAaron Conole 				     depth + 1);
2719b2335040SYifeng Sun 	if (err)
2720b2335040SYifeng Sun 		return err;
2721b2335040SYifeng Sun 
2722b2335040SYifeng Sun 	add_nested_action_end(*sfa, start);
2723b2335040SYifeng Sun 
2724b2335040SYifeng Sun 	return 0;
2725b2335040SYifeng Sun }
2726b2335040SYifeng Sun 
ovs_match_init(struct sw_flow_match * match,struct sw_flow_key * key,bool reset_key,struct sw_flow_mask * mask)2727e6445719SPravin B Shelar void ovs_match_init(struct sw_flow_match *match,
2728e6445719SPravin B Shelar 		    struct sw_flow_key *key,
27292279994dSpravin shelar 		    bool reset_key,
2730e6445719SPravin B Shelar 		    struct sw_flow_mask *mask)
2731e6445719SPravin B Shelar {
2732e6445719SPravin B Shelar 	memset(match, 0, sizeof(*match));
2733e6445719SPravin B Shelar 	match->key = key;
2734e6445719SPravin B Shelar 	match->mask = mask;
2735e6445719SPravin B Shelar 
27362279994dSpravin shelar 	if (reset_key)
2737e6445719SPravin B Shelar 		memset(key, 0, sizeof(*key));
2738e6445719SPravin B Shelar 
2739e6445719SPravin B Shelar 	if (mask) {
2740e6445719SPravin B Shelar 		memset(&mask->key, 0, sizeof(mask->key));
2741e6445719SPravin B Shelar 		mask->range.start = mask->range.end = 0;
2742e6445719SPravin B Shelar 	}
2743e6445719SPravin B Shelar }
2744e6445719SPravin B Shelar 
validate_geneve_opts(struct sw_flow_key * key)2745d91641d9SThomas Graf static int validate_geneve_opts(struct sw_flow_key *key)
2746e6445719SPravin B Shelar {
2747d91641d9SThomas Graf 	struct geneve_opt *option;
2748d91641d9SThomas Graf 	int opts_len = key->tun_opts_len;
2749f5796684SJesse Gross 	bool crit_opt = false;
2750f5796684SJesse Gross 
2751d91641d9SThomas Graf 	option = (struct geneve_opt *)TUN_METADATA_OPTS(key, key->tun_opts_len);
2752f5796684SJesse Gross 	while (opts_len > 0) {
2753f5796684SJesse Gross 		int len;
2754f5796684SJesse Gross 
2755f5796684SJesse Gross 		if (opts_len < sizeof(*option))
2756f5796684SJesse Gross 			return -EINVAL;
2757f5796684SJesse Gross 
2758f5796684SJesse Gross 		len = sizeof(*option) + option->length * 4;
2759f5796684SJesse Gross 		if (len > opts_len)
2760f5796684SJesse Gross 			return -EINVAL;
2761f5796684SJesse Gross 
2762f5796684SJesse Gross 		crit_opt |= !!(option->type & GENEVE_CRIT_OPT_TYPE);
2763f5796684SJesse Gross 
2764f5796684SJesse Gross 		option = (struct geneve_opt *)((u8 *)option + len);
2765f5796684SJesse Gross 		opts_len -= len;
276689290b83SChristopher Díaz Riveros 	}
2767f5796684SJesse Gross 
27685832c4a7SAlexander Lobakin 	if (crit_opt)
27695832c4a7SAlexander Lobakin 		__set_bit(IP_TUNNEL_CRIT_OPT_BIT, key->tun_key.tun_flags);
2770d91641d9SThomas Graf 
2771d91641d9SThomas Graf 	return 0;
2772d91641d9SThomas Graf }
2773d91641d9SThomas Graf 
validate_and_copy_set_tun(const struct nlattr * attr,struct sw_flow_actions ** sfa,bool log)2774d91641d9SThomas Graf static int validate_and_copy_set_tun(const struct nlattr *attr,
2775d91641d9SThomas Graf 				     struct sw_flow_actions **sfa, bool log)
2776d91641d9SThomas Graf {
27775832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(dst_opt_type) = { };
2778d91641d9SThomas Graf 	struct sw_flow_match match;
2779d91641d9SThomas Graf 	struct sw_flow_key key;
278034ae932aSThomas Graf 	struct metadata_dst *tun_dst;
27811d8fff90SThomas Graf 	struct ip_tunnel_info *tun_info;
278234ae932aSThomas Graf 	struct ovs_tunnel_info *ovs_tun;
2783d91641d9SThomas Graf 	struct nlattr *a;
278413101602SGeert Uytterhoeven 	int err = 0, start, opts_type;
2785d91641d9SThomas Graf 
27862279994dSpravin shelar 	ovs_match_init(&match, &key, true, NULL);
27876b26ba3aSJiri Benc 	opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
27881dd144cfSThomas Graf 	if (opts_type < 0)
27891dd144cfSThomas Graf 		return opts_type;
2790d91641d9SThomas Graf 
2791d91641d9SThomas Graf 	if (key.tun_opts_len) {
27921dd144cfSThomas Graf 		switch (opts_type) {
27931dd144cfSThomas Graf 		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
2794d91641d9SThomas Graf 			err = validate_geneve_opts(&key);
2795d91641d9SThomas Graf 			if (err < 0)
2796d91641d9SThomas Graf 				return err;
27975832c4a7SAlexander Lobakin 
27985832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_GENEVE_OPT_BIT, dst_opt_type);
27991dd144cfSThomas Graf 			break;
28001dd144cfSThomas Graf 		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
28015832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_VXLAN_OPT_BIT, dst_opt_type);
28021dd144cfSThomas Graf 			break;
2803fc1372f8SWilliam Tu 		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
28045832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT, dst_opt_type);
2805fc1372f8SWilliam Tu 			break;
28061dd144cfSThomas Graf 		}
280789290b83SChristopher Díaz Riveros 	}
2808f5796684SJesse Gross 
280905da5898SJarno Rajahalme 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET, log);
2810e6445719SPravin B Shelar 	if (start < 0)
2811e6445719SPravin B Shelar 		return start;
2812e6445719SPravin B Shelar 
28133fcece12SJakub Kicinski 	tun_dst = metadata_dst_alloc(key.tun_opts_len, METADATA_IP_TUNNEL,
28143fcece12SJakub Kicinski 				     GFP_KERNEL);
28153fcece12SJakub Kicinski 
281634ae932aSThomas Graf 	if (!tun_dst)
281734ae932aSThomas Graf 		return -ENOMEM;
2818f0b128c1SJesse Gross 
2819d71785ffSPaolo Abeni 	err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
2820d71785ffSPaolo Abeni 	if (err) {
2821d71785ffSPaolo Abeni 		dst_release((struct dst_entry *)tun_dst);
2822d71785ffSPaolo Abeni 		return err;
2823d71785ffSPaolo Abeni 	}
2824d71785ffSPaolo Abeni 
282534ae932aSThomas Graf 	a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
282634ae932aSThomas Graf 			 sizeof(*ovs_tun), log);
282734ae932aSThomas Graf 	if (IS_ERR(a)) {
282834ae932aSThomas Graf 		dst_release((struct dst_entry *)tun_dst);
282934ae932aSThomas Graf 		return PTR_ERR(a);
283034ae932aSThomas Graf 	}
283134ae932aSThomas Graf 
283234ae932aSThomas Graf 	ovs_tun = nla_data(a);
283334ae932aSThomas Graf 	ovs_tun->tun_dst = tun_dst;
283434ae932aSThomas Graf 
283534ae932aSThomas Graf 	tun_info = &tun_dst->u.tun_info;
283634ae932aSThomas Graf 	tun_info->mode = IP_TUNNEL_INFO_TX;
283700a93babSJiri Benc 	if (key.tun_proto == AF_INET6)
283800a93babSJiri Benc 		tun_info->mode |= IP_TUNNEL_INFO_IPV6;
283918b6f717Swenxu 	else if (key.tun_proto == AF_INET && key.tun_key.u.ipv4.dst == 0)
284018b6f717Swenxu 		tun_info->mode |= IP_TUNNEL_INFO_BRIDGE;
28411d8fff90SThomas Graf 	tun_info->key = key.tun_key;
2842f5796684SJesse Gross 
2843f5796684SJesse Gross 	/* We need to store the options in the action itself since
2844f5796684SJesse Gross 	 * everything else will go away after flow setup. We can append
2845f5796684SJesse Gross 	 * it to tun_info and then point there.
2846f5796684SJesse Gross 	 */
28474c222798SPravin B Shelar 	ip_tunnel_info_opts_set(tun_info,
28484c222798SPravin B Shelar 				TUN_METADATA_OPTS(&key, key.tun_opts_len),
2849256c87c1SPieter Jansen van Vuuren 				key.tun_opts_len, dst_opt_type);
2850e6445719SPravin B Shelar 	add_nested_action_end(*sfa, start);
2851e6445719SPravin B Shelar 
2852e6445719SPravin B Shelar 	return err;
2853e6445719SPravin B Shelar }
2854e6445719SPravin B Shelar 
validate_nsh(const struct nlattr * attr,bool is_mask,bool is_push_nsh,bool log)2855b2d0f5d5SYi Yang static bool validate_nsh(const struct nlattr *attr, bool is_mask,
2856b2d0f5d5SYi Yang 			 bool is_push_nsh, bool log)
2857b2d0f5d5SYi Yang {
2858b2d0f5d5SYi Yang 	struct sw_flow_match match;
2859b2d0f5d5SYi Yang 	struct sw_flow_key key;
2860b2d0f5d5SYi Yang 	int ret = 0;
2861b2d0f5d5SYi Yang 
2862b2d0f5d5SYi Yang 	ovs_match_init(&match, &key, true, NULL);
2863b2d0f5d5SYi Yang 	ret = nsh_key_put_from_nlattr(attr, &match, is_mask,
2864b2d0f5d5SYi Yang 				      is_push_nsh, log);
2865b2d0f5d5SYi Yang 	return !ret;
2866b2d0f5d5SYi Yang }
2867b2d0f5d5SYi Yang 
286883d2b9baSJarno Rajahalme /* Return false if there are any non-masked bits set.
286983d2b9baSJarno Rajahalme  * Mask follows data immediately, before any netlink padding.
287083d2b9baSJarno Rajahalme  */
validate_masked(u8 * data,int len)287183d2b9baSJarno Rajahalme static bool validate_masked(u8 *data, int len)
287283d2b9baSJarno Rajahalme {
287383d2b9baSJarno Rajahalme 	u8 *mask = data + len;
287483d2b9baSJarno Rajahalme 
287583d2b9baSJarno Rajahalme 	while (len--)
287683d2b9baSJarno Rajahalme 		if (*data++ & ~*mask++)
287783d2b9baSJarno Rajahalme 			return false;
287883d2b9baSJarno Rajahalme 
287983d2b9baSJarno Rajahalme 	return true;
288083d2b9baSJarno Rajahalme }
288183d2b9baSJarno Rajahalme 
validate_set(const struct nlattr * a,const struct sw_flow_key * flow_key,struct sw_flow_actions ** sfa,bool * skip_copy,u8 mac_proto,__be16 eth_type,bool masked,bool log)2882e6445719SPravin B Shelar static int validate_set(const struct nlattr *a,
2883e6445719SPravin B Shelar 			const struct sw_flow_key *flow_key,
28840a6410fbSJiri Benc 			struct sw_flow_actions **sfa, bool *skip_copy,
28850a6410fbSJiri Benc 			u8 mac_proto, __be16 eth_type, bool masked, bool log)
2886e6445719SPravin B Shelar {
2887e6445719SPravin B Shelar 	const struct nlattr *ovs_key = nla_data(a);
2888e6445719SPravin B Shelar 	int key_type = nla_type(ovs_key);
288983d2b9baSJarno Rajahalme 	size_t key_len;
2890e6445719SPravin B Shelar 
2891e6445719SPravin B Shelar 	/* There can be only one key in a action */
2892e6445719SPravin B Shelar 	if (nla_total_size(nla_len(ovs_key)) != nla_len(a))
2893e6445719SPravin B Shelar 		return -EINVAL;
2894e6445719SPravin B Shelar 
289583d2b9baSJarno Rajahalme 	key_len = nla_len(ovs_key);
289683d2b9baSJarno Rajahalme 	if (masked)
289783d2b9baSJarno Rajahalme 		key_len /= 2;
289883d2b9baSJarno Rajahalme 
2899e6445719SPravin B Shelar 	if (key_type > OVS_KEY_ATTR_MAX ||
2900982b5270SJesse Gross 	    !check_attr_len(key_len, ovs_key_lens[key_type].len))
2901e6445719SPravin B Shelar 		return -EINVAL;
2902e6445719SPravin B Shelar 
290383d2b9baSJarno Rajahalme 	if (masked && !validate_masked(nla_data(ovs_key), key_len))
290483d2b9baSJarno Rajahalme 		return -EINVAL;
290583d2b9baSJarno Rajahalme 
2906e6445719SPravin B Shelar 	switch (key_type) {
2907e6445719SPravin B Shelar 	case OVS_KEY_ATTR_PRIORITY:
2908e6445719SPravin B Shelar 	case OVS_KEY_ATTR_SKB_MARK:
2909182e3042SJoe Stringer 	case OVS_KEY_ATTR_CT_MARK:
291033db4125SJoe Stringer 	case OVS_KEY_ATTR_CT_LABELS:
2911e6445719SPravin B Shelar 		break;
2912e6445719SPravin B Shelar 
29130a6410fbSJiri Benc 	case OVS_KEY_ATTR_ETHERNET:
29140a6410fbSJiri Benc 		if (mac_proto != MAC_PROTO_ETHERNET)
29150a6410fbSJiri Benc 			return -EINVAL;
291687e159c5SJarno Rajahalme 		break;
29170a6410fbSJiri Benc 
291816a556eeSKees Cook 	case OVS_KEY_ATTR_TUNNEL: {
291916a556eeSKees Cook 		int err;
292016a556eeSKees Cook 
292183d2b9baSJarno Rajahalme 		if (masked)
292283d2b9baSJarno Rajahalme 			return -EINVAL; /* Masked tunnel set not supported. */
292383d2b9baSJarno Rajahalme 
292483d2b9baSJarno Rajahalme 		*skip_copy = true;
292505da5898SJarno Rajahalme 		err = validate_and_copy_set_tun(a, sfa, log);
2926e6445719SPravin B Shelar 		if (err)
2927e6445719SPravin B Shelar 			return err;
2928e6445719SPravin B Shelar 		break;
292916a556eeSKees Cook 	}
293016a556eeSKees Cook 	case OVS_KEY_ATTR_IPV4: {
293116a556eeSKees Cook 		const struct ovs_key_ipv4 *ipv4_key;
2932e6445719SPravin B Shelar 
293325cd9ba0SSimon Horman 		if (eth_type != htons(ETH_P_IP))
2934e6445719SPravin B Shelar 			return -EINVAL;
2935e6445719SPravin B Shelar 
2936e6445719SPravin B Shelar 		ipv4_key = nla_data(ovs_key);
293783d2b9baSJarno Rajahalme 
293883d2b9baSJarno Rajahalme 		if (masked) {
293983d2b9baSJarno Rajahalme 			const struct ovs_key_ipv4 *mask = ipv4_key + 1;
294083d2b9baSJarno Rajahalme 
294183d2b9baSJarno Rajahalme 			/* Non-writeable fields. */
294283d2b9baSJarno Rajahalme 			if (mask->ipv4_proto || mask->ipv4_frag)
294383d2b9baSJarno Rajahalme 				return -EINVAL;
294483d2b9baSJarno Rajahalme 		} else {
2945e6445719SPravin B Shelar 			if (ipv4_key->ipv4_proto != flow_key->ip.proto)
2946e6445719SPravin B Shelar 				return -EINVAL;
2947e6445719SPravin B Shelar 
2948e6445719SPravin B Shelar 			if (ipv4_key->ipv4_frag != flow_key->ip.frag)
2949e6445719SPravin B Shelar 				return -EINVAL;
295083d2b9baSJarno Rajahalme 		}
2951e6445719SPravin B Shelar 		break;
295216a556eeSKees Cook 	}
295316a556eeSKees Cook 	case OVS_KEY_ATTR_IPV6: {
295416a556eeSKees Cook 		const struct ovs_key_ipv6 *ipv6_key;
2955e6445719SPravin B Shelar 
295625cd9ba0SSimon Horman 		if (eth_type != htons(ETH_P_IPV6))
2957e6445719SPravin B Shelar 			return -EINVAL;
2958e6445719SPravin B Shelar 
295983d2b9baSJarno Rajahalme 		ipv6_key = nla_data(ovs_key);
296083d2b9baSJarno Rajahalme 
296183d2b9baSJarno Rajahalme 		if (masked) {
296283d2b9baSJarno Rajahalme 			const struct ovs_key_ipv6 *mask = ipv6_key + 1;
296383d2b9baSJarno Rajahalme 
296483d2b9baSJarno Rajahalme 			/* Non-writeable fields. */
296583d2b9baSJarno Rajahalme 			if (mask->ipv6_proto || mask->ipv6_frag)
2966e6445719SPravin B Shelar 				return -EINVAL;
2967e6445719SPravin B Shelar 
296883d2b9baSJarno Rajahalme 			/* Invalid bits in the flow label mask? */
296983d2b9baSJarno Rajahalme 			if (ntohl(mask->ipv6_label) & 0xFFF00000)
297083d2b9baSJarno Rajahalme 				return -EINVAL;
297183d2b9baSJarno Rajahalme 		} else {
2972e6445719SPravin B Shelar 			if (ipv6_key->ipv6_proto != flow_key->ip.proto)
2973e6445719SPravin B Shelar 				return -EINVAL;
2974e6445719SPravin B Shelar 
2975e6445719SPravin B Shelar 			if (ipv6_key->ipv6_frag != flow_key->ip.frag)
2976e6445719SPravin B Shelar 				return -EINVAL;
297783d2b9baSJarno Rajahalme 		}
2978e6445719SPravin B Shelar 		if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000)
2979e6445719SPravin B Shelar 			return -EINVAL;
2980e6445719SPravin B Shelar 
2981e6445719SPravin B Shelar 		break;
298216a556eeSKees Cook 	}
2983e6445719SPravin B Shelar 	case OVS_KEY_ATTR_TCP:
298483d2b9baSJarno Rajahalme 		if ((eth_type != htons(ETH_P_IP) &&
298583d2b9baSJarno Rajahalme 		     eth_type != htons(ETH_P_IPV6)) ||
298683d2b9baSJarno Rajahalme 		    flow_key->ip.proto != IPPROTO_TCP)
2987e6445719SPravin B Shelar 			return -EINVAL;
2988e6445719SPravin B Shelar 
298983d2b9baSJarno Rajahalme 		break;
2990e6445719SPravin B Shelar 
2991e6445719SPravin B Shelar 	case OVS_KEY_ATTR_UDP:
299283d2b9baSJarno Rajahalme 		if ((eth_type != htons(ETH_P_IP) &&
299383d2b9baSJarno Rajahalme 		     eth_type != htons(ETH_P_IPV6)) ||
299483d2b9baSJarno Rajahalme 		    flow_key->ip.proto != IPPROTO_UDP)
2995e6445719SPravin B Shelar 			return -EINVAL;
2996e6445719SPravin B Shelar 
299783d2b9baSJarno Rajahalme 		break;
299825cd9ba0SSimon Horman 
299925cd9ba0SSimon Horman 	case OVS_KEY_ATTR_MPLS:
300025cd9ba0SSimon Horman 		if (!eth_p_mpls(eth_type))
300125cd9ba0SSimon Horman 			return -EINVAL;
300225cd9ba0SSimon Horman 		break;
3003e6445719SPravin B Shelar 
3004e6445719SPravin B Shelar 	case OVS_KEY_ATTR_SCTP:
300583d2b9baSJarno Rajahalme 		if ((eth_type != htons(ETH_P_IP) &&
300683d2b9baSJarno Rajahalme 		     eth_type != htons(ETH_P_IPV6)) ||
300783d2b9baSJarno Rajahalme 		    flow_key->ip.proto != IPPROTO_SCTP)
3008e6445719SPravin B Shelar 			return -EINVAL;
3009e6445719SPravin B Shelar 
301083d2b9baSJarno Rajahalme 		break;
3011e6445719SPravin B Shelar 
3012b2d0f5d5SYi Yang 	case OVS_KEY_ATTR_NSH:
3013b2d0f5d5SYi Yang 		if (eth_type != htons(ETH_P_NSH))
3014b2d0f5d5SYi Yang 			return -EINVAL;
3015b2d0f5d5SYi Yang 		if (!validate_nsh(nla_data(a), masked, false, log))
3016b2d0f5d5SYi Yang 			return -EINVAL;
3017b2d0f5d5SYi Yang 		break;
3018b2d0f5d5SYi Yang 
3019e6445719SPravin B Shelar 	default:
3020e6445719SPravin B Shelar 		return -EINVAL;
3021e6445719SPravin B Shelar 	}
3022e6445719SPravin B Shelar 
302383d2b9baSJarno Rajahalme 	/* Convert non-masked non-tunnel set actions to masked set actions. */
302483d2b9baSJarno Rajahalme 	if (!masked && key_type != OVS_KEY_ATTR_TUNNEL) {
302583d2b9baSJarno Rajahalme 		int start, len = key_len * 2;
302683d2b9baSJarno Rajahalme 		struct nlattr *at;
302783d2b9baSJarno Rajahalme 
302883d2b9baSJarno Rajahalme 		*skip_copy = true;
302983d2b9baSJarno Rajahalme 
303083d2b9baSJarno Rajahalme 		start = add_nested_action_start(sfa,
303183d2b9baSJarno Rajahalme 						OVS_ACTION_ATTR_SET_TO_MASKED,
303283d2b9baSJarno Rajahalme 						log);
303383d2b9baSJarno Rajahalme 		if (start < 0)
303483d2b9baSJarno Rajahalme 			return start;
303583d2b9baSJarno Rajahalme 
303683d2b9baSJarno Rajahalme 		at = __add_action(sfa, key_type, NULL, len, log);
303783d2b9baSJarno Rajahalme 		if (IS_ERR(at))
303883d2b9baSJarno Rajahalme 			return PTR_ERR(at);
303983d2b9baSJarno Rajahalme 
304083d2b9baSJarno Rajahalme 		memcpy(nla_data(at), nla_data(ovs_key), key_len); /* Key. */
304183d2b9baSJarno Rajahalme 		memset(nla_data(at) + key_len, 0xff, key_len);    /* Mask. */
304283d2b9baSJarno Rajahalme 		/* Clear non-writeable bits from otherwise writeable fields. */
304383d2b9baSJarno Rajahalme 		if (key_type == OVS_KEY_ATTR_IPV6) {
304483d2b9baSJarno Rajahalme 			struct ovs_key_ipv6 *mask = nla_data(at) + key_len;
304583d2b9baSJarno Rajahalme 
304683d2b9baSJarno Rajahalme 			mask->ipv6_label &= htonl(0x000FFFFF);
304783d2b9baSJarno Rajahalme 		}
304883d2b9baSJarno Rajahalme 		add_nested_action_end(*sfa, start);
304983d2b9baSJarno Rajahalme 	}
305083d2b9baSJarno Rajahalme 
3051e6445719SPravin B Shelar 	return 0;
3052e6445719SPravin B Shelar }
3053e6445719SPravin B Shelar 
validate_userspace(const struct nlattr * attr)3054e6445719SPravin B Shelar static int validate_userspace(const struct nlattr *attr)
3055e6445719SPravin B Shelar {
3056e6445719SPravin B Shelar 	static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = {
3057e6445719SPravin B Shelar 		[OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
3058e6445719SPravin B Shelar 		[OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
30598f0aad6fSWenyu Zhang 		[OVS_USERSPACE_ATTR_EGRESS_TUN_PORT] = {.type = NLA_U32 },
3060e6445719SPravin B Shelar 	};
3061e6445719SPravin B Shelar 	struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
3062e6445719SPravin B Shelar 	int error;
3063e6445719SPravin B Shelar 
30648cb08174SJohannes Berg 	error = nla_parse_nested_deprecated(a, OVS_USERSPACE_ATTR_MAX, attr,
3065fceb6435SJohannes Berg 					    userspace_policy, NULL);
3066e6445719SPravin B Shelar 	if (error)
3067e6445719SPravin B Shelar 		return error;
3068e6445719SPravin B Shelar 
3069e6445719SPravin B Shelar 	if (!a[OVS_USERSPACE_ATTR_PID] ||
3070e6445719SPravin B Shelar 	    !nla_get_u32(a[OVS_USERSPACE_ATTR_PID]))
3071e6445719SPravin B Shelar 		return -EINVAL;
3072e6445719SPravin B Shelar 
3073e6445719SPravin B Shelar 	return 0;
3074e6445719SPravin B Shelar }
3075e6445719SPravin B Shelar 
30764d5ec89fSNuman Siddique static const struct nla_policy cpl_policy[OVS_CHECK_PKT_LEN_ATTR_MAX + 1] = {
30774d5ec89fSNuman Siddique 	[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] = {.type = NLA_U16 },
30784d5ec89fSNuman Siddique 	[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER] = {.type = NLA_NESTED },
30794d5ec89fSNuman Siddique 	[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL] = {.type = NLA_NESTED },
30804d5ec89fSNuman Siddique };
30814d5ec89fSNuman Siddique 
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,u32 mpls_label_count,bool log,bool last,u32 depth)30824d5ec89fSNuman Siddique static int validate_and_copy_check_pkt_len(struct net *net,
30834d5ec89fSNuman Siddique 					   const struct nlattr *attr,
30844d5ec89fSNuman Siddique 					   const struct sw_flow_key *key,
30854d5ec89fSNuman Siddique 					   struct sw_flow_actions **sfa,
30864d5ec89fSNuman Siddique 					   __be16 eth_type, __be16 vlan_tci,
3087fbdcdd78SMartin Varghese 					   u32 mpls_label_count,
30886e2f90d3SAaron Conole 					   bool log, bool last, u32 depth)
30894d5ec89fSNuman Siddique {
30904d5ec89fSNuman Siddique 	const struct nlattr *acts_if_greater, *acts_if_lesser_eq;
30914d5ec89fSNuman Siddique 	struct nlattr *a[OVS_CHECK_PKT_LEN_ATTR_MAX + 1];
30924d5ec89fSNuman Siddique 	struct check_pkt_len_arg arg;
30934d5ec89fSNuman Siddique 	int nested_acts_start;
30944d5ec89fSNuman Siddique 	int start, err;
30954d5ec89fSNuman Siddique 
30968cb08174SJohannes Berg 	err = nla_parse_deprecated_strict(a, OVS_CHECK_PKT_LEN_ATTR_MAX,
30978cb08174SJohannes Berg 					  nla_data(attr), nla_len(attr),
30988cb08174SJohannes Berg 					  cpl_policy, NULL);
30994d5ec89fSNuman Siddique 	if (err)
31004d5ec89fSNuman Siddique 		return err;
31014d5ec89fSNuman Siddique 
31024d5ec89fSNuman Siddique 	if (!a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] ||
31034d5ec89fSNuman Siddique 	    !nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]))
31044d5ec89fSNuman Siddique 		return -EINVAL;
31054d5ec89fSNuman Siddique 
31064d5ec89fSNuman Siddique 	acts_if_lesser_eq = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL];
31074d5ec89fSNuman Siddique 	acts_if_greater = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER];
31084d5ec89fSNuman Siddique 
31094d5ec89fSNuman Siddique 	/* Both the nested action should be present. */
31104d5ec89fSNuman Siddique 	if (!acts_if_greater || !acts_if_lesser_eq)
31114d5ec89fSNuman Siddique 		return -EINVAL;
31124d5ec89fSNuman Siddique 
31134d5ec89fSNuman Siddique 	/* validation done, copy the nested actions. */
31144d5ec89fSNuman Siddique 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CHECK_PKT_LEN,
31154d5ec89fSNuman Siddique 					log);
31164d5ec89fSNuman Siddique 	if (start < 0)
31174d5ec89fSNuman Siddique 		return start;
31184d5ec89fSNuman Siddique 
31194d5ec89fSNuman Siddique 	arg.pkt_len = nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]);
31204d5ec89fSNuman Siddique 	arg.exec_for_lesser_equal =
31214d5ec89fSNuman Siddique 		last || !actions_may_change_flow(acts_if_lesser_eq);
31224d5ec89fSNuman Siddique 	arg.exec_for_greater =
31234d5ec89fSNuman Siddique 		last || !actions_may_change_flow(acts_if_greater);
31244d5ec89fSNuman Siddique 
31254d5ec89fSNuman Siddique 	err = ovs_nla_add_action(sfa, OVS_CHECK_PKT_LEN_ATTR_ARG, &arg,
31264d5ec89fSNuman Siddique 				 sizeof(arg), log);
31274d5ec89fSNuman Siddique 	if (err)
31284d5ec89fSNuman Siddique 		return err;
31294d5ec89fSNuman Siddique 
31304d5ec89fSNuman Siddique 	nested_acts_start = add_nested_action_start(sfa,
31314d5ec89fSNuman Siddique 		OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL, log);
31324d5ec89fSNuman Siddique 	if (nested_acts_start < 0)
31334d5ec89fSNuman Siddique 		return nested_acts_start;
31344d5ec89fSNuman Siddique 
31354d5ec89fSNuman Siddique 	err = __ovs_nla_copy_actions(net, acts_if_lesser_eq, key, sfa,
31366e2f90d3SAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
31376e2f90d3SAaron Conole 				     depth + 1);
31384d5ec89fSNuman Siddique 
31394d5ec89fSNuman Siddique 	if (err)
31404d5ec89fSNuman Siddique 		return err;
31414d5ec89fSNuman Siddique 
31424d5ec89fSNuman Siddique 	add_nested_action_end(*sfa, nested_acts_start);
31434d5ec89fSNuman Siddique 
31444d5ec89fSNuman Siddique 	nested_acts_start = add_nested_action_start(sfa,
31454d5ec89fSNuman Siddique 		OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER, log);
31464d5ec89fSNuman Siddique 	if (nested_acts_start < 0)
31474d5ec89fSNuman Siddique 		return nested_acts_start;
31484d5ec89fSNuman Siddique 
31494d5ec89fSNuman Siddique 	err = __ovs_nla_copy_actions(net, acts_if_greater, key, sfa,
31506e2f90d3SAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
31516e2f90d3SAaron Conole 				     depth + 1);
31524d5ec89fSNuman Siddique 
31534d5ec89fSNuman Siddique 	if (err)
31544d5ec89fSNuman Siddique 		return err;
31554d5ec89fSNuman Siddique 
31564d5ec89fSNuman Siddique 	add_nested_action_end(*sfa, nested_acts_start);
31574d5ec89fSNuman Siddique 	add_nested_action_end(*sfa, start);
31584d5ec89fSNuman Siddique 	return 0;
31594d5ec89fSNuman Siddique }
31604d5ec89fSNuman Siddique 
validate_psample(const struct nlattr * attr)3161aae0b82bSAdrian Moreno static int validate_psample(const struct nlattr *attr)
3162aae0b82bSAdrian Moreno {
3163aae0b82bSAdrian Moreno 	static const struct nla_policy policy[OVS_PSAMPLE_ATTR_MAX + 1] = {
3164aae0b82bSAdrian Moreno 		[OVS_PSAMPLE_ATTR_GROUP] = { .type = NLA_U32 },
3165aae0b82bSAdrian Moreno 		[OVS_PSAMPLE_ATTR_COOKIE] = {
3166aae0b82bSAdrian Moreno 			.type = NLA_BINARY,
3167aae0b82bSAdrian Moreno 			.len = OVS_PSAMPLE_COOKIE_MAX_SIZE,
3168aae0b82bSAdrian Moreno 		},
3169aae0b82bSAdrian Moreno 	};
3170aae0b82bSAdrian Moreno 	struct nlattr *a[OVS_PSAMPLE_ATTR_MAX + 1];
3171aae0b82bSAdrian Moreno 	int err;
3172aae0b82bSAdrian Moreno 
3173aae0b82bSAdrian Moreno 	if (!IS_ENABLED(CONFIG_PSAMPLE))
3174aae0b82bSAdrian Moreno 		return -EOPNOTSUPP;
3175aae0b82bSAdrian Moreno 
3176aae0b82bSAdrian Moreno 	err = nla_parse_nested(a, OVS_PSAMPLE_ATTR_MAX, attr, policy, NULL);
3177aae0b82bSAdrian Moreno 	if (err)
3178aae0b82bSAdrian Moreno 		return err;
3179aae0b82bSAdrian Moreno 
3180aae0b82bSAdrian Moreno 	return a[OVS_PSAMPLE_ATTR_GROUP] ? 0 : -EINVAL;
3181aae0b82bSAdrian Moreno }
3182aae0b82bSAdrian Moreno 
copy_action(const struct nlattr * from,struct sw_flow_actions ** sfa,bool log)3183e6445719SPravin B Shelar static int copy_action(const struct nlattr *from,
318405da5898SJarno Rajahalme 		       struct sw_flow_actions **sfa, bool log)
3185e6445719SPravin B Shelar {
3186e6445719SPravin B Shelar 	int totlen = NLA_ALIGN(from->nla_len);
3187e6445719SPravin B Shelar 	struct nlattr *to;
3188e6445719SPravin B Shelar 
318905da5898SJarno Rajahalme 	to = reserve_sfa_size(sfa, from->nla_len, log);
3190e6445719SPravin B Shelar 	if (IS_ERR(to))
3191e6445719SPravin B Shelar 		return PTR_ERR(to);
3192e6445719SPravin B Shelar 
3193e6445719SPravin B Shelar 	memcpy(to, from, totlen);
3194e6445719SPravin B Shelar 	return 0;
3195e6445719SPravin B Shelar }
3196e6445719SPravin B Shelar 
__ovs_nla_copy_actions(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,u32 depth)31977f8a436eSJoe Stringer static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3198e6445719SPravin B Shelar 				  const struct sw_flow_key *key,
3199798c1661Sandy zhou 				  struct sw_flow_actions **sfa,
3200fbdcdd78SMartin Varghese 				  __be16 eth_type, __be16 vlan_tci,
32016e2f90d3SAaron Conole 				  u32 mpls_label_count, bool log,
32026e2f90d3SAaron Conole 				  u32 depth)
3203e6445719SPravin B Shelar {
32040a6410fbSJiri Benc 	u8 mac_proto = ovs_key_mac_proto(key);
3205e6445719SPravin B Shelar 	const struct nlattr *a;
3206e6445719SPravin B Shelar 	int rem, err;
3207e6445719SPravin B Shelar 
32086e2f90d3SAaron Conole 	if (depth > OVS_COPY_ACTIONS_MAX_DEPTH)
32096e2f90d3SAaron Conole 		return -EOVERFLOW;
32106e2f90d3SAaron Conole 
3211e6445719SPravin B Shelar 	nla_for_each_nested(a, attr, rem) {
3212e6445719SPravin B Shelar 		/* Expected argument lengths, (u32)-1 for variable length. */
3213e6445719SPravin B Shelar 		static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
3214e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
3215971427f3SAndy Zhou 			[OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
3216e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
321725cd9ba0SSimon Horman 			[OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls),
321825cd9ba0SSimon Horman 			[OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
3219e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
3220e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_POP_VLAN] = 0,
3221e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_SET] = (u32)-1,
322283d2b9baSJarno Rajahalme 			[OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
3223971427f3SAndy Zhou 			[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
32247f8a436eSJoe Stringer 			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
32257f8a436eSJoe Stringer 			[OVS_ACTION_ATTR_CT] = (u32)-1,
3226b8226962SEric Garver 			[OVS_ACTION_ATTR_CT_CLEAR] = 0,
3227f2a4d086SWilliam Tu 			[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
322891820da6SJiri Benc 			[OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
322991820da6SJiri Benc 			[OVS_ACTION_ATTR_POP_ETH] = 0,
3230b2d0f5d5SYi Yang 			[OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
3231b2d0f5d5SYi Yang 			[OVS_ACTION_ATTR_POP_NSH] = 0,
3232cd8a6c33SAndy Zhou 			[OVS_ACTION_ATTR_METER] = sizeof(u32),
3233b2335040SYifeng Sun 			[OVS_ACTION_ATTR_CLONE] = (u32)-1,
32344d5ec89fSNuman Siddique 			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
3235f66b53fdSMartin Varghese 			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
3236744676e7SMatteo Croce 			[OVS_ACTION_ATTR_DEC_TTL] = (u32)-1,
3237e7bc7db9SEric Garver 			[OVS_ACTION_ATTR_DROP] = sizeof(u32),
3238aae0b82bSAdrian Moreno 			[OVS_ACTION_ATTR_PSAMPLE] = (u32)-1,
3239e6445719SPravin B Shelar 		};
3240e6445719SPravin B Shelar 		const struct ovs_action_push_vlan *vlan;
3241e6445719SPravin B Shelar 		int type = nla_type(a);
3242e6445719SPravin B Shelar 		bool skip_copy;
3243e6445719SPravin B Shelar 
3244e6445719SPravin B Shelar 		if (type > OVS_ACTION_ATTR_MAX ||
3245e6445719SPravin B Shelar 		    (action_lens[type] != nla_len(a) &&
3246e6445719SPravin B Shelar 		     action_lens[type] != (u32)-1))
3247e6445719SPravin B Shelar 			return -EINVAL;
3248e6445719SPravin B Shelar 
3249e6445719SPravin B Shelar 		skip_copy = false;
3250e6445719SPravin B Shelar 		switch (type) {
3251e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_UNSPEC:
3252e6445719SPravin B Shelar 			return -EINVAL;
3253e6445719SPravin B Shelar 
3254e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_USERSPACE:
3255e6445719SPravin B Shelar 			err = validate_userspace(a);
3256e6445719SPravin B Shelar 			if (err)
3257e6445719SPravin B Shelar 				return err;
3258e6445719SPravin B Shelar 			break;
3259e6445719SPravin B Shelar 
3260e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_OUTPUT:
3261e6445719SPravin B Shelar 			if (nla_get_u32(a) >= DP_MAX_PORTS)
3262e6445719SPravin B Shelar 				return -EINVAL;
3263e6445719SPravin B Shelar 			break;
3264e6445719SPravin B Shelar 
3265f2a4d086SWilliam Tu 		case OVS_ACTION_ATTR_TRUNC: {
3266f2a4d086SWilliam Tu 			const struct ovs_action_trunc *trunc = nla_data(a);
3267f2a4d086SWilliam Tu 
3268f2a4d086SWilliam Tu 			if (trunc->max_len < ETH_HLEN)
3269f2a4d086SWilliam Tu 				return -EINVAL;
3270f2a4d086SWilliam Tu 			break;
3271f2a4d086SWilliam Tu 		}
3272f2a4d086SWilliam Tu 
3273971427f3SAndy Zhou 		case OVS_ACTION_ATTR_HASH: {
3274971427f3SAndy Zhou 			const struct ovs_action_hash *act_hash = nla_data(a);
3275971427f3SAndy Zhou 
3276971427f3SAndy Zhou 			switch (act_hash->hash_alg) {
3277971427f3SAndy Zhou 			case OVS_HASH_ALG_L4:
3278e069ba07SAaron Conole 				fallthrough;
3279e069ba07SAaron Conole 			case OVS_HASH_ALG_SYM_L4:
3280971427f3SAndy Zhou 				break;
3281971427f3SAndy Zhou 			default:
3282971427f3SAndy Zhou 				return  -EINVAL;
3283971427f3SAndy Zhou 			}
3284971427f3SAndy Zhou 
3285971427f3SAndy Zhou 			break;
3286971427f3SAndy Zhou 		}
3287e6445719SPravin B Shelar 
3288e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_POP_VLAN:
32890a6410fbSJiri Benc 			if (mac_proto != MAC_PROTO_ETHERNET)
32900a6410fbSJiri Benc 				return -EINVAL;
329125cd9ba0SSimon Horman 			vlan_tci = htons(0);
3292e6445719SPravin B Shelar 			break;
3293e6445719SPravin B Shelar 
3294e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_PUSH_VLAN:
32950a6410fbSJiri Benc 			if (mac_proto != MAC_PROTO_ETHERNET)
32960a6410fbSJiri Benc 				return -EINVAL;
3297e6445719SPravin B Shelar 			vlan = nla_data(a);
3298018c1ddaSEric Garver 			if (!eth_type_vlan(vlan->vlan_tpid))
3299e6445719SPravin B Shelar 				return -EINVAL;
33009df46aefSMichał Mirosław 			if (!(vlan->vlan_tci & htons(VLAN_CFI_MASK)))
3301e6445719SPravin B Shelar 				return -EINVAL;
330225cd9ba0SSimon Horman 			vlan_tci = vlan->vlan_tci;
3303e6445719SPravin B Shelar 			break;
3304e6445719SPravin B Shelar 
3305971427f3SAndy Zhou 		case OVS_ACTION_ATTR_RECIRC:
3306971427f3SAndy Zhou 			break;
3307971427f3SAndy Zhou 
3308f66b53fdSMartin Varghese 		case OVS_ACTION_ATTR_ADD_MPLS: {
3309f66b53fdSMartin Varghese 			const struct ovs_action_add_mpls *mpls = nla_data(a);
3310f66b53fdSMartin Varghese 
3311f66b53fdSMartin Varghese 			if (!eth_p_mpls(mpls->mpls_ethertype))
3312f66b53fdSMartin Varghese 				return -EINVAL;
3313f66b53fdSMartin Varghese 
3314f66b53fdSMartin Varghese 			if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK) {
3315f66b53fdSMartin Varghese 				if (vlan_tci & htons(VLAN_CFI_MASK) ||
3316f66b53fdSMartin Varghese 				    (eth_type != htons(ETH_P_IP) &&
3317f66b53fdSMartin Varghese 				     eth_type != htons(ETH_P_IPV6) &&
3318f66b53fdSMartin Varghese 				     eth_type != htons(ETH_P_ARP) &&
3319f66b53fdSMartin Varghese 				     eth_type != htons(ETH_P_RARP) &&
3320f66b53fdSMartin Varghese 				     !eth_p_mpls(eth_type)))
3321f66b53fdSMartin Varghese 					return -EINVAL;
3322f66b53fdSMartin Varghese 				mpls_label_count++;
3323f66b53fdSMartin Varghese 			} else {
3324f66b53fdSMartin Varghese 				if (mac_proto == MAC_PROTO_ETHERNET) {
3325f66b53fdSMartin Varghese 					mpls_label_count = 1;
3326f66b53fdSMartin Varghese 					mac_proto = MAC_PROTO_NONE;
3327f66b53fdSMartin Varghese 				} else {
3328f66b53fdSMartin Varghese 					mpls_label_count++;
3329f66b53fdSMartin Varghese 				}
3330f66b53fdSMartin Varghese 			}
3331f66b53fdSMartin Varghese 			eth_type = mpls->mpls_ethertype;
3332f66b53fdSMartin Varghese 			break;
3333f66b53fdSMartin Varghese 		}
3334f66b53fdSMartin Varghese 
333525cd9ba0SSimon Horman 		case OVS_ACTION_ATTR_PUSH_MPLS: {
333625cd9ba0SSimon Horman 			const struct ovs_action_push_mpls *mpls = nla_data(a);
333725cd9ba0SSimon Horman 
333825cd9ba0SSimon Horman 			if (!eth_p_mpls(mpls->mpls_ethertype))
333925cd9ba0SSimon Horman 				return -EINVAL;
334025cd9ba0SSimon Horman 			/* Prohibit push MPLS other than to a white list
334125cd9ba0SSimon Horman 			 * for packets that have a known tag order.
334225cd9ba0SSimon Horman 			 */
33439df46aefSMichał Mirosław 			if (vlan_tci & htons(VLAN_CFI_MASK) ||
334425cd9ba0SSimon Horman 			    (eth_type != htons(ETH_P_IP) &&
334525cd9ba0SSimon Horman 			     eth_type != htons(ETH_P_IPV6) &&
334625cd9ba0SSimon Horman 			     eth_type != htons(ETH_P_ARP) &&
334725cd9ba0SSimon Horman 			     eth_type != htons(ETH_P_RARP) &&
334825cd9ba0SSimon Horman 			     !eth_p_mpls(eth_type)))
334925cd9ba0SSimon Horman 				return -EINVAL;
335025cd9ba0SSimon Horman 			eth_type = mpls->mpls_ethertype;
3351fbdcdd78SMartin Varghese 			mpls_label_count++;
335225cd9ba0SSimon Horman 			break;
335325cd9ba0SSimon Horman 		}
335425cd9ba0SSimon Horman 
3355fbdcdd78SMartin Varghese 		case OVS_ACTION_ATTR_POP_MPLS: {
3356fbdcdd78SMartin Varghese 			__be16  proto;
33579df46aefSMichał Mirosław 			if (vlan_tci & htons(VLAN_CFI_MASK) ||
335825cd9ba0SSimon Horman 			    !eth_p_mpls(eth_type))
335925cd9ba0SSimon Horman 				return -EINVAL;
336025cd9ba0SSimon Horman 
3361fbdcdd78SMartin Varghese 			/* Disallow subsequent L2.5+ set actions and mpls_pop
3362fbdcdd78SMartin Varghese 			 * actions once the last MPLS label in the packet is
3363169ccf0eSJilin Yuan 			 * popped as there is no check here to ensure that
3364fbdcdd78SMartin Varghese 			 * the new eth type is valid and thus set actions could
3365fbdcdd78SMartin Varghese 			 * write off the end of the packet or otherwise corrupt
3366fbdcdd78SMartin Varghese 			 * it.
336725cd9ba0SSimon Horman 			 *
336825cd9ba0SSimon Horman 			 * Support for these actions is planned using packet
336925cd9ba0SSimon Horman 			 * recirculation.
337025cd9ba0SSimon Horman 			 */
3371fbdcdd78SMartin Varghese 			proto = nla_get_be16(a);
3372f66b53fdSMartin Varghese 
3373f66b53fdSMartin Varghese 			if (proto == htons(ETH_P_TEB) &&
3374f66b53fdSMartin Varghese 			    mac_proto != MAC_PROTO_NONE)
3375f66b53fdSMartin Varghese 				return -EINVAL;
3376f66b53fdSMartin Varghese 
3377fbdcdd78SMartin Varghese 			mpls_label_count--;
3378fbdcdd78SMartin Varghese 
3379fbdcdd78SMartin Varghese 			if (!eth_p_mpls(proto) || !mpls_label_count)
338025cd9ba0SSimon Horman 				eth_type = htons(0);
3381fbdcdd78SMartin Varghese 			else
3382fbdcdd78SMartin Varghese 				eth_type =  proto;
3383fbdcdd78SMartin Varghese 
338425cd9ba0SSimon Horman 			break;
3385fbdcdd78SMartin Varghese 		}
338625cd9ba0SSimon Horman 
3387e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_SET:
338825cd9ba0SSimon Horman 			err = validate_set(a, key, sfa,
33890a6410fbSJiri Benc 					   &skip_copy, mac_proto, eth_type,
33900a6410fbSJiri Benc 					   false, log);
339183d2b9baSJarno Rajahalme 			if (err)
339283d2b9baSJarno Rajahalme 				return err;
339383d2b9baSJarno Rajahalme 			break;
339483d2b9baSJarno Rajahalme 
339583d2b9baSJarno Rajahalme 		case OVS_ACTION_ATTR_SET_MASKED:
339683d2b9baSJarno Rajahalme 			err = validate_set(a, key, sfa,
33970a6410fbSJiri Benc 					   &skip_copy, mac_proto, eth_type,
33980a6410fbSJiri Benc 					   true, log);
3399e6445719SPravin B Shelar 			if (err)
3400e6445719SPravin B Shelar 				return err;
3401e6445719SPravin B Shelar 			break;
3402e6445719SPravin B Shelar 
3403798c1661Sandy zhou 		case OVS_ACTION_ATTR_SAMPLE: {
3404798c1661Sandy zhou 			bool last = nla_is_last(a, rem);
3405798c1661Sandy zhou 
3406798c1661Sandy zhou 			err = validate_and_copy_sample(net, a, key, sfa,
3407798c1661Sandy zhou 						       eth_type, vlan_tci,
3408fbdcdd78SMartin Varghese 						       mpls_label_count,
34096e2f90d3SAaron Conole 						       log, last, depth);
3410e6445719SPravin B Shelar 			if (err)
3411e6445719SPravin B Shelar 				return err;
3412e6445719SPravin B Shelar 			skip_copy = true;
3413e6445719SPravin B Shelar 			break;
3414798c1661Sandy zhou 		}
3415e6445719SPravin B Shelar 
34167f8a436eSJoe Stringer 		case OVS_ACTION_ATTR_CT:
34177f8a436eSJoe Stringer 			err = ovs_ct_copy_action(net, a, key, sfa, log);
34187f8a436eSJoe Stringer 			if (err)
34197f8a436eSJoe Stringer 				return err;
34207f8a436eSJoe Stringer 			skip_copy = true;
34217f8a436eSJoe Stringer 			break;
34227f8a436eSJoe Stringer 
3423b8226962SEric Garver 		case OVS_ACTION_ATTR_CT_CLEAR:
3424b8226962SEric Garver 			break;
3425b8226962SEric Garver 
342691820da6SJiri Benc 		case OVS_ACTION_ATTR_PUSH_ETH:
342791820da6SJiri Benc 			/* Disallow pushing an Ethernet header if one
342891820da6SJiri Benc 			 * is already present */
342991820da6SJiri Benc 			if (mac_proto != MAC_PROTO_NONE)
343091820da6SJiri Benc 				return -EINVAL;
343146ebe283SJaime Caamaño Ruiz 			mac_proto = MAC_PROTO_ETHERNET;
343291820da6SJiri Benc 			break;
343391820da6SJiri Benc 
343491820da6SJiri Benc 		case OVS_ACTION_ATTR_POP_ETH:
343591820da6SJiri Benc 			if (mac_proto != MAC_PROTO_ETHERNET)
343691820da6SJiri Benc 				return -EINVAL;
34379df46aefSMichał Mirosław 			if (vlan_tci & htons(VLAN_CFI_MASK))
343891820da6SJiri Benc 				return -EINVAL;
343946ebe283SJaime Caamaño Ruiz 			mac_proto = MAC_PROTO_NONE;
344091820da6SJiri Benc 			break;
344191820da6SJiri Benc 
3442b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_PUSH_NSH:
3443b2d0f5d5SYi Yang 			if (mac_proto != MAC_PROTO_ETHERNET) {
3444b2d0f5d5SYi Yang 				u8 next_proto;
3445b2d0f5d5SYi Yang 
3446b2d0f5d5SYi Yang 				next_proto = tun_p_from_eth_p(eth_type);
3447b2d0f5d5SYi Yang 				if (!next_proto)
3448b2d0f5d5SYi Yang 					return -EINVAL;
3449b2d0f5d5SYi Yang 			}
3450b2d0f5d5SYi Yang 			mac_proto = MAC_PROTO_NONE;
3451b2d0f5d5SYi Yang 			if (!validate_nsh(nla_data(a), false, true, true))
3452b2d0f5d5SYi Yang 				return -EINVAL;
3453b2d0f5d5SYi Yang 			break;
3454b2d0f5d5SYi Yang 
3455b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_POP_NSH: {
3456b2d0f5d5SYi Yang 			__be16 inner_proto;
3457b2d0f5d5SYi Yang 
3458b2d0f5d5SYi Yang 			if (eth_type != htons(ETH_P_NSH))
3459b2d0f5d5SYi Yang 				return -EINVAL;
3460b2d0f5d5SYi Yang 			inner_proto = tun_p_to_eth_p(key->nsh.base.np);
3461b2d0f5d5SYi Yang 			if (!inner_proto)
3462b2d0f5d5SYi Yang 				return -EINVAL;
3463b2d0f5d5SYi Yang 			if (key->nsh.base.np == TUN_P_ETHERNET)
3464b2d0f5d5SYi Yang 				mac_proto = MAC_PROTO_ETHERNET;
3465b2d0f5d5SYi Yang 			else
3466b2d0f5d5SYi Yang 				mac_proto = MAC_PROTO_NONE;
3467b2d0f5d5SYi Yang 			break;
3468b2d0f5d5SYi Yang 		}
3469b2d0f5d5SYi Yang 
3470cd8a6c33SAndy Zhou 		case OVS_ACTION_ATTR_METER:
3471cd8a6c33SAndy Zhou 			/* Non-existent meters are simply ignored.  */
3472cd8a6c33SAndy Zhou 			break;
3473cd8a6c33SAndy Zhou 
3474b2335040SYifeng Sun 		case OVS_ACTION_ATTR_CLONE: {
3475b2335040SYifeng Sun 			bool last = nla_is_last(a, rem);
3476b2335040SYifeng Sun 
3477b2335040SYifeng Sun 			err = validate_and_copy_clone(net, a, key, sfa,
3478b2335040SYifeng Sun 						      eth_type, vlan_tci,
3479fbdcdd78SMartin Varghese 						      mpls_label_count,
34806e2f90d3SAaron Conole 						      log, last, depth);
3481b2335040SYifeng Sun 			if (err)
3482b2335040SYifeng Sun 				return err;
3483b2335040SYifeng Sun 			skip_copy = true;
3484b2335040SYifeng Sun 			break;
3485b2335040SYifeng Sun 		}
3486b2335040SYifeng Sun 
34874d5ec89fSNuman Siddique 		case OVS_ACTION_ATTR_CHECK_PKT_LEN: {
34884d5ec89fSNuman Siddique 			bool last = nla_is_last(a, rem);
34894d5ec89fSNuman Siddique 
34904d5ec89fSNuman Siddique 			err = validate_and_copy_check_pkt_len(net, a, key, sfa,
34914d5ec89fSNuman Siddique 							      eth_type,
3492fbdcdd78SMartin Varghese 							      vlan_tci,
3493fbdcdd78SMartin Varghese 							      mpls_label_count,
34946e2f90d3SAaron Conole 							      log, last,
34956e2f90d3SAaron Conole 							      depth);
34964d5ec89fSNuman Siddique 			if (err)
34974d5ec89fSNuman Siddique 				return err;
34984d5ec89fSNuman Siddique 			skip_copy = true;
34994d5ec89fSNuman Siddique 			break;
35004d5ec89fSNuman Siddique 		}
35014d5ec89fSNuman Siddique 
3502744676e7SMatteo Croce 		case OVS_ACTION_ATTR_DEC_TTL:
3503744676e7SMatteo Croce 			err = validate_and_copy_dec_ttl(net, a, key, sfa,
3504744676e7SMatteo Croce 							eth_type, vlan_tci,
35056e2f90d3SAaron Conole 							mpls_label_count, log,
35066e2f90d3SAaron Conole 							depth);
3507744676e7SMatteo Croce 			if (err)
3508744676e7SMatteo Croce 				return err;
3509744676e7SMatteo Croce 			skip_copy = true;
3510744676e7SMatteo Croce 			break;
3511744676e7SMatteo Croce 
3512e7bc7db9SEric Garver 		case OVS_ACTION_ATTR_DROP:
3513e7bc7db9SEric Garver 			if (!nla_is_last(a, rem))
3514e7bc7db9SEric Garver 				return -EINVAL;
3515e7bc7db9SEric Garver 			break;
3516e7bc7db9SEric Garver 
3517aae0b82bSAdrian Moreno 		case OVS_ACTION_ATTR_PSAMPLE:
3518aae0b82bSAdrian Moreno 			err = validate_psample(a);
3519aae0b82bSAdrian Moreno 			if (err)
3520aae0b82bSAdrian Moreno 				return err;
3521aae0b82bSAdrian Moreno 			break;
3522aae0b82bSAdrian Moreno 
3523e6445719SPravin B Shelar 		default:
352405da5898SJarno Rajahalme 			OVS_NLERR(log, "Unknown Action type %d", type);
3525e6445719SPravin B Shelar 			return -EINVAL;
3526e6445719SPravin B Shelar 		}
3527e6445719SPravin B Shelar 		if (!skip_copy) {
352805da5898SJarno Rajahalme 			err = copy_action(a, sfa, log);
3529e6445719SPravin B Shelar 			if (err)
3530e6445719SPravin B Shelar 				return err;
3531e6445719SPravin B Shelar 		}
3532e6445719SPravin B Shelar 	}
3533e6445719SPravin B Shelar 
3534e6445719SPravin B Shelar 	if (rem > 0)
3535e6445719SPravin B Shelar 		return -EINVAL;
3536e6445719SPravin B Shelar 
3537e6445719SPravin B Shelar 	return 0;
3538e6445719SPravin B Shelar }
3539e6445719SPravin B Shelar 
354083d2b9baSJarno Rajahalme /* 'key' must be the masked key. */
ovs_nla_copy_actions(struct net * net,const struct nlattr * attr,const struct sw_flow_key * key,struct sw_flow_actions ** sfa,bool log)35417f8a436eSJoe Stringer int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
354225cd9ba0SSimon Horman 			 const struct sw_flow_key *key,
354305da5898SJarno Rajahalme 			 struct sw_flow_actions **sfa, bool log)
354425cd9ba0SSimon Horman {
35452fdb957dSPravin B Shelar 	int err;
3546fbdcdd78SMartin Varghese 	u32 mpls_label_count = 0;
35472fdb957dSPravin B Shelar 
354867c8d22aSzhangliping 	*sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE));
35492fdb957dSPravin B Shelar 	if (IS_ERR(*sfa))
35502fdb957dSPravin B Shelar 		return PTR_ERR(*sfa);
35512fdb957dSPravin B Shelar 
3552fbdcdd78SMartin Varghese 	if (eth_p_mpls(key->eth.type))
3553fbdcdd78SMartin Varghese 		mpls_label_count = hweight_long(key->mpls.num_labels_mask);
3554fbdcdd78SMartin Varghese 
35558e2fed1cSJoe Stringer 	(*sfa)->orig_len = nla_len(attr);
3556798c1661Sandy zhou 	err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type,
35576e2f90d3SAaron Conole 				     key->eth.vlan.tci, mpls_label_count, log,
35586e2f90d3SAaron Conole 				     0);
35592fdb957dSPravin B Shelar 	if (err)
356034ae932aSThomas Graf 		ovs_nla_free_flow_actions(*sfa);
35612fdb957dSPravin B Shelar 
35622fdb957dSPravin B Shelar 	return err;
356325cd9ba0SSimon Horman }
356425cd9ba0SSimon Horman 
sample_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)3565798c1661Sandy zhou static int sample_action_to_attr(const struct nlattr *attr,
3566798c1661Sandy zhou 				 struct sk_buff *skb)
3567e6445719SPravin B Shelar {
3568798c1661Sandy zhou 	struct nlattr *start, *ac_start = NULL, *sample_arg;
3569798c1661Sandy zhou 	int err = 0, rem = nla_len(attr);
3570798c1661Sandy zhou 	const struct sample_arg *arg;
3571798c1661Sandy zhou 	struct nlattr *actions;
3572e6445719SPravin B Shelar 
3573ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SAMPLE);
3574e6445719SPravin B Shelar 	if (!start)
3575e6445719SPravin B Shelar 		return -EMSGSIZE;
3576e6445719SPravin B Shelar 
3577798c1661Sandy zhou 	sample_arg = nla_data(attr);
3578798c1661Sandy zhou 	arg = nla_data(sample_arg);
3579798c1661Sandy zhou 	actions = nla_next(sample_arg, &rem);
3580e6445719SPravin B Shelar 
3581798c1661Sandy zhou 	if (nla_put_u32(skb, OVS_SAMPLE_ATTR_PROBABILITY, arg->probability)) {
3582798c1661Sandy zhou 		err = -EMSGSIZE;
3583798c1661Sandy zhou 		goto out;
3584e6445719SPravin B Shelar 	}
3585e6445719SPravin B Shelar 
3586ae0be8deSMichal Kubecek 	ac_start = nla_nest_start_noflag(skb, OVS_SAMPLE_ATTR_ACTIONS);
3587798c1661Sandy zhou 	if (!ac_start) {
3588798c1661Sandy zhou 		err = -EMSGSIZE;
3589798c1661Sandy zhou 		goto out;
3590798c1661Sandy zhou 	}
3591798c1661Sandy zhou 
3592798c1661Sandy zhou 	err = ovs_nla_put_actions(actions, rem, skb);
3593798c1661Sandy zhou 
3594798c1661Sandy zhou out:
3595798c1661Sandy zhou 	if (err) {
3596798c1661Sandy zhou 		nla_nest_cancel(skb, ac_start);
3597798c1661Sandy zhou 		nla_nest_cancel(skb, start);
3598798c1661Sandy zhou 	} else {
3599798c1661Sandy zhou 		nla_nest_end(skb, ac_start);
3600e6445719SPravin B Shelar 		nla_nest_end(skb, start);
3601798c1661Sandy zhou 	}
3602798c1661Sandy zhou 
3603e6445719SPravin B Shelar 	return err;
3604e6445719SPravin B Shelar }
3605e6445719SPravin B Shelar 
clone_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)3606b2335040SYifeng Sun static int clone_action_to_attr(const struct nlattr *attr,
3607b2335040SYifeng Sun 				struct sk_buff *skb)
3608b2335040SYifeng Sun {
3609b2335040SYifeng Sun 	struct nlattr *start;
3610b2335040SYifeng Sun 	int err = 0, rem = nla_len(attr);
3611b2335040SYifeng Sun 
3612ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CLONE);
3613b2335040SYifeng Sun 	if (!start)
3614b2335040SYifeng Sun 		return -EMSGSIZE;
3615b2335040SYifeng Sun 
36163f2a3050SIlya Maximets 	/* Skipping the OVS_CLONE_ATTR_EXEC that is always the first attribute. */
36173f2a3050SIlya Maximets 	attr = nla_next(nla_data(attr), &rem);
36183f2a3050SIlya Maximets 	err = ovs_nla_put_actions(attr, rem, skb);
3619b2335040SYifeng Sun 
3620b2335040SYifeng Sun 	if (err)
3621b2335040SYifeng Sun 		nla_nest_cancel(skb, start);
3622b2335040SYifeng Sun 	else
3623b2335040SYifeng Sun 		nla_nest_end(skb, start);
3624b2335040SYifeng Sun 
3625b2335040SYifeng Sun 	return err;
3626b2335040SYifeng Sun }
3627b2335040SYifeng Sun 
check_pkt_len_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)36284d5ec89fSNuman Siddique static int check_pkt_len_action_to_attr(const struct nlattr *attr,
36294d5ec89fSNuman Siddique 					struct sk_buff *skb)
36304d5ec89fSNuman Siddique {
36314d5ec89fSNuman Siddique 	struct nlattr *start, *ac_start = NULL;
36324d5ec89fSNuman Siddique 	const struct check_pkt_len_arg *arg;
36334d5ec89fSNuman Siddique 	const struct nlattr *a, *cpl_arg;
36344d5ec89fSNuman Siddique 	int err = 0, rem = nla_len(attr);
36354d5ec89fSNuman Siddique 
3636ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CHECK_PKT_LEN);
36374d5ec89fSNuman Siddique 	if (!start)
36384d5ec89fSNuman Siddique 		return -EMSGSIZE;
36394d5ec89fSNuman Siddique 
36404d5ec89fSNuman Siddique 	/* The first nested attribute in 'attr' is always
36414d5ec89fSNuman Siddique 	 * 'OVS_CHECK_PKT_LEN_ATTR_ARG'.
36424d5ec89fSNuman Siddique 	 */
36434d5ec89fSNuman Siddique 	cpl_arg = nla_data(attr);
36444d5ec89fSNuman Siddique 	arg = nla_data(cpl_arg);
36454d5ec89fSNuman Siddique 
36464d5ec89fSNuman Siddique 	if (nla_put_u16(skb, OVS_CHECK_PKT_LEN_ATTR_PKT_LEN, arg->pkt_len)) {
36474d5ec89fSNuman Siddique 		err = -EMSGSIZE;
36484d5ec89fSNuman Siddique 		goto out;
36494d5ec89fSNuman Siddique 	}
36504d5ec89fSNuman Siddique 
36514d5ec89fSNuman Siddique 	/* Second nested attribute in 'attr' is always
36524d5ec89fSNuman Siddique 	 * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL'.
36534d5ec89fSNuman Siddique 	 */
36544d5ec89fSNuman Siddique 	a = nla_next(cpl_arg, &rem);
3655ae0be8deSMichal Kubecek 	ac_start =  nla_nest_start_noflag(skb,
36564d5ec89fSNuman Siddique 					  OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL);
36574d5ec89fSNuman Siddique 	if (!ac_start) {
36584d5ec89fSNuman Siddique 		err = -EMSGSIZE;
36594d5ec89fSNuman Siddique 		goto out;
36604d5ec89fSNuman Siddique 	}
36614d5ec89fSNuman Siddique 
36624d5ec89fSNuman Siddique 	err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
36634d5ec89fSNuman Siddique 	if (err) {
36644d5ec89fSNuman Siddique 		nla_nest_cancel(skb, ac_start);
36654d5ec89fSNuman Siddique 		goto out;
36664d5ec89fSNuman Siddique 	} else {
36674d5ec89fSNuman Siddique 		nla_nest_end(skb, ac_start);
36684d5ec89fSNuman Siddique 	}
36694d5ec89fSNuman Siddique 
36704d5ec89fSNuman Siddique 	/* Third nested attribute in 'attr' is always
36714d5ec89fSNuman Siddique 	 * OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER.
36724d5ec89fSNuman Siddique 	 */
36734d5ec89fSNuman Siddique 	a = nla_next(a, &rem);
3674ae0be8deSMichal Kubecek 	ac_start =  nla_nest_start_noflag(skb,
36754d5ec89fSNuman Siddique 					  OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER);
36764d5ec89fSNuman Siddique 	if (!ac_start) {
36774d5ec89fSNuman Siddique 		err = -EMSGSIZE;
36784d5ec89fSNuman Siddique 		goto out;
36794d5ec89fSNuman Siddique 	}
36804d5ec89fSNuman Siddique 
36814d5ec89fSNuman Siddique 	err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
36824d5ec89fSNuman Siddique 	if (err) {
36834d5ec89fSNuman Siddique 		nla_nest_cancel(skb, ac_start);
36844d5ec89fSNuman Siddique 		goto out;
36854d5ec89fSNuman Siddique 	} else {
36864d5ec89fSNuman Siddique 		nla_nest_end(skb, ac_start);
36874d5ec89fSNuman Siddique 	}
36884d5ec89fSNuman Siddique 
36894d5ec89fSNuman Siddique 	nla_nest_end(skb, start);
36904d5ec89fSNuman Siddique 	return 0;
36914d5ec89fSNuman Siddique 
36924d5ec89fSNuman Siddique out:
36934d5ec89fSNuman Siddique 	nla_nest_cancel(skb, start);
36944d5ec89fSNuman Siddique 	return err;
36954d5ec89fSNuman Siddique }
36964d5ec89fSNuman Siddique 
dec_ttl_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)3697744676e7SMatteo Croce static int dec_ttl_action_to_attr(const struct nlattr *attr,
3698744676e7SMatteo Croce 				  struct sk_buff *skb)
3699744676e7SMatteo Croce {
370069929d4cSEelco Chaudron 	struct nlattr *start, *action_start;
370169929d4cSEelco Chaudron 	const struct nlattr *a;
370269929d4cSEelco Chaudron 	int err = 0, rem;
3703744676e7SMatteo Croce 
3704744676e7SMatteo Croce 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL);
3705744676e7SMatteo Croce 	if (!start)
3706744676e7SMatteo Croce 		return -EMSGSIZE;
3707744676e7SMatteo Croce 
370869929d4cSEelco Chaudron 	nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) {
370969929d4cSEelco Chaudron 		switch (nla_type(a)) {
371069929d4cSEelco Chaudron 		case OVS_DEC_TTL_ATTR_ACTION:
3711744676e7SMatteo Croce 
371269929d4cSEelco Chaudron 			action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION);
371369929d4cSEelco Chaudron 			if (!action_start) {
371469929d4cSEelco Chaudron 				err = -EMSGSIZE;
371569929d4cSEelco Chaudron 				goto out;
371669929d4cSEelco Chaudron 			}
371769929d4cSEelco Chaudron 
371869929d4cSEelco Chaudron 			err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
371969929d4cSEelco Chaudron 			if (err)
372069929d4cSEelco Chaudron 				goto out;
372169929d4cSEelco Chaudron 
372269929d4cSEelco Chaudron 			nla_nest_end(skb, action_start);
372369929d4cSEelco Chaudron 			break;
372469929d4cSEelco Chaudron 
372569929d4cSEelco Chaudron 		default:
372669929d4cSEelco Chaudron 			/* Ignore all other option to be future compatible */
372769929d4cSEelco Chaudron 			break;
372869929d4cSEelco Chaudron 		}
372969929d4cSEelco Chaudron 	}
373069929d4cSEelco Chaudron 
373169929d4cSEelco Chaudron 	nla_nest_end(skb, start);
373269929d4cSEelco Chaudron 	return 0;
373369929d4cSEelco Chaudron 
373469929d4cSEelco Chaudron out:
373569929d4cSEelco Chaudron 	nla_nest_cancel(skb, start);
3736744676e7SMatteo Croce 	return err;
3737744676e7SMatteo Croce }
3738744676e7SMatteo Croce 
set_action_to_attr(const struct nlattr * a,struct sk_buff * skb)3739e6445719SPravin B Shelar static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
3740e6445719SPravin B Shelar {
3741e6445719SPravin B Shelar 	const struct nlattr *ovs_key = nla_data(a);
3742e6445719SPravin B Shelar 	int key_type = nla_type(ovs_key);
3743e6445719SPravin B Shelar 	struct nlattr *start;
3744e6445719SPravin B Shelar 	int err;
3745e6445719SPravin B Shelar 
3746e6445719SPravin B Shelar 	switch (key_type) {
3747f0b128c1SJesse Gross 	case OVS_KEY_ATTR_TUNNEL_INFO: {
374834ae932aSThomas Graf 		struct ovs_tunnel_info *ovs_tun = nla_data(ovs_key);
374934ae932aSThomas Graf 		struct ip_tunnel_info *tun_info = &ovs_tun->tun_dst->u.tun_info;
3750f0b128c1SJesse Gross 
3751ae0be8deSMichal Kubecek 		start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET);
3752e6445719SPravin B Shelar 		if (!start)
3753e6445719SPravin B Shelar 			return -EMSGSIZE;
3754e6445719SPravin B Shelar 
3755e905eabcSSimon Horman 		err =  ip_tun_to_nlattr(skb, &tun_info->key,
3756e905eabcSSimon Horman 					ip_tunnel_info_opts(tun_info),
3757e905eabcSSimon Horman 					tun_info->options_len,
375818b6f717Swenxu 					ip_tunnel_info_af(tun_info), tun_info->mode);
3759e6445719SPravin B Shelar 		if (err)
3760e6445719SPravin B Shelar 			return err;
3761e6445719SPravin B Shelar 		nla_nest_end(skb, start);
3762e6445719SPravin B Shelar 		break;
3763f0b128c1SJesse Gross 	}
3764e6445719SPravin B Shelar 	default:
3765e6445719SPravin B Shelar 		if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
3766e6445719SPravin B Shelar 			return -EMSGSIZE;
3767e6445719SPravin B Shelar 		break;
3768e6445719SPravin B Shelar 	}
3769e6445719SPravin B Shelar 
3770e6445719SPravin B Shelar 	return 0;
3771e6445719SPravin B Shelar }
3772e6445719SPravin B Shelar 
masked_set_action_to_set_action_attr(const struct nlattr * a,struct sk_buff * skb)377383d2b9baSJarno Rajahalme static int masked_set_action_to_set_action_attr(const struct nlattr *a,
377483d2b9baSJarno Rajahalme 						struct sk_buff *skb)
377583d2b9baSJarno Rajahalme {
377683d2b9baSJarno Rajahalme 	const struct nlattr *ovs_key = nla_data(a);
3777f4f8e738SJoe Stringer 	struct nlattr *nla;
377883d2b9baSJarno Rajahalme 	size_t key_len = nla_len(ovs_key) / 2;
377983d2b9baSJarno Rajahalme 
378083d2b9baSJarno Rajahalme 	/* Revert the conversion we did from a non-masked set action to
378183d2b9baSJarno Rajahalme 	 * masked set action.
378283d2b9baSJarno Rajahalme 	 */
3783ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET);
3784f4f8e738SJoe Stringer 	if (!nla)
378583d2b9baSJarno Rajahalme 		return -EMSGSIZE;
378683d2b9baSJarno Rajahalme 
3787f4f8e738SJoe Stringer 	if (nla_put(skb, nla_type(ovs_key), key_len, nla_data(ovs_key)))
3788f4f8e738SJoe Stringer 		return -EMSGSIZE;
3789f4f8e738SJoe Stringer 
3790f4f8e738SJoe Stringer 	nla_nest_end(skb, nla);
379183d2b9baSJarno Rajahalme 	return 0;
379283d2b9baSJarno Rajahalme }
379383d2b9baSJarno Rajahalme 
ovs_nla_put_actions(const struct nlattr * attr,int len,struct sk_buff * skb)3794e6445719SPravin B Shelar int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb)
3795e6445719SPravin B Shelar {
3796e6445719SPravin B Shelar 	const struct nlattr *a;
3797e6445719SPravin B Shelar 	int rem, err;
3798e6445719SPravin B Shelar 
3799e6445719SPravin B Shelar 	nla_for_each_attr(a, attr, len, rem) {
3800e6445719SPravin B Shelar 		int type = nla_type(a);
3801e6445719SPravin B Shelar 
3802e6445719SPravin B Shelar 		switch (type) {
3803e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_SET:
3804e6445719SPravin B Shelar 			err = set_action_to_attr(a, skb);
3805e6445719SPravin B Shelar 			if (err)
3806e6445719SPravin B Shelar 				return err;
3807e6445719SPravin B Shelar 			break;
3808e6445719SPravin B Shelar 
380983d2b9baSJarno Rajahalme 		case OVS_ACTION_ATTR_SET_TO_MASKED:
381083d2b9baSJarno Rajahalme 			err = masked_set_action_to_set_action_attr(a, skb);
381183d2b9baSJarno Rajahalme 			if (err)
381283d2b9baSJarno Rajahalme 				return err;
381383d2b9baSJarno Rajahalme 			break;
381483d2b9baSJarno Rajahalme 
3815e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_SAMPLE:
3816e6445719SPravin B Shelar 			err = sample_action_to_attr(a, skb);
3817e6445719SPravin B Shelar 			if (err)
3818e6445719SPravin B Shelar 				return err;
3819e6445719SPravin B Shelar 			break;
38207f8a436eSJoe Stringer 
38217f8a436eSJoe Stringer 		case OVS_ACTION_ATTR_CT:
38227f8a436eSJoe Stringer 			err = ovs_ct_action_to_attr(nla_data(a), skb);
38237f8a436eSJoe Stringer 			if (err)
38247f8a436eSJoe Stringer 				return err;
38257f8a436eSJoe Stringer 			break;
38267f8a436eSJoe Stringer 
3827b2335040SYifeng Sun 		case OVS_ACTION_ATTR_CLONE:
3828b2335040SYifeng Sun 			err = clone_action_to_attr(a, skb);
3829b2335040SYifeng Sun 			if (err)
3830b2335040SYifeng Sun 				return err;
3831b2335040SYifeng Sun 			break;
3832b2335040SYifeng Sun 
38334d5ec89fSNuman Siddique 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
38344d5ec89fSNuman Siddique 			err = check_pkt_len_action_to_attr(a, skb);
38354d5ec89fSNuman Siddique 			if (err)
38364d5ec89fSNuman Siddique 				return err;
38374d5ec89fSNuman Siddique 			break;
38384d5ec89fSNuman Siddique 
3839744676e7SMatteo Croce 		case OVS_ACTION_ATTR_DEC_TTL:
3840744676e7SMatteo Croce 			err = dec_ttl_action_to_attr(a, skb);
3841744676e7SMatteo Croce 			if (err)
3842744676e7SMatteo Croce 				return err;
3843744676e7SMatteo Croce 			break;
3844744676e7SMatteo Croce 
3845e6445719SPravin B Shelar 		default:
3846e6445719SPravin B Shelar 			if (nla_put(skb, type, nla_len(a), nla_data(a)))
3847e6445719SPravin B Shelar 				return -EMSGSIZE;
3848e6445719SPravin B Shelar 			break;
3849e6445719SPravin B Shelar 		}
3850e6445719SPravin B Shelar 	}
3851e6445719SPravin B Shelar 
3852e6445719SPravin B Shelar 	return 0;
3853e6445719SPravin B Shelar }
3854