xref: /openbmc/linux/net/openvswitch/flow_netlink.c (revision 36db6e8484ed455bbb320d89a119378897ae991c)
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
515eeb2a9eSAaron 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:
67798c1661Sandy zhou 			break;
68798c1661Sandy zhou 
69798c1661Sandy zhou 		case OVS_ACTION_ATTR_CT:
70b8226962SEric Garver 		case OVS_ACTION_ATTR_CT_CLEAR:
71798c1661Sandy zhou 		case OVS_ACTION_ATTR_HASH:
72798c1661Sandy zhou 		case OVS_ACTION_ATTR_POP_ETH:
73798c1661Sandy zhou 		case OVS_ACTION_ATTR_POP_MPLS:
74b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_POP_NSH:
75798c1661Sandy zhou 		case OVS_ACTION_ATTR_POP_VLAN:
76798c1661Sandy zhou 		case OVS_ACTION_ATTR_PUSH_ETH:
77798c1661Sandy zhou 		case OVS_ACTION_ATTR_PUSH_MPLS:
78b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_PUSH_NSH:
79798c1661Sandy zhou 		case OVS_ACTION_ATTR_PUSH_VLAN:
80798c1661Sandy zhou 		case OVS_ACTION_ATTR_SAMPLE:
81798c1661Sandy zhou 		case OVS_ACTION_ATTR_SET:
82798c1661Sandy zhou 		case OVS_ACTION_ATTR_SET_MASKED:
83cd8a6c33SAndy Zhou 		case OVS_ACTION_ATTR_METER:
844d5ec89fSNuman Siddique 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
85f66b53fdSMartin Varghese 		case OVS_ACTION_ATTR_ADD_MPLS:
86744676e7SMatteo Croce 		case OVS_ACTION_ATTR_DEC_TTL:
87798c1661Sandy zhou 		default:
88798c1661Sandy zhou 			return true;
89798c1661Sandy zhou 		}
90798c1661Sandy zhou 	}
91798c1661Sandy zhou 	return false;
92798c1661Sandy zhou }
93798c1661Sandy zhou 
update_range(struct sw_flow_match * match,size_t offset,size_t size,bool is_mask)94a85311bfSPravin B Shelar static void update_range(struct sw_flow_match *match,
95e6445719SPravin B Shelar 			 size_t offset, size_t size, bool is_mask)
96e6445719SPravin B Shelar {
97a85311bfSPravin B Shelar 	struct sw_flow_key_range *range;
98e6445719SPravin B Shelar 	size_t start = rounddown(offset, sizeof(long));
99e6445719SPravin B Shelar 	size_t end = roundup(offset + size, sizeof(long));
100e6445719SPravin B Shelar 
101e6445719SPravin B Shelar 	if (!is_mask)
102e6445719SPravin B Shelar 		range = &match->range;
103a85311bfSPravin B Shelar 	else
104e6445719SPravin B Shelar 		range = &match->mask->range;
105e6445719SPravin B Shelar 
106e6445719SPravin B Shelar 	if (range->start == range->end) {
107e6445719SPravin B Shelar 		range->start = start;
108e6445719SPravin B Shelar 		range->end = end;
109e6445719SPravin B Shelar 		return;
110e6445719SPravin B Shelar 	}
111e6445719SPravin B Shelar 
112e6445719SPravin B Shelar 	if (range->start > start)
113e6445719SPravin B Shelar 		range->start = start;
114e6445719SPravin B Shelar 
115e6445719SPravin B Shelar 	if (range->end < end)
116e6445719SPravin B Shelar 		range->end = end;
117e6445719SPravin B Shelar }
118e6445719SPravin B Shelar 
119e6445719SPravin B Shelar #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
120e6445719SPravin B Shelar 	do { \
121a85311bfSPravin B Shelar 		update_range(match, offsetof(struct sw_flow_key, field),    \
122e6445719SPravin B Shelar 			     sizeof((match)->key->field), is_mask);	    \
123a85311bfSPravin B Shelar 		if (is_mask)						    \
124e6445719SPravin B Shelar 			(match)->mask->key.field = value;		    \
125a85311bfSPravin B Shelar 		else							    \
126e6445719SPravin B Shelar 			(match)->key->field = value;		            \
127e6445719SPravin B Shelar 	} while (0)
128e6445719SPravin B Shelar 
129f5796684SJesse Gross #define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask)	    \
130e6445719SPravin B Shelar 	do {								    \
131a85311bfSPravin B Shelar 		update_range(match, offset, len, is_mask);		    \
132f5796684SJesse Gross 		if (is_mask)						    \
133f5796684SJesse Gross 			memcpy((u8 *)&(match)->mask->key + offset, value_p, \
134f5796684SJesse Gross 			       len);					   \
135f5796684SJesse Gross 		else							    \
136f5796684SJesse Gross 			memcpy((u8 *)(match)->key + offset, value_p, len);  \
137e6445719SPravin B Shelar 	} while (0)
138e6445719SPravin B Shelar 
139f5796684SJesse Gross #define SW_FLOW_KEY_MEMCPY(match, field, value_p, len, is_mask)		      \
140f5796684SJesse Gross 	SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \
141f5796684SJesse Gross 				  value_p, len, is_mask)
142f5796684SJesse Gross 
143f47de068SPravin B Shelar #define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask)		    \
144f47de068SPravin B Shelar 	do {								    \
145a85311bfSPravin B Shelar 		update_range(match, offsetof(struct sw_flow_key, field),    \
146f47de068SPravin B Shelar 			     sizeof((match)->key->field), is_mask);	    \
147a85311bfSPravin B Shelar 		if (is_mask)						    \
148f47de068SPravin B Shelar 			memset((u8 *)&(match)->mask->key.field, value,      \
149f47de068SPravin B Shelar 			       sizeof((match)->mask->key.field));	    \
150a85311bfSPravin B Shelar 		else							    \
151f47de068SPravin B Shelar 			memset((u8 *)&(match)->key->field, value,           \
152f47de068SPravin B Shelar 			       sizeof((match)->key->field));                \
153f47de068SPravin B Shelar 	} while (0)
154e6445719SPravin B Shelar 
match_validate(const struct sw_flow_match * match,u64 key_attrs,u64 mask_attrs,bool log)155e6445719SPravin B Shelar static bool match_validate(const struct sw_flow_match *match,
15605da5898SJarno Rajahalme 			   u64 key_attrs, u64 mask_attrs, bool log)
157e6445719SPravin B Shelar {
1580a6410fbSJiri Benc 	u64 key_expected = 0;
159e6445719SPravin B Shelar 	u64 mask_allowed = key_attrs;  /* At most allow all key attributes */
160e6445719SPravin B Shelar 
161e6445719SPravin B Shelar 	/* The following mask attributes allowed only if they
162e6445719SPravin B Shelar 	 * pass the validation tests. */
163e6445719SPravin B Shelar 	mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4)
1649dd7f890SJarno Rajahalme 			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)
165e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_IPV6)
1669dd7f890SJarno Rajahalme 			| (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)
167e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_TCP)
1685eb26b15SJarno Rajahalme 			| (1 << OVS_KEY_ATTR_TCP_FLAGS)
169e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_UDP)
170e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_SCTP)
171e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_ICMP)
172e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_ICMPV6)
173e6445719SPravin B Shelar 			| (1 << OVS_KEY_ATTR_ARP)
17425cd9ba0SSimon Horman 			| (1 << OVS_KEY_ATTR_ND)
175b2d0f5d5SYi Yang 			| (1 << OVS_KEY_ATTR_MPLS)
176b2d0f5d5SYi Yang 			| (1 << OVS_KEY_ATTR_NSH));
177e6445719SPravin B Shelar 
178e6445719SPravin B Shelar 	/* Always allowed mask fields. */
179e6445719SPravin B Shelar 	mask_allowed |= ((1 << OVS_KEY_ATTR_TUNNEL)
180e6445719SPravin B Shelar 		       | (1 << OVS_KEY_ATTR_IN_PORT)
181e6445719SPravin B Shelar 		       | (1 << OVS_KEY_ATTR_ETHERTYPE));
182e6445719SPravin B Shelar 
183e6445719SPravin B Shelar 	/* Check key attributes. */
184e6445719SPravin B Shelar 	if (match->key->eth.type == htons(ETH_P_ARP)
185e6445719SPravin B Shelar 			|| match->key->eth.type == htons(ETH_P_RARP)) {
186e6445719SPravin B Shelar 		key_expected |= 1 << OVS_KEY_ATTR_ARP;
187f2a01517SPravin B Shelar 		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
188e6445719SPravin B Shelar 			mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
189e6445719SPravin B Shelar 	}
190e6445719SPravin B Shelar 
19125cd9ba0SSimon Horman 	if (eth_p_mpls(match->key->eth.type)) {
19225cd9ba0SSimon Horman 		key_expected |= 1 << OVS_KEY_ATTR_MPLS;
19325cd9ba0SSimon Horman 		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
19425cd9ba0SSimon Horman 			mask_allowed |= 1 << OVS_KEY_ATTR_MPLS;
19525cd9ba0SSimon Horman 	}
19625cd9ba0SSimon Horman 
197e6445719SPravin B Shelar 	if (match->key->eth.type == htons(ETH_P_IP)) {
198e6445719SPravin B Shelar 		key_expected |= 1 << OVS_KEY_ATTR_IPV4;
1999dd7f890SJarno Rajahalme 		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {
200e6445719SPravin B Shelar 			mask_allowed |= 1 << OVS_KEY_ATTR_IPV4;
2019dd7f890SJarno Rajahalme 			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4;
2029dd7f890SJarno Rajahalme 		}
203e6445719SPravin B Shelar 
204e6445719SPravin B Shelar 		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
205e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_UDP) {
206e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_UDP;
207e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
208e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
209e6445719SPravin B Shelar 			}
210e6445719SPravin B Shelar 
211e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_SCTP) {
212e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
213e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
214e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
215e6445719SPravin B Shelar 			}
216e6445719SPravin B Shelar 
217e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_TCP) {
218e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_TCP;
2195eb26b15SJarno Rajahalme 				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2205eb26b15SJarno Rajahalme 				if (match->mask && (match->mask->key.ip.proto == 0xff)) {
221e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
2225eb26b15SJarno Rajahalme 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2235eb26b15SJarno Rajahalme 				}
224e6445719SPravin B Shelar 			}
225e6445719SPravin B Shelar 
226e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_ICMP) {
227e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_ICMP;
228e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
229e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_ICMP;
230e6445719SPravin B Shelar 			}
231e6445719SPravin B Shelar 		}
232e6445719SPravin B Shelar 	}
233e6445719SPravin B Shelar 
234e6445719SPravin B Shelar 	if (match->key->eth.type == htons(ETH_P_IPV6)) {
235e6445719SPravin B Shelar 		key_expected |= 1 << OVS_KEY_ATTR_IPV6;
2369dd7f890SJarno Rajahalme 		if (match->mask && match->mask->key.eth.type == htons(0xffff)) {
237e6445719SPravin B Shelar 			mask_allowed |= 1 << OVS_KEY_ATTR_IPV6;
2389dd7f890SJarno Rajahalme 			mask_allowed |= 1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6;
2399dd7f890SJarno Rajahalme 		}
240e6445719SPravin B Shelar 
241e6445719SPravin B Shelar 		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
242e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_UDP) {
243e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_UDP;
244e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
245e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
246e6445719SPravin B Shelar 			}
247e6445719SPravin B Shelar 
248e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_SCTP) {
249e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
250e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
251e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
252e6445719SPravin B Shelar 			}
253e6445719SPravin B Shelar 
254e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_TCP) {
255e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_TCP;
2565eb26b15SJarno Rajahalme 				key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2575eb26b15SJarno Rajahalme 				if (match->mask && (match->mask->key.ip.proto == 0xff)) {
258e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
2595eb26b15SJarno Rajahalme 					mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS;
2605eb26b15SJarno Rajahalme 				}
261e6445719SPravin B Shelar 			}
262e6445719SPravin B Shelar 
263e6445719SPravin B Shelar 			if (match->key->ip.proto == IPPROTO_ICMPV6) {
264e6445719SPravin B Shelar 				key_expected |= 1 << OVS_KEY_ATTR_ICMPV6;
265e6445719SPravin B Shelar 				if (match->mask && (match->mask->key.ip.proto == 0xff))
266e6445719SPravin B Shelar 					mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6;
267e6445719SPravin B Shelar 
2681139e241SJarno Rajahalme 				if (match->key->tp.src ==
269e6445719SPravin B Shelar 						htons(NDISC_NEIGHBOUR_SOLICITATION) ||
2701139e241SJarno Rajahalme 				    match->key->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
271e6445719SPravin B Shelar 					key_expected |= 1 << OVS_KEY_ATTR_ND;
2729dd7f890SJarno Rajahalme 					/* Original direction conntrack tuple
2739dd7f890SJarno Rajahalme 					 * uses the same space as the ND fields
2749dd7f890SJarno Rajahalme 					 * in the key, so both are not allowed
2759dd7f890SJarno Rajahalme 					 * at the same time.
2769dd7f890SJarno Rajahalme 					 */
2779dd7f890SJarno Rajahalme 					mask_allowed &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
278f2a01517SPravin B Shelar 					if (match->mask && (match->mask->key.tp.src == htons(0xff)))
279e6445719SPravin B Shelar 						mask_allowed |= 1 << OVS_KEY_ATTR_ND;
280e6445719SPravin B Shelar 				}
281e6445719SPravin B Shelar 			}
282e6445719SPravin B Shelar 		}
283e6445719SPravin B Shelar 	}
284e6445719SPravin B Shelar 
285b2d0f5d5SYi Yang 	if (match->key->eth.type == htons(ETH_P_NSH)) {
286b2d0f5d5SYi Yang 		key_expected |= 1 << OVS_KEY_ATTR_NSH;
287b2d0f5d5SYi Yang 		if (match->mask &&
288b2d0f5d5SYi Yang 		    match->mask->key.eth.type == htons(0xffff)) {
289b2d0f5d5SYi Yang 			mask_allowed |= 1 << OVS_KEY_ATTR_NSH;
290b2d0f5d5SYi Yang 		}
291b2d0f5d5SYi Yang 	}
292b2d0f5d5SYi Yang 
293e6445719SPravin B Shelar 	if ((key_attrs & key_expected) != key_expected) {
294e6445719SPravin B Shelar 		/* Key attributes check failed. */
29505da5898SJarno Rajahalme 		OVS_NLERR(log, "Missing key (keys=%llx, expected=%llx)",
29605da5898SJarno Rajahalme 			  (unsigned long long)key_attrs,
29705da5898SJarno Rajahalme 			  (unsigned long long)key_expected);
298e6445719SPravin B Shelar 		return false;
299e6445719SPravin B Shelar 	}
300e6445719SPravin B Shelar 
301e6445719SPravin B Shelar 	if ((mask_attrs & mask_allowed) != mask_attrs) {
302e6445719SPravin B Shelar 		/* Mask attributes check failed. */
30305da5898SJarno Rajahalme 		OVS_NLERR(log, "Unexpected mask (mask=%llx, allowed=%llx)",
30405da5898SJarno Rajahalme 			  (unsigned long long)mask_attrs,
30505da5898SJarno Rajahalme 			  (unsigned long long)mask_allowed);
306e6445719SPravin B Shelar 		return false;
307e6445719SPravin B Shelar 	}
308e6445719SPravin B Shelar 
309e6445719SPravin B Shelar 	return true;
310e6445719SPravin B Shelar }
311e6445719SPravin B Shelar 
ovs_tun_key_attr_size(void)3128f0aad6fSWenyu Zhang size_t ovs_tun_key_attr_size(void)
3138f0aad6fSWenyu Zhang {
3148f0aad6fSWenyu Zhang 	/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
3158f0aad6fSWenyu Zhang 	 * updating this function.
3168f0aad6fSWenyu Zhang 	 */
317b46f6dedSNicolas Dichtel 	return    nla_total_size_64bit(8) /* OVS_TUNNEL_KEY_ATTR_ID */
3186b26ba3aSJiri Benc 		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */
3196b26ba3aSJiri Benc 		+ nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */
3208f0aad6fSWenyu Zhang 		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */
3218f0aad6fSWenyu Zhang 		+ nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TTL */
3228f0aad6fSWenyu Zhang 		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
3238f0aad6fSWenyu Zhang 		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_CSUM */
3248f0aad6fSWenyu Zhang 		+ nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_OAM */
3258f0aad6fSWenyu Zhang 		+ nla_total_size(256)  /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
326fc1372f8SWilliam Tu 		/* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and
327fc1372f8SWilliam Tu 		 * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with
3281dd144cfSThomas Graf 		 * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.
3291dd144cfSThomas Graf 		 */
3308f0aad6fSWenyu Zhang 		+ nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
33195a33208SWilliam Tu 		+ nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
3328f0aad6fSWenyu Zhang }
3338f0aad6fSWenyu Zhang 
ovs_nsh_key_attr_size(void)33406c2351fSWei Yongjun static size_t ovs_nsh_key_attr_size(void)
335b2d0f5d5SYi Yang {
336b2d0f5d5SYi Yang 	/* Whenever adding new OVS_NSH_KEY_ FIELDS, we should consider
337b2d0f5d5SYi Yang 	 * updating this function.
338b2d0f5d5SYi Yang 	 */
339b2d0f5d5SYi Yang 	return  nla_total_size(NSH_BASE_HDR_LEN) /* OVS_NSH_KEY_ATTR_BASE */
340b2d0f5d5SYi Yang 		/* OVS_NSH_KEY_ATTR_MD1 and OVS_NSH_KEY_ATTR_MD2 are
341b2d0f5d5SYi Yang 		 * mutually exclusive, so the bigger one can cover
342b2d0f5d5SYi Yang 		 * the small one.
343b2d0f5d5SYi Yang 		 */
344b2d0f5d5SYi Yang 		+ nla_total_size(NSH_CTX_HDRS_MAX_LEN);
345b2d0f5d5SYi Yang }
346b2d0f5d5SYi Yang 
ovs_key_attr_size(void)34741af73e9SJoe Stringer size_t ovs_key_attr_size(void)
34841af73e9SJoe Stringer {
34941af73e9SJoe Stringer 	/* Whenever adding new OVS_KEY_ FIELDS, we should consider
35041af73e9SJoe Stringer 	 * updating this function.
35141af73e9SJoe Stringer 	 */
3521926407aSIlya Maximets 	BUILD_BUG_ON(OVS_KEY_ATTR_MAX != 32);
35341af73e9SJoe Stringer 
35441af73e9SJoe Stringer 	return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */
35541af73e9SJoe Stringer 		+ nla_total_size(0)   /* OVS_KEY_ATTR_TUNNEL */
3568f0aad6fSWenyu Zhang 		  + ovs_tun_key_attr_size()
35741af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_IN_PORT */
35841af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */
35941af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */
36041af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */
361fbccce59SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_STATE */
3627f8a436eSJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_CT_ZONE */
363182e3042SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_CT_MARK */
36433db4125SJoe Stringer 		+ nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABELS */
3659dd7f890SJarno Rajahalme 		+ nla_total_size(40)  /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */
366b2d0f5d5SYi Yang 		+ nla_total_size(0)   /* OVS_KEY_ATTR_NSH */
367b2d0f5d5SYi Yang 		  + ovs_nsh_key_attr_size()
36841af73e9SJoe Stringer 		+ nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
36941af73e9SJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
37041af73e9SJoe Stringer 		+ nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
37141af73e9SJoe Stringer 		+ nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */
37241af73e9SJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
37341af73e9SJoe Stringer 		+ nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */
37441af73e9SJoe Stringer 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */
37528a3f060SToms Atteka 		+ nla_total_size(28)  /* OVS_KEY_ATTR_ND */
37628a3f060SToms Atteka 		+ nla_total_size(2);  /* OVS_KEY_ATTR_IPV6_EXTHDRS */
37741af73e9SJoe Stringer }
37841af73e9SJoe Stringer 
379982b5270SJesse Gross static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
380982b5270SJesse Gross 	[OVS_VXLAN_EXT_GBP]	    = { .len = sizeof(u32) },
381982b5270SJesse Gross };
382982b5270SJesse Gross 
38381bfe3c3SThomas Graf static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
38481bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_ID]	    = { .len = sizeof(u64) },
38581bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]	    = { .len = sizeof(u32) },
38681bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_IPV4_DST]	    = { .len = sizeof(u32) },
38781bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TOS]	    = { .len = 1 },
38881bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TTL]	    = { .len = 1 },
38981bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = { .len = 0 },
39081bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_CSUM]	    = { .len = 0 },
39181bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TP_SRC]	    = { .len = sizeof(u16) },
39281bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_TP_DST]	    = { .len = sizeof(u16) },
39381bfe3c3SThomas Graf 	[OVS_TUNNEL_KEY_ATTR_OAM]	    = { .len = 0 },
394982b5270SJesse Gross 	[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = OVS_ATTR_VARIABLE },
395982b5270SJesse Gross 	[OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = OVS_ATTR_NESTED,
396982b5270SJesse Gross 						.next = ovs_vxlan_ext_key_lens },
3976b26ba3aSJiri Benc 	[OVS_TUNNEL_KEY_ATTR_IPV6_SRC]      = { .len = sizeof(struct in6_addr) },
3986b26ba3aSJiri Benc 	[OVS_TUNNEL_KEY_ATTR_IPV6_DST]      = { .len = sizeof(struct in6_addr) },
399fc1372f8SWilliam Tu 	[OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS]   = { .len = OVS_ATTR_VARIABLE },
40018b6f717Swenxu 	[OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE]   = { .len = 0 },
40181bfe3c3SThomas Graf };
40281bfe3c3SThomas Graf 
403b2d0f5d5SYi Yang static const struct ovs_len_tbl
404b2d0f5d5SYi Yang ovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
405b2d0f5d5SYi Yang 	[OVS_NSH_KEY_ATTR_BASE] = { .len = sizeof(struct ovs_nsh_key_base) },
406b2d0f5d5SYi Yang 	[OVS_NSH_KEY_ATTR_MD1]  = { .len = sizeof(struct ovs_nsh_key_md1) },
407b2d0f5d5SYi Yang 	[OVS_NSH_KEY_ATTR_MD2]  = { .len = OVS_ATTR_VARIABLE },
408b2d0f5d5SYi Yang };
409b2d0f5d5SYi Yang 
410e6445719SPravin B Shelar /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
41181bfe3c3SThomas Graf static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
41281bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ENCAP]	 = { .len = OVS_ATTR_NESTED },
41381bfe3c3SThomas Graf 	[OVS_KEY_ATTR_PRIORITY]	 = { .len = sizeof(u32) },
41481bfe3c3SThomas Graf 	[OVS_KEY_ATTR_IN_PORT]	 = { .len = sizeof(u32) },
41581bfe3c3SThomas Graf 	[OVS_KEY_ATTR_SKB_MARK]	 = { .len = sizeof(u32) },
41681bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ETHERNET]	 = { .len = sizeof(struct ovs_key_ethernet) },
41781bfe3c3SThomas Graf 	[OVS_KEY_ATTR_VLAN]	 = { .len = sizeof(__be16) },
41881bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
41981bfe3c3SThomas Graf 	[OVS_KEY_ATTR_IPV4]	 = { .len = sizeof(struct ovs_key_ipv4) },
42081bfe3c3SThomas Graf 	[OVS_KEY_ATTR_IPV6]	 = { .len = sizeof(struct ovs_key_ipv6) },
42181bfe3c3SThomas Graf 	[OVS_KEY_ATTR_TCP]	 = { .len = sizeof(struct ovs_key_tcp) },
42281bfe3c3SThomas Graf 	[OVS_KEY_ATTR_TCP_FLAGS] = { .len = sizeof(__be16) },
42381bfe3c3SThomas Graf 	[OVS_KEY_ATTR_UDP]	 = { .len = sizeof(struct ovs_key_udp) },
42481bfe3c3SThomas Graf 	[OVS_KEY_ATTR_SCTP]	 = { .len = sizeof(struct ovs_key_sctp) },
42581bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ICMP]	 = { .len = sizeof(struct ovs_key_icmp) },
42681bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ICMPV6]	 = { .len = sizeof(struct ovs_key_icmpv6) },
42781bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ARP]	 = { .len = sizeof(struct ovs_key_arp) },
42881bfe3c3SThomas Graf 	[OVS_KEY_ATTR_ND]	 = { .len = sizeof(struct ovs_key_nd) },
42981bfe3c3SThomas Graf 	[OVS_KEY_ATTR_RECIRC_ID] = { .len = sizeof(u32) },
43081bfe3c3SThomas Graf 	[OVS_KEY_ATTR_DP_HASH]	 = { .len = sizeof(u32) },
43181bfe3c3SThomas Graf 	[OVS_KEY_ATTR_TUNNEL]	 = { .len = OVS_ATTR_NESTED,
43281bfe3c3SThomas Graf 				     .next = ovs_tunnel_key_lens, },
433fbdcdd78SMartin Varghese 	[OVS_KEY_ATTR_MPLS]	 = { .len = OVS_ATTR_VARIABLE },
434fbccce59SJoe Stringer 	[OVS_KEY_ATTR_CT_STATE]	 = { .len = sizeof(u32) },
4357f8a436eSJoe Stringer 	[OVS_KEY_ATTR_CT_ZONE]	 = { .len = sizeof(u16) },
436182e3042SJoe Stringer 	[OVS_KEY_ATTR_CT_MARK]	 = { .len = sizeof(u32) },
43733db4125SJoe Stringer 	[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
4389dd7f890SJarno Rajahalme 	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4] = {
4399dd7f890SJarno Rajahalme 		.len = sizeof(struct ovs_key_ct_tuple_ipv4) },
4409dd7f890SJarno Rajahalme 	[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {
4419dd7f890SJarno Rajahalme 		.len = sizeof(struct ovs_key_ct_tuple_ipv6) },
442b2d0f5d5SYi Yang 	[OVS_KEY_ATTR_NSH]       = { .len = OVS_ATTR_NESTED,
443b2d0f5d5SYi Yang 				     .next = ovs_nsh_key_attr_lens, },
44428a3f060SToms Atteka 	[OVS_KEY_ATTR_IPV6_EXTHDRS] = {
44528a3f060SToms Atteka 		.len = sizeof(struct ovs_key_ipv6_exthdrs) },
446e6445719SPravin B Shelar };
447e6445719SPravin B Shelar 
check_attr_len(unsigned int attr_len,unsigned int expected_len)448982b5270SJesse Gross static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
449982b5270SJesse Gross {
450982b5270SJesse Gross 	return expected_len == attr_len ||
451982b5270SJesse Gross 	       expected_len == OVS_ATTR_NESTED ||
452982b5270SJesse Gross 	       expected_len == OVS_ATTR_VARIABLE;
453982b5270SJesse Gross }
454982b5270SJesse Gross 
is_all_zero(const u8 * fp,size_t size)455e6445719SPravin B Shelar static bool is_all_zero(const u8 *fp, size_t size)
456e6445719SPravin B Shelar {
457e6445719SPravin B Shelar 	int i;
458e6445719SPravin B Shelar 
459e6445719SPravin B Shelar 	if (!fp)
460e6445719SPravin B Shelar 		return false;
461e6445719SPravin B Shelar 
462e6445719SPravin B Shelar 	for (i = 0; i < size; i++)
463e6445719SPravin B Shelar 		if (fp[i])
464e6445719SPravin B Shelar 			return false;
465e6445719SPravin B Shelar 
466e6445719SPravin B Shelar 	return true;
467e6445719SPravin B Shelar }
468e6445719SPravin B Shelar 
__parse_flow_nlattrs(const struct nlattr * attr,const struct nlattr * a[],u64 * attrsp,bool log,bool nz)469e6445719SPravin B Shelar static int __parse_flow_nlattrs(const struct nlattr *attr,
470e6445719SPravin B Shelar 				const struct nlattr *a[],
47105da5898SJarno Rajahalme 				u64 *attrsp, bool log, bool nz)
472e6445719SPravin B Shelar {
473e6445719SPravin B Shelar 	const struct nlattr *nla;
474e6445719SPravin B Shelar 	u64 attrs;
475e6445719SPravin B Shelar 	int rem;
476e6445719SPravin B Shelar 
477e6445719SPravin B Shelar 	attrs = *attrsp;
478e6445719SPravin B Shelar 	nla_for_each_nested(nla, attr, rem) {
479e6445719SPravin B Shelar 		u16 type = nla_type(nla);
480e6445719SPravin B Shelar 		int expected_len;
481e6445719SPravin B Shelar 
482e6445719SPravin B Shelar 		if (type > OVS_KEY_ATTR_MAX) {
48305da5898SJarno Rajahalme 			OVS_NLERR(log, "Key type %d is out of range max %d",
484e6445719SPravin B Shelar 				  type, OVS_KEY_ATTR_MAX);
485e6445719SPravin B Shelar 			return -EINVAL;
486e6445719SPravin B Shelar 		}
487e6445719SPravin B Shelar 
4881926407aSIlya Maximets 		if (type == OVS_KEY_ATTR_PACKET_TYPE ||
4891926407aSIlya Maximets 		    type == OVS_KEY_ATTR_ND_EXTENSIONS ||
4901926407aSIlya Maximets 		    type == OVS_KEY_ATTR_TUNNEL_INFO) {
4911926407aSIlya Maximets 			OVS_NLERR(log, "Key type %d is not supported", type);
4921926407aSIlya Maximets 			return -EINVAL;
4931926407aSIlya Maximets 		}
4941926407aSIlya Maximets 
4951926407aSIlya Maximets 		if (attrs & (1ULL << type)) {
49605da5898SJarno Rajahalme 			OVS_NLERR(log, "Duplicate key (type %d).", type);
497e6445719SPravin B Shelar 			return -EINVAL;
498e6445719SPravin B Shelar 		}
499e6445719SPravin B Shelar 
50081bfe3c3SThomas Graf 		expected_len = ovs_key_lens[type].len;
501982b5270SJesse Gross 		if (!check_attr_len(nla_len(nla), expected_len)) {
50205da5898SJarno Rajahalme 			OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
50305da5898SJarno Rajahalme 				  type, nla_len(nla), expected_len);
504e6445719SPravin B Shelar 			return -EINVAL;
505e6445719SPravin B Shelar 		}
506e6445719SPravin B Shelar 
50704a4af33SRoss Lagerwall 		if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
5081926407aSIlya Maximets 			attrs |= 1ULL << type;
509e6445719SPravin B Shelar 			a[type] = nla;
510e6445719SPravin B Shelar 		}
511e6445719SPravin B Shelar 	}
512e6445719SPravin B Shelar 	if (rem) {
51305da5898SJarno Rajahalme 		OVS_NLERR(log, "Message has %d unknown bytes.", rem);
514e6445719SPravin B Shelar 		return -EINVAL;
515e6445719SPravin B Shelar 	}
516e6445719SPravin B Shelar 
517e6445719SPravin B Shelar 	*attrsp = attrs;
518e6445719SPravin B Shelar 	return 0;
519e6445719SPravin B Shelar }
520e6445719SPravin B Shelar 
parse_flow_mask_nlattrs(const struct nlattr * attr,const struct nlattr * a[],u64 * attrsp,bool log)521e6445719SPravin B Shelar static int parse_flow_mask_nlattrs(const struct nlattr *attr,
52205da5898SJarno Rajahalme 				   const struct nlattr *a[], u64 *attrsp,
52305da5898SJarno Rajahalme 				   bool log)
524e6445719SPravin B Shelar {
52505da5898SJarno Rajahalme 	return __parse_flow_nlattrs(attr, a, attrsp, log, true);
526e6445719SPravin B Shelar }
527e6445719SPravin B Shelar 
parse_flow_nlattrs(const struct nlattr * attr,const struct nlattr * a[],u64 * attrsp,bool log)5289dd7f890SJarno Rajahalme int parse_flow_nlattrs(const struct nlattr *attr, const struct nlattr *a[],
5299dd7f890SJarno Rajahalme 		       u64 *attrsp, bool log)
530e6445719SPravin B Shelar {
53105da5898SJarno Rajahalme 	return __parse_flow_nlattrs(attr, a, attrsp, log, false);
53205da5898SJarno Rajahalme }
53305da5898SJarno Rajahalme 
genev_tun_opt_from_nlattr(const struct nlattr * a,struct sw_flow_match * match,bool is_mask,bool log)53405da5898SJarno Rajahalme static int genev_tun_opt_from_nlattr(const struct nlattr *a,
53505da5898SJarno Rajahalme 				     struct sw_flow_match *match, bool is_mask,
53605da5898SJarno Rajahalme 				     bool log)
53705da5898SJarno Rajahalme {
53805da5898SJarno Rajahalme 	unsigned long opt_key_offset;
53905da5898SJarno Rajahalme 
54005da5898SJarno Rajahalme 	if (nla_len(a) > sizeof(match->key->tun_opts)) {
54105da5898SJarno Rajahalme 		OVS_NLERR(log, "Geneve option length err (len %d, max %zu).",
54205da5898SJarno Rajahalme 			  nla_len(a), sizeof(match->key->tun_opts));
54305da5898SJarno Rajahalme 		return -EINVAL;
54405da5898SJarno Rajahalme 	}
54505da5898SJarno Rajahalme 
54605da5898SJarno Rajahalme 	if (nla_len(a) % 4 != 0) {
54705da5898SJarno Rajahalme 		OVS_NLERR(log, "Geneve opt len %d is not a multiple of 4.",
54805da5898SJarno Rajahalme 			  nla_len(a));
54905da5898SJarno Rajahalme 		return -EINVAL;
55005da5898SJarno Rajahalme 	}
55105da5898SJarno Rajahalme 
55205da5898SJarno Rajahalme 	/* We need to record the length of the options passed
55305da5898SJarno Rajahalme 	 * down, otherwise packets with the same format but
55405da5898SJarno Rajahalme 	 * additional options will be silently matched.
55505da5898SJarno Rajahalme 	 */
55605da5898SJarno Rajahalme 	if (!is_mask) {
55705da5898SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
55805da5898SJarno Rajahalme 				false);
55905da5898SJarno Rajahalme 	} else {
56005da5898SJarno Rajahalme 		/* This is somewhat unusual because it looks at
56105da5898SJarno Rajahalme 		 * both the key and mask while parsing the
56205da5898SJarno Rajahalme 		 * attributes (and by extension assumes the key
56305da5898SJarno Rajahalme 		 * is parsed first). Normally, we would verify
56405da5898SJarno Rajahalme 		 * that each is the correct length and that the
56505da5898SJarno Rajahalme 		 * attributes line up in the validate function.
56605da5898SJarno Rajahalme 		 * However, that is difficult because this is
56705da5898SJarno Rajahalme 		 * variable length and we won't have the
56805da5898SJarno Rajahalme 		 * information later.
56905da5898SJarno Rajahalme 		 */
57005da5898SJarno Rajahalme 		if (match->key->tun_opts_len != nla_len(a)) {
57105da5898SJarno Rajahalme 			OVS_NLERR(log, "Geneve option len %d != mask len %d",
57205da5898SJarno Rajahalme 				  match->key->tun_opts_len, nla_len(a));
57305da5898SJarno Rajahalme 			return -EINVAL;
57405da5898SJarno Rajahalme 		}
57505da5898SJarno Rajahalme 
57605da5898SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
57705da5898SJarno Rajahalme 	}
57805da5898SJarno Rajahalme 
579d91641d9SThomas Graf 	opt_key_offset = TUN_METADATA_OFFSET(nla_len(a));
58005da5898SJarno Rajahalme 	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
58105da5898SJarno Rajahalme 				  nla_len(a), is_mask);
58205da5898SJarno Rajahalme 	return 0;
583e6445719SPravin B Shelar }
584e6445719SPravin B Shelar 
vxlan_tun_opt_from_nlattr(const struct nlattr * attr,struct sw_flow_match * match,bool is_mask,bool log)585982b5270SJesse Gross static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
5861dd144cfSThomas Graf 				     struct sw_flow_match *match, bool is_mask,
5871dd144cfSThomas Graf 				     bool log)
5881dd144cfSThomas Graf {
589982b5270SJesse Gross 	struct nlattr *a;
590982b5270SJesse Gross 	int rem;
5911dd144cfSThomas Graf 	unsigned long opt_key_offset;
592614732eaSThomas Graf 	struct vxlan_metadata opts;
5931dd144cfSThomas Graf 
5941dd144cfSThomas Graf 	BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
5951dd144cfSThomas Graf 
5961dd144cfSThomas Graf 	memset(&opts, 0, sizeof(opts));
597982b5270SJesse Gross 	nla_for_each_nested(a, attr, rem) {
598982b5270SJesse Gross 		int type = nla_type(a);
5991dd144cfSThomas Graf 
600982b5270SJesse Gross 		if (type > OVS_VXLAN_EXT_MAX) {
601982b5270SJesse Gross 			OVS_NLERR(log, "VXLAN extension %d out of range max %d",
602982b5270SJesse Gross 				  type, OVS_VXLAN_EXT_MAX);
603982b5270SJesse Gross 			return -EINVAL;
604982b5270SJesse Gross 		}
605982b5270SJesse Gross 
606982b5270SJesse Gross 		if (!check_attr_len(nla_len(a),
607982b5270SJesse Gross 				    ovs_vxlan_ext_key_lens[type].len)) {
608982b5270SJesse Gross 			OVS_NLERR(log, "VXLAN extension %d has unexpected len %d expected %d",
609982b5270SJesse Gross 				  type, nla_len(a),
610982b5270SJesse Gross 				  ovs_vxlan_ext_key_lens[type].len);
611982b5270SJesse Gross 			return -EINVAL;
612982b5270SJesse Gross 		}
613982b5270SJesse Gross 
614982b5270SJesse Gross 		switch (type) {
615982b5270SJesse Gross 		case OVS_VXLAN_EXT_GBP:
616982b5270SJesse Gross 			opts.gbp = nla_get_u32(a);
617982b5270SJesse Gross 			break;
618982b5270SJesse Gross 		default:
619982b5270SJesse Gross 			OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
620982b5270SJesse Gross 				  type);
621982b5270SJesse Gross 			return -EINVAL;
622982b5270SJesse Gross 		}
623982b5270SJesse Gross 	}
624982b5270SJesse Gross 	if (rem) {
625982b5270SJesse Gross 		OVS_NLERR(log, "VXLAN extension message has %d unknown bytes.",
626982b5270SJesse Gross 			  rem);
627982b5270SJesse Gross 		return -EINVAL;
628982b5270SJesse Gross 	}
6291dd144cfSThomas Graf 
6301dd144cfSThomas Graf 	if (!is_mask)
6311dd144cfSThomas Graf 		SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), false);
6321dd144cfSThomas Graf 	else
6331dd144cfSThomas Graf 		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
6341dd144cfSThomas Graf 
6351dd144cfSThomas Graf 	opt_key_offset = TUN_METADATA_OFFSET(sizeof(opts));
6361dd144cfSThomas Graf 	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, &opts, sizeof(opts),
6371dd144cfSThomas Graf 				  is_mask);
6381dd144cfSThomas Graf 	return 0;
6391dd144cfSThomas Graf }
6401dd144cfSThomas Graf 
erspan_tun_opt_from_nlattr(const struct nlattr * a,struct sw_flow_match * match,bool is_mask,bool log)641fc1372f8SWilliam Tu static int erspan_tun_opt_from_nlattr(const struct nlattr *a,
642fc1372f8SWilliam Tu 				      struct sw_flow_match *match, bool is_mask,
643fc1372f8SWilliam Tu 				      bool log)
644fc1372f8SWilliam Tu {
645fc1372f8SWilliam Tu 	unsigned long opt_key_offset;
646fc1372f8SWilliam Tu 
647fc1372f8SWilliam Tu 	BUILD_BUG_ON(sizeof(struct erspan_metadata) >
648fc1372f8SWilliam Tu 		     sizeof(match->key->tun_opts));
649fc1372f8SWilliam Tu 
650fc1372f8SWilliam Tu 	if (nla_len(a) > sizeof(match->key->tun_opts)) {
651fc1372f8SWilliam Tu 		OVS_NLERR(log, "ERSPAN option length err (len %d, max %zu).",
652fc1372f8SWilliam Tu 			  nla_len(a), sizeof(match->key->tun_opts));
653fc1372f8SWilliam Tu 		return -EINVAL;
654fc1372f8SWilliam Tu 	}
655fc1372f8SWilliam Tu 
656fc1372f8SWilliam Tu 	if (!is_mask)
657fc1372f8SWilliam Tu 		SW_FLOW_KEY_PUT(match, tun_opts_len,
658fc1372f8SWilliam Tu 				sizeof(struct erspan_metadata), false);
659fc1372f8SWilliam Tu 	else
660fc1372f8SWilliam Tu 		SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
661fc1372f8SWilliam Tu 
662fc1372f8SWilliam Tu 	opt_key_offset = TUN_METADATA_OFFSET(nla_len(a));
663fc1372f8SWilliam Tu 	SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
664fc1372f8SWilliam Tu 				  nla_len(a), is_mask);
665fc1372f8SWilliam Tu 	return 0;
666fc1372f8SWilliam Tu }
667fc1372f8SWilliam Tu 
ip_tun_from_nlattr(const struct nlattr * attr,struct sw_flow_match * match,bool is_mask,bool log)6686b26ba3aSJiri Benc static int ip_tun_from_nlattr(const struct nlattr *attr,
66905da5898SJarno Rajahalme 			      struct sw_flow_match *match, bool is_mask,
67005da5898SJarno Rajahalme 			      bool log)
671e6445719SPravin B Shelar {
67299e28f18SPravin B Shelar 	bool ttl = false, ipv4 = false, ipv6 = false;
67318b6f717Swenxu 	bool info_bridge_mode = false;
67499e28f18SPravin B Shelar 	__be16 tun_flags = 0;
67599e28f18SPravin B Shelar 	int opts_type = 0;
676e6445719SPravin B Shelar 	struct nlattr *a;
677e6445719SPravin B Shelar 	int rem;
678e6445719SPravin B Shelar 
679e6445719SPravin B Shelar 	nla_for_each_nested(a, attr, rem) {
680e6445719SPravin B Shelar 		int type = nla_type(a);
68105da5898SJarno Rajahalme 		int err;
68205da5898SJarno Rajahalme 
683e6445719SPravin B Shelar 		if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
68405da5898SJarno Rajahalme 			OVS_NLERR(log, "Tunnel attr %d out of range max %d",
685e6445719SPravin B Shelar 				  type, OVS_TUNNEL_KEY_ATTR_MAX);
686e6445719SPravin B Shelar 			return -EINVAL;
687e6445719SPravin B Shelar 		}
688e6445719SPravin B Shelar 
689982b5270SJesse Gross 		if (!check_attr_len(nla_len(a),
690982b5270SJesse Gross 				    ovs_tunnel_key_lens[type].len)) {
69105da5898SJarno Rajahalme 			OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
69281bfe3c3SThomas Graf 				  type, nla_len(a), ovs_tunnel_key_lens[type].len);
693e6445719SPravin B Shelar 			return -EINVAL;
694e6445719SPravin B Shelar 		}
695e6445719SPravin B Shelar 
696e6445719SPravin B Shelar 		switch (type) {
697e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_ID:
698e6445719SPravin B Shelar 			SW_FLOW_KEY_PUT(match, tun_key.tun_id,
699e6445719SPravin B Shelar 					nla_get_be64(a), is_mask);
700e6445719SPravin B Shelar 			tun_flags |= TUNNEL_KEY;
701e6445719SPravin B Shelar 			break;
702e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
703c1ea5d67SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src,
70467b61f6cSJiri Benc 					nla_get_in_addr(a), is_mask);
7056b26ba3aSJiri Benc 			ipv4 = true;
706e6445719SPravin B Shelar 			break;
707e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
708c1ea5d67SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst,
70967b61f6cSJiri Benc 					nla_get_in_addr(a), is_mask);
7106b26ba3aSJiri Benc 			ipv4 = true;
7116b26ba3aSJiri Benc 			break;
7126b26ba3aSJiri Benc 		case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
7133d20f1f7SOr Gerlitz 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.src,
7146b26ba3aSJiri Benc 					nla_get_in6_addr(a), is_mask);
7156b26ba3aSJiri Benc 			ipv6 = true;
7166b26ba3aSJiri Benc 			break;
7176b26ba3aSJiri Benc 		case OVS_TUNNEL_KEY_ATTR_IPV6_DST:
7186b26ba3aSJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
7196b26ba3aSJiri Benc 					nla_get_in6_addr(a), is_mask);
7206b26ba3aSJiri Benc 			ipv6 = true;
721e6445719SPravin B Shelar 			break;
722e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_TOS:
7237c383fb2SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.tos,
724e6445719SPravin B Shelar 					nla_get_u8(a), is_mask);
725e6445719SPravin B Shelar 			break;
726e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_TTL:
7277c383fb2SJiri Benc 			SW_FLOW_KEY_PUT(match, tun_key.ttl,
728e6445719SPravin B Shelar 					nla_get_u8(a), is_mask);
729e6445719SPravin B Shelar 			ttl = true;
730e6445719SPravin B Shelar 			break;
731e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
732e6445719SPravin B Shelar 			tun_flags |= TUNNEL_DONT_FRAGMENT;
733e6445719SPravin B Shelar 			break;
734e6445719SPravin B Shelar 		case OVS_TUNNEL_KEY_ATTR_CSUM:
735e6445719SPravin B Shelar 			tun_flags |= TUNNEL_CSUM;
736e6445719SPravin B Shelar 			break;
7378f0aad6fSWenyu Zhang 		case OVS_TUNNEL_KEY_ATTR_TP_SRC:
7388f0aad6fSWenyu Zhang 			SW_FLOW_KEY_PUT(match, tun_key.tp_src,
7398f0aad6fSWenyu Zhang 					nla_get_be16(a), is_mask);
7408f0aad6fSWenyu Zhang 			break;
7418f0aad6fSWenyu Zhang 		case OVS_TUNNEL_KEY_ATTR_TP_DST:
7428f0aad6fSWenyu Zhang 			SW_FLOW_KEY_PUT(match, tun_key.tp_dst,
7438f0aad6fSWenyu Zhang 					nla_get_be16(a), is_mask);
7448f0aad6fSWenyu Zhang 			break;
74567fa0341SJesse Gross 		case OVS_TUNNEL_KEY_ATTR_OAM:
74667fa0341SJesse Gross 			tun_flags |= TUNNEL_OAM;
74767fa0341SJesse Gross 			break;
748f5796684SJesse Gross 		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
7491dd144cfSThomas Graf 			if (opts_type) {
7501dd144cfSThomas Graf 				OVS_NLERR(log, "Multiple metadata blocks provided");
7511dd144cfSThomas Graf 				return -EINVAL;
7521dd144cfSThomas Graf 			}
7531dd144cfSThomas Graf 
75405da5898SJarno Rajahalme 			err = genev_tun_opt_from_nlattr(a, match, is_mask, log);
75505da5898SJarno Rajahalme 			if (err)
75605da5898SJarno Rajahalme 				return err;
75705da5898SJarno Rajahalme 
7581dd144cfSThomas Graf 			tun_flags |= TUNNEL_GENEVE_OPT;
7591dd144cfSThomas Graf 			opts_type = type;
7601dd144cfSThomas Graf 			break;
7611dd144cfSThomas Graf 		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
7621dd144cfSThomas Graf 			if (opts_type) {
7631dd144cfSThomas Graf 				OVS_NLERR(log, "Multiple metadata blocks provided");
7641dd144cfSThomas Graf 				return -EINVAL;
7651dd144cfSThomas Graf 			}
7661dd144cfSThomas Graf 
7671dd144cfSThomas Graf 			err = vxlan_tun_opt_from_nlattr(a, match, is_mask, log);
7681dd144cfSThomas Graf 			if (err)
7691dd144cfSThomas Graf 				return err;
7701dd144cfSThomas Graf 
7711dd144cfSThomas Graf 			tun_flags |= TUNNEL_VXLAN_OPT;
7721dd144cfSThomas Graf 			opts_type = type;
773f5796684SJesse Gross 			break;
7748f3dbfd7SKris Murphy 		case OVS_TUNNEL_KEY_ATTR_PAD:
7758f3dbfd7SKris Murphy 			break;
776fc1372f8SWilliam Tu 		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
777fc1372f8SWilliam Tu 			if (opts_type) {
778fc1372f8SWilliam Tu 				OVS_NLERR(log, "Multiple metadata blocks provided");
779fc1372f8SWilliam Tu 				return -EINVAL;
780fc1372f8SWilliam Tu 			}
781fc1372f8SWilliam Tu 
782fc1372f8SWilliam Tu 			err = erspan_tun_opt_from_nlattr(a, match, is_mask,
783fc1372f8SWilliam Tu 							 log);
784fc1372f8SWilliam Tu 			if (err)
785fc1372f8SWilliam Tu 				return err;
786fc1372f8SWilliam Tu 
787fc1372f8SWilliam Tu 			tun_flags |= TUNNEL_ERSPAN_OPT;
788fc1372f8SWilliam Tu 			opts_type = type;
789fc1372f8SWilliam Tu 			break;
79018b6f717Swenxu 		case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE:
79118b6f717Swenxu 			info_bridge_mode = true;
79218b6f717Swenxu 			ipv4 = true;
79318b6f717Swenxu 			break;
794e6445719SPravin B Shelar 		default:
7956b26ba3aSJiri Benc 			OVS_NLERR(log, "Unknown IP tunnel attribute %d",
796f5796684SJesse Gross 				  type);
797e6445719SPravin B Shelar 			return -EINVAL;
798e6445719SPravin B Shelar 		}
799e6445719SPravin B Shelar 	}
800e6445719SPravin B Shelar 
801e6445719SPravin B Shelar 	SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
80200a93babSJiri Benc 	if (is_mask)
80300a93babSJiri Benc 		SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true);
80400a93babSJiri Benc 	else
8056b26ba3aSJiri Benc 		SW_FLOW_KEY_PUT(match, tun_proto, ipv6 ? AF_INET6 : AF_INET,
8066b26ba3aSJiri Benc 				false);
807e6445719SPravin B Shelar 
808e6445719SPravin B Shelar 	if (rem > 0) {
8096b26ba3aSJiri Benc 		OVS_NLERR(log, "IP tunnel attribute has %d unknown bytes.",
81005da5898SJarno Rajahalme 			  rem);
811e6445719SPravin B Shelar 		return -EINVAL;
812e6445719SPravin B Shelar 	}
813e6445719SPravin B Shelar 
8146b26ba3aSJiri Benc 	if (ipv4 && ipv6) {
8156b26ba3aSJiri Benc 		OVS_NLERR(log, "Mixed IPv4 and IPv6 tunnel attributes");
8166b26ba3aSJiri Benc 		return -EINVAL;
8176b26ba3aSJiri Benc 	}
8186b26ba3aSJiri Benc 
819e6445719SPravin B Shelar 	if (!is_mask) {
8206b26ba3aSJiri Benc 		if (!ipv4 && !ipv6) {
8216b26ba3aSJiri Benc 			OVS_NLERR(log, "IP tunnel dst address not specified");
8226b26ba3aSJiri Benc 			return -EINVAL;
8236b26ba3aSJiri Benc 		}
82418b6f717Swenxu 		if (ipv4) {
82518b6f717Swenxu 			if (info_bridge_mode) {
82618b6f717Swenxu 				if (match->key->tun_key.u.ipv4.src ||
82718b6f717Swenxu 				    match->key->tun_key.u.ipv4.dst ||
82818b6f717Swenxu 				    match->key->tun_key.tp_src ||
82918b6f717Swenxu 				    match->key->tun_key.tp_dst ||
83018b6f717Swenxu 				    match->key->tun_key.ttl ||
83118b6f717Swenxu 				    match->key->tun_key.tos ||
83218b6f717Swenxu 				    tun_flags & ~TUNNEL_KEY) {
83318b6f717Swenxu 					OVS_NLERR(log, "IPv4 tun info is not correct");
83418b6f717Swenxu 					return -EINVAL;
83518b6f717Swenxu 				}
83618b6f717Swenxu 			} else if (!match->key->tun_key.u.ipv4.dst) {
83705da5898SJarno Rajahalme 				OVS_NLERR(log, "IPv4 tunnel dst address is zero");
838e6445719SPravin B Shelar 				return -EINVAL;
839e6445719SPravin B Shelar 			}
84018b6f717Swenxu 		}
8416b26ba3aSJiri Benc 		if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) {
8426b26ba3aSJiri Benc 			OVS_NLERR(log, "IPv6 tunnel dst address is zero");
8436b26ba3aSJiri Benc 			return -EINVAL;
8446b26ba3aSJiri Benc 		}
845e6445719SPravin B Shelar 
84618b6f717Swenxu 		if (!ttl && !info_bridge_mode) {
8476b26ba3aSJiri Benc 			OVS_NLERR(log, "IP tunnel TTL not specified.");
848e6445719SPravin B Shelar 			return -EINVAL;
849e6445719SPravin B Shelar 		}
850e6445719SPravin B Shelar 	}
851e6445719SPravin B Shelar 
8521dd144cfSThomas Graf 	return opts_type;
8531dd144cfSThomas Graf }
8541dd144cfSThomas Graf 
vxlan_opt_to_nlattr(struct sk_buff * skb,const void * tun_opts,int swkey_tun_opts_len)8551dd144cfSThomas Graf static int vxlan_opt_to_nlattr(struct sk_buff *skb,
8561dd144cfSThomas Graf 			       const void *tun_opts, int swkey_tun_opts_len)
8571dd144cfSThomas Graf {
858614732eaSThomas Graf 	const struct vxlan_metadata *opts = tun_opts;
8591dd144cfSThomas Graf 	struct nlattr *nla;
8601dd144cfSThomas Graf 
861ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
8621dd144cfSThomas Graf 	if (!nla)
8631dd144cfSThomas Graf 		return -EMSGSIZE;
8641dd144cfSThomas Graf 
8651dd144cfSThomas Graf 	if (nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
8661dd144cfSThomas Graf 		return -EMSGSIZE;
8671dd144cfSThomas Graf 
8681dd144cfSThomas Graf 	nla_nest_end(skb, nla);
869e6445719SPravin B Shelar 	return 0;
870e6445719SPravin B Shelar }
871e6445719SPravin 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)8726b26ba3aSJiri Benc static int __ip_tun_to_nlattr(struct sk_buff *skb,
8731d8fff90SThomas Graf 			      const struct ip_tunnel_key *output,
8746b26ba3aSJiri Benc 			      const void *tun_opts, int swkey_tun_opts_len,
87518b6f717Swenxu 			      unsigned short tun_proto, u8 mode)
876e6445719SPravin B Shelar {
877e6445719SPravin B Shelar 	if (output->tun_flags & TUNNEL_KEY &&
878b46f6dedSNicolas Dichtel 	    nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id,
879b46f6dedSNicolas Dichtel 			 OVS_TUNNEL_KEY_ATTR_PAD))
880e6445719SPravin B Shelar 		return -EMSGSIZE;
88118b6f717Swenxu 
88218b6f717Swenxu 	if (mode & IP_TUNNEL_INFO_BRIDGE)
88318b6f717Swenxu 		return nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE)
88418b6f717Swenxu 		       ? -EMSGSIZE : 0;
88518b6f717Swenxu 
8866b26ba3aSJiri Benc 	switch (tun_proto) {
8876b26ba3aSJiri Benc 	case AF_INET:
888c1ea5d67SJiri Benc 		if (output->u.ipv4.src &&
889930345eaSJiri Benc 		    nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
890c1ea5d67SJiri Benc 				    output->u.ipv4.src))
891e6445719SPravin B Shelar 			return -EMSGSIZE;
892c1ea5d67SJiri Benc 		if (output->u.ipv4.dst &&
893930345eaSJiri Benc 		    nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
894c1ea5d67SJiri Benc 				    output->u.ipv4.dst))
895e6445719SPravin B Shelar 			return -EMSGSIZE;
8966b26ba3aSJiri Benc 		break;
8976b26ba3aSJiri Benc 	case AF_INET6:
8986b26ba3aSJiri Benc 		if (!ipv6_addr_any(&output->u.ipv6.src) &&
8996b26ba3aSJiri Benc 		    nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,
9006b26ba3aSJiri Benc 				     &output->u.ipv6.src))
9016b26ba3aSJiri Benc 			return -EMSGSIZE;
9026b26ba3aSJiri Benc 		if (!ipv6_addr_any(&output->u.ipv6.dst) &&
9036b26ba3aSJiri Benc 		    nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_DST,
9046b26ba3aSJiri Benc 				     &output->u.ipv6.dst))
9056b26ba3aSJiri Benc 			return -EMSGSIZE;
9066b26ba3aSJiri Benc 		break;
9076b26ba3aSJiri Benc 	}
9087c383fb2SJiri Benc 	if (output->tos &&
9097c383fb2SJiri Benc 	    nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos))
910e6445719SPravin B Shelar 		return -EMSGSIZE;
9117c383fb2SJiri Benc 	if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, output->ttl))
912e6445719SPravin B Shelar 		return -EMSGSIZE;
913e6445719SPravin B Shelar 	if ((output->tun_flags & TUNNEL_DONT_FRAGMENT) &&
914e6445719SPravin B Shelar 	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
915e6445719SPravin B Shelar 		return -EMSGSIZE;
916e6445719SPravin B Shelar 	if ((output->tun_flags & TUNNEL_CSUM) &&
917e6445719SPravin B Shelar 	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
918e6445719SPravin B Shelar 		return -EMSGSIZE;
9198f0aad6fSWenyu Zhang 	if (output->tp_src &&
9208f0aad6fSWenyu Zhang 	    nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
9218f0aad6fSWenyu Zhang 		return -EMSGSIZE;
9228f0aad6fSWenyu Zhang 	if (output->tp_dst &&
9238f0aad6fSWenyu Zhang 	    nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
9248f0aad6fSWenyu Zhang 		return -EMSGSIZE;
92567fa0341SJesse Gross 	if ((output->tun_flags & TUNNEL_OAM) &&
92667fa0341SJesse Gross 	    nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
92767fa0341SJesse Gross 		return -EMSGSIZE;
928fc4099f1SPravin B Shelar 	if (swkey_tun_opts_len) {
9291dd144cfSThomas Graf 		if (output->tun_flags & TUNNEL_GENEVE_OPT &&
930f5796684SJesse Gross 		    nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
931f5796684SJesse Gross 			    swkey_tun_opts_len, tun_opts))
932f5796684SJesse Gross 			return -EMSGSIZE;
9331dd144cfSThomas Graf 		else if (output->tun_flags & TUNNEL_VXLAN_OPT &&
9341dd144cfSThomas Graf 			 vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len))
9351dd144cfSThomas Graf 			return -EMSGSIZE;
936fc1372f8SWilliam Tu 		else if (output->tun_flags & TUNNEL_ERSPAN_OPT &&
937fc1372f8SWilliam Tu 			 nla_put(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
938fc1372f8SWilliam Tu 				 swkey_tun_opts_len, tun_opts))
939fc1372f8SWilliam Tu 			return -EMSGSIZE;
9401dd144cfSThomas Graf 	}
941f5796684SJesse Gross 
942f5796684SJesse Gross 	return 0;
943f5796684SJesse Gross }
944f5796684SJesse 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)9456b26ba3aSJiri Benc static int ip_tun_to_nlattr(struct sk_buff *skb,
9461d8fff90SThomas Graf 			    const struct ip_tunnel_key *output,
9476b26ba3aSJiri Benc 			    const void *tun_opts, int swkey_tun_opts_len,
94818b6f717Swenxu 			    unsigned short tun_proto, u8 mode)
949f5796684SJesse Gross {
950f5796684SJesse Gross 	struct nlattr *nla;
951f5796684SJesse Gross 	int err;
952f5796684SJesse Gross 
953ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_KEY_ATTR_TUNNEL);
954f5796684SJesse Gross 	if (!nla)
955f5796684SJesse Gross 		return -EMSGSIZE;
956f5796684SJesse Gross 
9576b26ba3aSJiri Benc 	err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len,
95818b6f717Swenxu 				 tun_proto, mode);
959f5796684SJesse Gross 	if (err)
960f5796684SJesse Gross 		return err;
961e6445719SPravin B Shelar 
962e6445719SPravin B Shelar 	nla_nest_end(skb, nla);
963e6445719SPravin B Shelar 	return 0;
964e6445719SPravin B Shelar }
965e6445719SPravin B Shelar 
ovs_nla_put_tunnel_info(struct sk_buff * skb,struct ip_tunnel_info * tun_info)966fc4099f1SPravin B Shelar int ovs_nla_put_tunnel_info(struct sk_buff *skb,
967fc4099f1SPravin B Shelar 			    struct ip_tunnel_info *tun_info)
9688f0aad6fSWenyu Zhang {
969ba3e2084SDavid S. Miller 	return __ip_tun_to_nlattr(skb, &tun_info->key,
970fc4099f1SPravin B Shelar 				  ip_tunnel_info_opts(tun_info),
971ba3e2084SDavid S. Miller 				  tun_info->options_len,
97218b6f717Swenxu 				  ip_tunnel_info_af(tun_info), tun_info->mode);
9738f0aad6fSWenyu Zhang }
9748f0aad6fSWenyu Zhang 
encode_vlan_from_nlattrs(struct sw_flow_match * match,const struct nlattr * a[],bool is_mask,bool inner)975018c1ddaSEric Garver static int encode_vlan_from_nlattrs(struct sw_flow_match *match,
976018c1ddaSEric Garver 				    const struct nlattr *a[],
977018c1ddaSEric Garver 				    bool is_mask, bool inner)
978018c1ddaSEric Garver {
979018c1ddaSEric Garver 	__be16 tci = 0;
980018c1ddaSEric Garver 	__be16 tpid = 0;
981018c1ddaSEric Garver 
982018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_VLAN])
983018c1ddaSEric Garver 		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
984018c1ddaSEric Garver 
985018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_ETHERTYPE])
986018c1ddaSEric Garver 		tpid = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
987018c1ddaSEric Garver 
988018c1ddaSEric Garver 	if (likely(!inner)) {
989018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.vlan.tpid, tpid, is_mask);
990018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.vlan.tci, tci, is_mask);
991018c1ddaSEric Garver 	} else {
992018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.cvlan.tpid, tpid, is_mask);
993018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.cvlan.tci, tci, is_mask);
994018c1ddaSEric Garver 	}
995018c1ddaSEric Garver 	return 0;
996018c1ddaSEric Garver }
997018c1ddaSEric Garver 
validate_vlan_from_nlattrs(const struct sw_flow_match * match,u64 key_attrs,bool inner,const struct nlattr ** a,bool log)998018c1ddaSEric Garver static int validate_vlan_from_nlattrs(const struct sw_flow_match *match,
999018c1ddaSEric Garver 				      u64 key_attrs, bool inner,
1000018c1ddaSEric Garver 				      const struct nlattr **a, bool log)
1001018c1ddaSEric Garver {
1002018c1ddaSEric Garver 	__be16 tci = 0;
1003018c1ddaSEric Garver 
1004018c1ddaSEric Garver 	if (!((key_attrs & (1 << OVS_KEY_ATTR_ETHERNET)) &&
1005018c1ddaSEric Garver 	      (key_attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) &&
1006018c1ddaSEric Garver 	       eth_type_vlan(nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE])))) {
1007018c1ddaSEric Garver 		/* Not a VLAN. */
1008018c1ddaSEric Garver 		return 0;
1009018c1ddaSEric Garver 	}
1010018c1ddaSEric Garver 
1011018c1ddaSEric Garver 	if (!((key_attrs & (1 << OVS_KEY_ATTR_VLAN)) &&
1012018c1ddaSEric Garver 	      (key_attrs & (1 << OVS_KEY_ATTR_ENCAP)))) {
1013018c1ddaSEric Garver 		OVS_NLERR(log, "Invalid %s frame", (inner) ? "C-VLAN" : "VLAN");
1014018c1ddaSEric Garver 		return -EINVAL;
1015018c1ddaSEric Garver 	}
1016018c1ddaSEric Garver 
1017018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_VLAN])
1018018c1ddaSEric Garver 		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
1019018c1ddaSEric Garver 
10209df46aefSMichał Mirosław 	if (!(tci & htons(VLAN_CFI_MASK))) {
1021018c1ddaSEric Garver 		if (tci) {
10229df46aefSMichał Mirosław 			OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit set.",
1023018c1ddaSEric Garver 				  (inner) ? "C-VLAN" : "VLAN");
1024018c1ddaSEric Garver 			return -EINVAL;
1025018c1ddaSEric Garver 		} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
1026018c1ddaSEric Garver 			/* Corner case for truncated VLAN header. */
1027018c1ddaSEric Garver 			OVS_NLERR(log, "Truncated %s header has non-zero encap attribute.",
1028018c1ddaSEric Garver 				  (inner) ? "C-VLAN" : "VLAN");
1029018c1ddaSEric Garver 			return -EINVAL;
1030018c1ddaSEric Garver 		}
1031018c1ddaSEric Garver 	}
1032018c1ddaSEric Garver 
1033018c1ddaSEric Garver 	return 1;
1034018c1ddaSEric Garver }
1035018c1ddaSEric Garver 
validate_vlan_mask_from_nlattrs(const struct sw_flow_match * match,u64 key_attrs,bool inner,const struct nlattr ** a,bool log)1036018c1ddaSEric Garver static int validate_vlan_mask_from_nlattrs(const struct sw_flow_match *match,
1037018c1ddaSEric Garver 					   u64 key_attrs, bool inner,
1038018c1ddaSEric Garver 					   const struct nlattr **a, bool log)
1039018c1ddaSEric Garver {
1040018c1ddaSEric Garver 	__be16 tci = 0;
1041018c1ddaSEric Garver 	__be16 tpid = 0;
1042018c1ddaSEric Garver 	bool encap_valid = !!(match->key->eth.vlan.tci &
10439df46aefSMichał Mirosław 			      htons(VLAN_CFI_MASK));
1044018c1ddaSEric Garver 	bool i_encap_valid = !!(match->key->eth.cvlan.tci &
10459df46aefSMichał Mirosław 				htons(VLAN_CFI_MASK));
1046018c1ddaSEric Garver 
1047018c1ddaSEric Garver 	if (!(key_attrs & (1 << OVS_KEY_ATTR_ENCAP))) {
1048018c1ddaSEric Garver 		/* Not a VLAN. */
1049018c1ddaSEric Garver 		return 0;
1050018c1ddaSEric Garver 	}
1051018c1ddaSEric Garver 
1052018c1ddaSEric Garver 	if ((!inner && !encap_valid) || (inner && !i_encap_valid)) {
1053018c1ddaSEric Garver 		OVS_NLERR(log, "Encap mask attribute is set for non-%s frame.",
1054018c1ddaSEric Garver 			  (inner) ? "C-VLAN" : "VLAN");
1055018c1ddaSEric Garver 		return -EINVAL;
1056018c1ddaSEric Garver 	}
1057018c1ddaSEric Garver 
1058018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_VLAN])
1059018c1ddaSEric Garver 		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
1060018c1ddaSEric Garver 
1061018c1ddaSEric Garver 	if (a[OVS_KEY_ATTR_ETHERTYPE])
1062018c1ddaSEric Garver 		tpid = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
1063018c1ddaSEric Garver 
1064018c1ddaSEric Garver 	if (tpid != htons(0xffff)) {
1065018c1ddaSEric Garver 		OVS_NLERR(log, "Must have an exact match on %s TPID (mask=%x).",
1066018c1ddaSEric Garver 			  (inner) ? "C-VLAN" : "VLAN", ntohs(tpid));
1067018c1ddaSEric Garver 		return -EINVAL;
1068018c1ddaSEric Garver 	}
10699df46aefSMichał Mirosław 	if (!(tci & htons(VLAN_CFI_MASK))) {
10709df46aefSMichał Mirosław 		OVS_NLERR(log, "%s TCI mask does not have exact match for VLAN_CFI_MASK bit.",
1071018c1ddaSEric Garver 			  (inner) ? "C-VLAN" : "VLAN");
1072018c1ddaSEric Garver 		return -EINVAL;
1073018c1ddaSEric Garver 	}
1074018c1ddaSEric Garver 
1075018c1ddaSEric Garver 	return 1;
1076018c1ddaSEric Garver }
1077018c1ddaSEric Garver 
__parse_vlan_from_nlattrs(struct sw_flow_match * match,u64 * key_attrs,bool inner,const struct nlattr ** a,bool is_mask,bool log)1078018c1ddaSEric Garver static int __parse_vlan_from_nlattrs(struct sw_flow_match *match,
1079018c1ddaSEric Garver 				     u64 *key_attrs, bool inner,
1080018c1ddaSEric Garver 				     const struct nlattr **a, bool is_mask,
1081018c1ddaSEric Garver 				     bool log)
1082018c1ddaSEric Garver {
1083018c1ddaSEric Garver 	int err;
1084018c1ddaSEric Garver 	const struct nlattr *encap;
1085018c1ddaSEric Garver 
1086018c1ddaSEric Garver 	if (!is_mask)
1087018c1ddaSEric Garver 		err = validate_vlan_from_nlattrs(match, *key_attrs, inner,
1088018c1ddaSEric Garver 						 a, log);
1089018c1ddaSEric Garver 	else
1090018c1ddaSEric Garver 		err = validate_vlan_mask_from_nlattrs(match, *key_attrs, inner,
1091018c1ddaSEric Garver 						      a, log);
1092018c1ddaSEric Garver 	if (err <= 0)
1093018c1ddaSEric Garver 		return err;
1094018c1ddaSEric Garver 
1095018c1ddaSEric Garver 	err = encode_vlan_from_nlattrs(match, a, is_mask, inner);
1096018c1ddaSEric Garver 	if (err)
1097018c1ddaSEric Garver 		return err;
1098018c1ddaSEric Garver 
1099018c1ddaSEric Garver 	*key_attrs &= ~(1 << OVS_KEY_ATTR_ENCAP);
1100018c1ddaSEric Garver 	*key_attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
1101018c1ddaSEric Garver 	*key_attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
1102018c1ddaSEric Garver 
1103018c1ddaSEric Garver 	encap = a[OVS_KEY_ATTR_ENCAP];
1104018c1ddaSEric Garver 
1105018c1ddaSEric Garver 	if (!is_mask)
1106018c1ddaSEric Garver 		err = parse_flow_nlattrs(encap, a, key_attrs, log);
1107018c1ddaSEric Garver 	else
1108018c1ddaSEric Garver 		err = parse_flow_mask_nlattrs(encap, a, key_attrs, log);
1109018c1ddaSEric Garver 
1110018c1ddaSEric Garver 	return err;
1111018c1ddaSEric Garver }
1112018c1ddaSEric Garver 
parse_vlan_from_nlattrs(struct sw_flow_match * match,u64 * key_attrs,const struct nlattr ** a,bool is_mask,bool log)1113018c1ddaSEric Garver static int parse_vlan_from_nlattrs(struct sw_flow_match *match,
1114018c1ddaSEric Garver 				   u64 *key_attrs, const struct nlattr **a,
1115018c1ddaSEric Garver 				   bool is_mask, bool log)
1116018c1ddaSEric Garver {
1117018c1ddaSEric Garver 	int err;
1118018c1ddaSEric Garver 	bool encap_valid = false;
1119018c1ddaSEric Garver 
1120018c1ddaSEric Garver 	err = __parse_vlan_from_nlattrs(match, key_attrs, false, a,
1121018c1ddaSEric Garver 					is_mask, log);
1122018c1ddaSEric Garver 	if (err)
1123018c1ddaSEric Garver 		return err;
1124018c1ddaSEric Garver 
11259df46aefSMichał Mirosław 	encap_valid = !!(match->key->eth.vlan.tci & htons(VLAN_CFI_MASK));
1126018c1ddaSEric Garver 	if (encap_valid) {
1127018c1ddaSEric Garver 		err = __parse_vlan_from_nlattrs(match, key_attrs, true, a,
1128018c1ddaSEric Garver 						is_mask, log);
1129018c1ddaSEric Garver 		if (err)
1130018c1ddaSEric Garver 			return err;
1131018c1ddaSEric Garver 	}
1132018c1ddaSEric Garver 
1133018c1ddaSEric Garver 	return 0;
1134018c1ddaSEric Garver }
1135018c1ddaSEric Garver 
parse_eth_type_from_nlattrs(struct sw_flow_match * match,u64 * attrs,const struct nlattr ** a,bool is_mask,bool log)11360a6410fbSJiri Benc static int parse_eth_type_from_nlattrs(struct sw_flow_match *match,
11370a6410fbSJiri Benc 				       u64 *attrs, const struct nlattr **a,
11380a6410fbSJiri Benc 				       bool is_mask, bool log)
11390a6410fbSJiri Benc {
11400a6410fbSJiri Benc 	__be16 eth_type;
11410a6410fbSJiri Benc 
11420a6410fbSJiri Benc 	eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
11430a6410fbSJiri Benc 	if (is_mask) {
11440a6410fbSJiri Benc 		/* Always exact match EtherType. */
11450a6410fbSJiri Benc 		eth_type = htons(0xffff);
11460a6410fbSJiri Benc 	} else if (!eth_proto_is_802_3(eth_type)) {
11470a6410fbSJiri Benc 		OVS_NLERR(log, "EtherType %x is less than min %x",
11480a6410fbSJiri Benc 				ntohs(eth_type), ETH_P_802_3_MIN);
11490a6410fbSJiri Benc 		return -EINVAL;
11500a6410fbSJiri Benc 	}
11510a6410fbSJiri Benc 
11520a6410fbSJiri Benc 	SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
11530a6410fbSJiri Benc 	*attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
11540a6410fbSJiri Benc 	return 0;
11550a6410fbSJiri Benc }
11560a6410fbSJiri Benc 
metadata_from_nlattrs(struct net * net,struct sw_flow_match * match,u64 * attrs,const struct nlattr ** a,bool is_mask,bool log)1157c2ac6673SJoe Stringer static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
1158c2ac6673SJoe Stringer 				 u64 *attrs, const struct nlattr **a,
1159c2ac6673SJoe Stringer 				 bool is_mask, bool log)
1160e6445719SPravin B Shelar {
11610a6410fbSJiri Benc 	u8 mac_proto = MAC_PROTO_ETHERNET;
11620a6410fbSJiri Benc 
1163971427f3SAndy Zhou 	if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
1164971427f3SAndy Zhou 		u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
1165971427f3SAndy Zhou 
1166971427f3SAndy Zhou 		SW_FLOW_KEY_PUT(match, ovs_flow_hash, hash_val, is_mask);
1167971427f3SAndy Zhou 		*attrs &= ~(1 << OVS_KEY_ATTR_DP_HASH);
1168971427f3SAndy Zhou 	}
1169971427f3SAndy Zhou 
1170971427f3SAndy Zhou 	if (*attrs & (1 << OVS_KEY_ATTR_RECIRC_ID)) {
1171971427f3SAndy Zhou 		u32 recirc_id = nla_get_u32(a[OVS_KEY_ATTR_RECIRC_ID]);
1172971427f3SAndy Zhou 
1173971427f3SAndy Zhou 		SW_FLOW_KEY_PUT(match, recirc_id, recirc_id, is_mask);
1174971427f3SAndy Zhou 		*attrs &= ~(1 << OVS_KEY_ATTR_RECIRC_ID);
1175971427f3SAndy Zhou 	}
1176971427f3SAndy Zhou 
1177e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
1178e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.priority,
1179e6445719SPravin B Shelar 			  nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask);
1180e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_PRIORITY);
1181e6445719SPravin B Shelar 	}
1182e6445719SPravin B Shelar 
1183e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_IN_PORT)) {
1184e6445719SPravin B Shelar 		u32 in_port = nla_get_u32(a[OVS_KEY_ATTR_IN_PORT]);
1185e6445719SPravin B Shelar 
1186426cda5cSJesse Gross 		if (is_mask) {
1187e6445719SPravin B Shelar 			in_port = 0xffffffff; /* Always exact match in_port. */
1188426cda5cSJesse Gross 		} else if (in_port >= DP_MAX_PORTS) {
118905da5898SJarno Rajahalme 			OVS_NLERR(log, "Port %d exceeds max allowable %d",
1190426cda5cSJesse Gross 				  in_port, DP_MAX_PORTS);
1191e6445719SPravin B Shelar 			return -EINVAL;
1192426cda5cSJesse Gross 		}
1193e6445719SPravin B Shelar 
1194e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.in_port, in_port, is_mask);
1195e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_IN_PORT);
1196e6445719SPravin B Shelar 	} else if (!is_mask) {
1197e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.in_port, DP_MAX_PORTS, is_mask);
1198e6445719SPravin B Shelar 	}
1199e6445719SPravin B Shelar 
1200e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
1201e6445719SPravin B Shelar 		uint32_t mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
1202e6445719SPravin B Shelar 
1203e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, phy.skb_mark, mark, is_mask);
1204e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
1205e6445719SPravin B Shelar 	}
1206e6445719SPravin B Shelar 	if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
12076b26ba3aSJiri Benc 		if (ip_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
12081dd144cfSThomas Graf 				       is_mask, log) < 0)
1209e6445719SPravin B Shelar 			return -EINVAL;
1210e6445719SPravin B Shelar 		*attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
1211e6445719SPravin B Shelar 	}
12127f8a436eSJoe Stringer 
12137f8a436eSJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
1214c2ac6673SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
1215fbccce59SJoe Stringer 		u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
12167f8a436eSJoe Stringer 
12179e384715SJoe Stringer 		if (ct_state & ~CT_SUPPORTED_MASK) {
1218fbccce59SJoe Stringer 			OVS_NLERR(log, "ct_state flags %08x unsupported",
12196f225952SJoe Stringer 				  ct_state);
12206f225952SJoe Stringer 			return -EINVAL;
12216f225952SJoe Stringer 		}
12227f8a436eSJoe Stringer 
1223316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_state, ct_state, is_mask);
12247f8a436eSJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
12257f8a436eSJoe Stringer 	}
12267f8a436eSJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) &&
1227c2ac6673SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_ZONE)) {
12287f8a436eSJoe Stringer 		u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]);
12297f8a436eSJoe Stringer 
1230316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_zone, ct_zone, is_mask);
12317f8a436eSJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE);
12327f8a436eSJoe Stringer 	}
1233182e3042SJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) &&
1234c2ac6673SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_MARK)) {
1235182e3042SJoe Stringer 		u32 mark = nla_get_u32(a[OVS_KEY_ATTR_CT_MARK]);
1236182e3042SJoe Stringer 
1237182e3042SJoe Stringer 		SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
1238182e3042SJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
1239182e3042SJoe Stringer 	}
124033db4125SJoe Stringer 	if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
124133db4125SJoe Stringer 	    ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
124233db4125SJoe Stringer 		const struct ovs_key_ct_labels *cl;
1243c2ac6673SJoe Stringer 
124433db4125SJoe Stringer 		cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
124533db4125SJoe Stringer 		SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
1246c2ac6673SJoe Stringer 				   sizeof(*cl), is_mask);
124733db4125SJoe Stringer 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
1248c2ac6673SJoe Stringer 	}
12499dd7f890SJarno Rajahalme 	if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4)) {
12509dd7f890SJarno Rajahalme 		const struct ovs_key_ct_tuple_ipv4 *ct;
12519dd7f890SJarno Rajahalme 
12529dd7f890SJarno Rajahalme 		ct = nla_data(a[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]);
12539dd7f890SJarno Rajahalme 
12549dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ipv4.ct_orig.src, ct->ipv4_src, is_mask);
12559dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ipv4.ct_orig.dst, ct->ipv4_dst, is_mask);
12569dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
12579dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
1258316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv4_proto, is_mask);
12599dd7f890SJarno Rajahalme 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4);
12609dd7f890SJarno Rajahalme 	}
12619dd7f890SJarno Rajahalme 	if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)) {
12629dd7f890SJarno Rajahalme 		const struct ovs_key_ct_tuple_ipv6 *ct;
12639dd7f890SJarno Rajahalme 
12649dd7f890SJarno Rajahalme 		ct = nla_data(a[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);
12659dd7f890SJarno Rajahalme 
12669dd7f890SJarno Rajahalme 		SW_FLOW_KEY_MEMCPY(match, ipv6.ct_orig.src, &ct->ipv6_src,
12679dd7f890SJarno Rajahalme 				   sizeof(match->key->ipv6.ct_orig.src),
12689dd7f890SJarno Rajahalme 				   is_mask);
12699dd7f890SJarno Rajahalme 		SW_FLOW_KEY_MEMCPY(match, ipv6.ct_orig.dst, &ct->ipv6_dst,
12709dd7f890SJarno Rajahalme 				   sizeof(match->key->ipv6.ct_orig.dst),
12719dd7f890SJarno Rajahalme 				   is_mask);
12729dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
12739dd7f890SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
1274316d4d78SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv6_proto, is_mask);
12759dd7f890SJarno Rajahalme 		*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
12769dd7f890SJarno Rajahalme 	}
1277329f45bcSJiri Benc 
12780a6410fbSJiri Benc 	/* For layer 3 packets the Ethernet type is provided
12790a6410fbSJiri Benc 	 * and treated as metadata but no MAC addresses are provided.
12800a6410fbSJiri Benc 	 */
12810a6410fbSJiri Benc 	if (!(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)) &&
12820a6410fbSJiri Benc 	    (*attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE)))
12830a6410fbSJiri Benc 		mac_proto = MAC_PROTO_NONE;
12840a6410fbSJiri Benc 
1285329f45bcSJiri Benc 	/* Always exact match mac_proto */
12860a6410fbSJiri Benc 	SW_FLOW_KEY_PUT(match, mac_proto, is_mask ? 0xff : mac_proto, is_mask);
12870a6410fbSJiri Benc 
12880a6410fbSJiri Benc 	if (mac_proto == MAC_PROTO_NONE)
12890a6410fbSJiri Benc 		return parse_eth_type_from_nlattrs(match, attrs, a, is_mask,
12900a6410fbSJiri Benc 						   log);
1291329f45bcSJiri Benc 
1292e6445719SPravin B Shelar 	return 0;
1293e6445719SPravin B Shelar }
1294e6445719SPravin B Shelar 
nsh_hdr_from_nlattr(const struct nlattr * attr,struct nshhdr * nh,size_t size)1295b2d0f5d5SYi Yang int nsh_hdr_from_nlattr(const struct nlattr *attr,
1296b2d0f5d5SYi Yang 			struct nshhdr *nh, size_t size)
1297b2d0f5d5SYi Yang {
1298b2d0f5d5SYi Yang 	struct nlattr *a;
1299b2d0f5d5SYi Yang 	int rem;
1300b2d0f5d5SYi Yang 	u8 flags = 0;
1301b2d0f5d5SYi Yang 	u8 ttl = 0;
1302b2d0f5d5SYi Yang 	int mdlen = 0;
1303b2d0f5d5SYi Yang 
1304b2d0f5d5SYi Yang 	/* validate_nsh has check this, so we needn't do duplicate check here
1305b2d0f5d5SYi Yang 	 */
1306b2d0f5d5SYi Yang 	if (size < NSH_BASE_HDR_LEN)
1307b2d0f5d5SYi Yang 		return -ENOBUFS;
1308b2d0f5d5SYi Yang 
1309b2d0f5d5SYi Yang 	nla_for_each_nested(a, attr, rem) {
1310b2d0f5d5SYi Yang 		int type = nla_type(a);
1311b2d0f5d5SYi Yang 
1312b2d0f5d5SYi Yang 		switch (type) {
1313b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_BASE: {
1314b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base = nla_data(a);
1315b2d0f5d5SYi Yang 
1316b2d0f5d5SYi Yang 			flags = base->flags;
1317b2d0f5d5SYi Yang 			ttl = base->ttl;
1318b2d0f5d5SYi Yang 			nh->np = base->np;
1319b2d0f5d5SYi Yang 			nh->mdtype = base->mdtype;
1320b2d0f5d5SYi Yang 			nh->path_hdr = base->path_hdr;
1321b2d0f5d5SYi Yang 			break;
1322b2d0f5d5SYi Yang 		}
1323b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD1:
1324b2d0f5d5SYi Yang 			mdlen = nla_len(a);
1325b2d0f5d5SYi Yang 			if (mdlen > size - NSH_BASE_HDR_LEN)
1326b2d0f5d5SYi Yang 				return -ENOBUFS;
1327b2d0f5d5SYi Yang 			memcpy(&nh->md1, nla_data(a), mdlen);
1328b2d0f5d5SYi Yang 			break;
1329b2d0f5d5SYi Yang 
1330b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD2:
1331b2d0f5d5SYi Yang 			mdlen = nla_len(a);
1332b2d0f5d5SYi Yang 			if (mdlen > size - NSH_BASE_HDR_LEN)
1333b2d0f5d5SYi Yang 				return -ENOBUFS;
1334b2d0f5d5SYi Yang 			memcpy(&nh->md2, nla_data(a), mdlen);
1335b2d0f5d5SYi Yang 			break;
1336b2d0f5d5SYi Yang 
1337b2d0f5d5SYi Yang 		default:
1338b2d0f5d5SYi Yang 			return -EINVAL;
1339b2d0f5d5SYi Yang 		}
1340b2d0f5d5SYi Yang 	}
1341b2d0f5d5SYi Yang 
1342b2d0f5d5SYi Yang 	/* nsh header length  = NSH_BASE_HDR_LEN + mdlen */
1343b2d0f5d5SYi Yang 	nh->ver_flags_ttl_len = 0;
1344b2d0f5d5SYi Yang 	nsh_set_flags_ttl_len(nh, flags, ttl, NSH_BASE_HDR_LEN + mdlen);
1345b2d0f5d5SYi Yang 
1346b2d0f5d5SYi Yang 	return 0;
1347b2d0f5d5SYi Yang }
1348b2d0f5d5SYi Yang 
nsh_key_from_nlattr(const struct nlattr * attr,struct ovs_key_nsh * nsh,struct ovs_key_nsh * nsh_mask)1349b2d0f5d5SYi Yang int nsh_key_from_nlattr(const struct nlattr *attr,
1350b2d0f5d5SYi Yang 			struct ovs_key_nsh *nsh, struct ovs_key_nsh *nsh_mask)
1351b2d0f5d5SYi Yang {
1352b2d0f5d5SYi Yang 	struct nlattr *a;
1353b2d0f5d5SYi Yang 	int rem;
1354b2d0f5d5SYi Yang 
1355b2d0f5d5SYi Yang 	/* validate_nsh has check this, so we needn't do duplicate check here
1356b2d0f5d5SYi Yang 	 */
1357b2d0f5d5SYi Yang 	nla_for_each_nested(a, attr, rem) {
1358b2d0f5d5SYi Yang 		int type = nla_type(a);
1359b2d0f5d5SYi Yang 
1360b2d0f5d5SYi Yang 		switch (type) {
1361b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_BASE: {
1362b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base = nla_data(a);
1363b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base_mask = base + 1;
1364b2d0f5d5SYi Yang 
1365b2d0f5d5SYi Yang 			nsh->base = *base;
1366b2d0f5d5SYi Yang 			nsh_mask->base = *base_mask;
1367b2d0f5d5SYi Yang 			break;
1368b2d0f5d5SYi Yang 		}
1369b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD1: {
1370b2d0f5d5SYi Yang 			const struct ovs_nsh_key_md1 *md1 = nla_data(a);
1371b2d0f5d5SYi Yang 			const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
1372b2d0f5d5SYi Yang 
1373b2d0f5d5SYi Yang 			memcpy(nsh->context, md1->context, sizeof(*md1));
1374b2d0f5d5SYi Yang 			memcpy(nsh_mask->context, md1_mask->context,
1375b2d0f5d5SYi Yang 			       sizeof(*md1_mask));
1376b2d0f5d5SYi Yang 			break;
1377b2d0f5d5SYi Yang 		}
1378b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD2:
1379b2d0f5d5SYi Yang 			/* Not supported yet */
1380b2d0f5d5SYi Yang 			return -ENOTSUPP;
1381b2d0f5d5SYi Yang 		default:
1382b2d0f5d5SYi Yang 			return -EINVAL;
1383b2d0f5d5SYi Yang 		}
1384b2d0f5d5SYi Yang 	}
1385b2d0f5d5SYi Yang 
1386b2d0f5d5SYi Yang 	return 0;
1387b2d0f5d5SYi Yang }
1388b2d0f5d5SYi Yang 
nsh_key_put_from_nlattr(const struct nlattr * attr,struct sw_flow_match * match,bool is_mask,bool is_push_nsh,bool log)1389b2d0f5d5SYi Yang static int nsh_key_put_from_nlattr(const struct nlattr *attr,
1390b2d0f5d5SYi Yang 				   struct sw_flow_match *match, bool is_mask,
1391b2d0f5d5SYi Yang 				   bool is_push_nsh, bool log)
1392b2d0f5d5SYi Yang {
1393b2d0f5d5SYi Yang 	struct nlattr *a;
1394b2d0f5d5SYi Yang 	int rem;
1395b2d0f5d5SYi Yang 	bool has_base = false;
1396b2d0f5d5SYi Yang 	bool has_md1 = false;
1397b2d0f5d5SYi Yang 	bool has_md2 = false;
1398b2d0f5d5SYi Yang 	u8 mdtype = 0;
1399b2d0f5d5SYi Yang 	int mdlen = 0;
1400b2d0f5d5SYi Yang 
1401b2d0f5d5SYi Yang 	if (WARN_ON(is_push_nsh && is_mask))
1402b2d0f5d5SYi Yang 		return -EINVAL;
1403b2d0f5d5SYi Yang 
1404b2d0f5d5SYi Yang 	nla_for_each_nested(a, attr, rem) {
1405b2d0f5d5SYi Yang 		int type = nla_type(a);
1406b2d0f5d5SYi Yang 		int i;
1407b2d0f5d5SYi Yang 
1408b2d0f5d5SYi Yang 		if (type > OVS_NSH_KEY_ATTR_MAX) {
1409b2d0f5d5SYi Yang 			OVS_NLERR(log, "nsh attr %d is out of range max %d",
1410b2d0f5d5SYi Yang 				  type, OVS_NSH_KEY_ATTR_MAX);
1411b2d0f5d5SYi Yang 			return -EINVAL;
1412b2d0f5d5SYi Yang 		}
1413b2d0f5d5SYi Yang 
1414b2d0f5d5SYi Yang 		if (!check_attr_len(nla_len(a),
1415b2d0f5d5SYi Yang 				    ovs_nsh_key_attr_lens[type].len)) {
1416b2d0f5d5SYi Yang 			OVS_NLERR(
1417b2d0f5d5SYi Yang 			    log,
1418b2d0f5d5SYi Yang 			    "nsh attr %d has unexpected len %d expected %d",
1419b2d0f5d5SYi Yang 			    type,
1420b2d0f5d5SYi Yang 			    nla_len(a),
1421b2d0f5d5SYi Yang 			    ovs_nsh_key_attr_lens[type].len
1422b2d0f5d5SYi Yang 			);
1423b2d0f5d5SYi Yang 			return -EINVAL;
1424b2d0f5d5SYi Yang 		}
1425b2d0f5d5SYi Yang 
1426b2d0f5d5SYi Yang 		switch (type) {
1427b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_BASE: {
1428b2d0f5d5SYi Yang 			const struct ovs_nsh_key_base *base = nla_data(a);
1429b2d0f5d5SYi Yang 
1430b2d0f5d5SYi Yang 			has_base = true;
1431b2d0f5d5SYi Yang 			mdtype = base->mdtype;
1432b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.flags,
1433b2d0f5d5SYi Yang 					base->flags, is_mask);
1434b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.ttl,
1435b2d0f5d5SYi Yang 					base->ttl, is_mask);
1436b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.mdtype,
1437b2d0f5d5SYi Yang 					base->mdtype, is_mask);
1438b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.np,
1439b2d0f5d5SYi Yang 					base->np, is_mask);
1440b2d0f5d5SYi Yang 			SW_FLOW_KEY_PUT(match, nsh.base.path_hdr,
1441b2d0f5d5SYi Yang 					base->path_hdr, is_mask);
1442b2d0f5d5SYi Yang 			break;
1443b2d0f5d5SYi Yang 		}
1444b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD1: {
1445b2d0f5d5SYi Yang 			const struct ovs_nsh_key_md1 *md1 = nla_data(a);
1446b2d0f5d5SYi Yang 
1447b2d0f5d5SYi Yang 			has_md1 = true;
1448b2d0f5d5SYi Yang 			for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)
1449b2d0f5d5SYi Yang 				SW_FLOW_KEY_PUT(match, nsh.context[i],
1450b2d0f5d5SYi Yang 						md1->context[i], is_mask);
1451b2d0f5d5SYi Yang 			break;
1452b2d0f5d5SYi Yang 		}
1453b2d0f5d5SYi Yang 		case OVS_NSH_KEY_ATTR_MD2:
1454b2d0f5d5SYi Yang 			if (!is_push_nsh) /* Not supported MD type 2 yet */
1455b2d0f5d5SYi Yang 				return -ENOTSUPP;
1456b2d0f5d5SYi Yang 
1457b2d0f5d5SYi Yang 			has_md2 = true;
1458b2d0f5d5SYi Yang 			mdlen = nla_len(a);
1459b2d0f5d5SYi Yang 			if (mdlen > NSH_CTX_HDRS_MAX_LEN || mdlen <= 0) {
1460b2d0f5d5SYi Yang 				OVS_NLERR(
1461b2d0f5d5SYi Yang 				    log,
1462b2d0f5d5SYi Yang 				    "Invalid MD length %d for MD type %d",
1463b2d0f5d5SYi Yang 				    mdlen,
1464b2d0f5d5SYi Yang 				    mdtype
1465b2d0f5d5SYi Yang 				);
1466b2d0f5d5SYi Yang 				return -EINVAL;
1467b2d0f5d5SYi Yang 			}
1468b2d0f5d5SYi Yang 			break;
1469b2d0f5d5SYi Yang 		default:
1470b2d0f5d5SYi Yang 			OVS_NLERR(log, "Unknown nsh attribute %d",
1471b2d0f5d5SYi Yang 				  type);
1472b2d0f5d5SYi Yang 			return -EINVAL;
1473b2d0f5d5SYi Yang 		}
1474b2d0f5d5SYi Yang 	}
1475b2d0f5d5SYi Yang 
1476b2d0f5d5SYi Yang 	if (rem > 0) {
1477b2d0f5d5SYi Yang 		OVS_NLERR(log, "nsh attribute has %d unknown bytes.", rem);
1478b2d0f5d5SYi Yang 		return -EINVAL;
1479b2d0f5d5SYi Yang 	}
1480b2d0f5d5SYi Yang 
1481b2d0f5d5SYi Yang 	if (has_md1 && has_md2) {
1482b2d0f5d5SYi Yang 		OVS_NLERR(
1483b2d0f5d5SYi Yang 		    1,
1484b2d0f5d5SYi Yang 		    "invalid nsh attribute: md1 and md2 are exclusive."
1485b2d0f5d5SYi Yang 		);
1486b2d0f5d5SYi Yang 		return -EINVAL;
1487b2d0f5d5SYi Yang 	}
1488b2d0f5d5SYi Yang 
1489b2d0f5d5SYi Yang 	if (!is_mask) {
1490b2d0f5d5SYi Yang 		if ((has_md1 && mdtype != NSH_M_TYPE1) ||
1491b2d0f5d5SYi Yang 		    (has_md2 && mdtype != NSH_M_TYPE2)) {
1492b2d0f5d5SYi Yang 			OVS_NLERR(1, "nsh attribute has unmatched MD type %d.",
1493b2d0f5d5SYi Yang 				  mdtype);
1494b2d0f5d5SYi Yang 			return -EINVAL;
1495b2d0f5d5SYi Yang 		}
1496b2d0f5d5SYi Yang 
1497b2d0f5d5SYi Yang 		if (is_push_nsh &&
1498b2d0f5d5SYi Yang 		    (!has_base || (!has_md1 && !has_md2))) {
1499b2d0f5d5SYi Yang 			OVS_NLERR(
1500b2d0f5d5SYi Yang 			    1,
1501b2d0f5d5SYi Yang 			    "push_nsh: missing base or metadata attributes"
1502b2d0f5d5SYi Yang 			);
1503b2d0f5d5SYi Yang 			return -EINVAL;
1504b2d0f5d5SYi Yang 		}
1505b2d0f5d5SYi Yang 	}
1506b2d0f5d5SYi Yang 
1507b2d0f5d5SYi Yang 	return 0;
1508b2d0f5d5SYi Yang }
1509b2d0f5d5SYi Yang 
ovs_key_from_nlattrs(struct net * net,struct sw_flow_match * match,u64 attrs,const struct nlattr ** a,bool is_mask,bool log)1510c2ac6673SJoe Stringer static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
1511c2ac6673SJoe Stringer 				u64 attrs, const struct nlattr **a,
1512c2ac6673SJoe Stringer 				bool is_mask, bool log)
1513e6445719SPravin B Shelar {
1514e6445719SPravin B Shelar 	int err;
1515e6445719SPravin B Shelar 
1516c2ac6673SJoe Stringer 	err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log);
1517e6445719SPravin B Shelar 	if (err)
1518e6445719SPravin B Shelar 		return err;
1519e6445719SPravin B Shelar 
1520e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ETHERNET)) {
1521e6445719SPravin B Shelar 		const struct ovs_key_ethernet *eth_key;
1522e6445719SPravin B Shelar 
1523e6445719SPravin B Shelar 		eth_key = nla_data(a[OVS_KEY_ATTR_ETHERNET]);
1524e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, eth.src,
1525e6445719SPravin B Shelar 				eth_key->eth_src, ETH_ALEN, is_mask);
1526e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, eth.dst,
1527e6445719SPravin B Shelar 				eth_key->eth_dst, ETH_ALEN, is_mask);
1528e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
1529e6445719SPravin B Shelar 
1530e6445719SPravin B Shelar 		if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
1531018c1ddaSEric Garver 			/* VLAN attribute is always parsed before getting here since it
1532018c1ddaSEric Garver 			 * may occur multiple times.
1533018c1ddaSEric Garver 			 */
1534018c1ddaSEric Garver 			OVS_NLERR(log, "VLAN attribute unexpected.");
1535e6445719SPravin B Shelar 			return -EINVAL;
1536e6445719SPravin B Shelar 		}
1537e6445719SPravin B Shelar 
1538e6445719SPravin B Shelar 		if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
15390a6410fbSJiri Benc 			err = parse_eth_type_from_nlattrs(match, &attrs, a, is_mask,
15400a6410fbSJiri Benc 							  log);
15410a6410fbSJiri Benc 			if (err)
15420a6410fbSJiri Benc 				return err;
1543e6445719SPravin B Shelar 		} else if (!is_mask) {
1544e6445719SPravin B Shelar 			SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
1545e6445719SPravin B Shelar 		}
15460a6410fbSJiri Benc 	} else if (!match->key->eth.type) {
15470a6410fbSJiri Benc 		OVS_NLERR(log, "Either Ethernet header or EtherType is required.");
15480a6410fbSJiri Benc 		return -EINVAL;
15490a6410fbSJiri Benc 	}
1550e6445719SPravin B Shelar 
1551e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
1552e6445719SPravin B Shelar 		const struct ovs_key_ipv4 *ipv4_key;
1553e6445719SPravin B Shelar 
1554e6445719SPravin B Shelar 		ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
1555e6445719SPravin B Shelar 		if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
155605da5898SJarno Rajahalme 			OVS_NLERR(log, "IPv4 frag type %d is out of range max %d",
1557e6445719SPravin B Shelar 				  ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
1558e6445719SPravin B Shelar 			return -EINVAL;
1559e6445719SPravin B Shelar 		}
1560e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.proto,
1561e6445719SPravin B Shelar 				ipv4_key->ipv4_proto, is_mask);
1562e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.tos,
1563e6445719SPravin B Shelar 				ipv4_key->ipv4_tos, is_mask);
1564e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.ttl,
1565e6445719SPravin B Shelar 				ipv4_key->ipv4_ttl, is_mask);
1566e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.frag,
1567e6445719SPravin B Shelar 				ipv4_key->ipv4_frag, is_mask);
1568e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
1569e6445719SPravin B Shelar 				ipv4_key->ipv4_src, is_mask);
1570e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
1571e6445719SPravin B Shelar 				ipv4_key->ipv4_dst, is_mask);
1572e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
1573e6445719SPravin B Shelar 	}
1574e6445719SPravin B Shelar 
1575e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
1576e6445719SPravin B Shelar 		const struct ovs_key_ipv6 *ipv6_key;
1577e6445719SPravin B Shelar 
1578e6445719SPravin B Shelar 		ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
1579e6445719SPravin B Shelar 		if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
158005da5898SJarno Rajahalme 			OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
1581e6445719SPravin B Shelar 				  ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
1582e6445719SPravin B Shelar 			return -EINVAL;
1583e6445719SPravin B Shelar 		}
1584fecaef85SJarno Rajahalme 
1585d3052bb5SJoe Stringer 		if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
15860ed80da5SJoe Perches 			OVS_NLERR(log, "IPv6 flow label %x is out of range (max=%x)",
1587fecaef85SJarno Rajahalme 				  ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
1588fecaef85SJarno Rajahalme 			return -EINVAL;
1589fecaef85SJarno Rajahalme 		}
1590fecaef85SJarno Rajahalme 
1591e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv6.label,
1592e6445719SPravin B Shelar 				ipv6_key->ipv6_label, is_mask);
1593e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.proto,
1594e6445719SPravin B Shelar 				ipv6_key->ipv6_proto, is_mask);
1595e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.tos,
1596e6445719SPravin B Shelar 				ipv6_key->ipv6_tclass, is_mask);
1597e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.ttl,
1598e6445719SPravin B Shelar 				ipv6_key->ipv6_hlimit, is_mask);
1599e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.frag,
1600e6445719SPravin B Shelar 				ipv6_key->ipv6_frag, is_mask);
1601e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.src,
1602e6445719SPravin B Shelar 				ipv6_key->ipv6_src,
1603e6445719SPravin B Shelar 				sizeof(match->key->ipv6.addr.src),
1604e6445719SPravin B Shelar 				is_mask);
1605e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.dst,
1606e6445719SPravin B Shelar 				ipv6_key->ipv6_dst,
1607e6445719SPravin B Shelar 				sizeof(match->key->ipv6.addr.dst),
1608e6445719SPravin B Shelar 				is_mask);
1609e6445719SPravin B Shelar 
1610e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
1611e6445719SPravin B Shelar 	}
1612e6445719SPravin B Shelar 
161328a3f060SToms Atteka 	if (attrs & (1ULL << OVS_KEY_ATTR_IPV6_EXTHDRS)) {
161428a3f060SToms Atteka 		const struct ovs_key_ipv6_exthdrs *ipv6_exthdrs_key;
161528a3f060SToms Atteka 
161628a3f060SToms Atteka 		ipv6_exthdrs_key = nla_data(a[OVS_KEY_ATTR_IPV6_EXTHDRS]);
161728a3f060SToms Atteka 
161828a3f060SToms Atteka 		SW_FLOW_KEY_PUT(match, ipv6.exthdrs,
161928a3f060SToms Atteka 				ipv6_exthdrs_key->hdrs, is_mask);
162028a3f060SToms Atteka 
162128a3f060SToms Atteka 		attrs &= ~(1ULL << OVS_KEY_ATTR_IPV6_EXTHDRS);
162228a3f060SToms Atteka 	}
162328a3f060SToms Atteka 
1624e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
1625e6445719SPravin B Shelar 		const struct ovs_key_arp *arp_key;
1626e6445719SPravin B Shelar 
1627e6445719SPravin B Shelar 		arp_key = nla_data(a[OVS_KEY_ATTR_ARP]);
1628e6445719SPravin B Shelar 		if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
162905da5898SJarno Rajahalme 			OVS_NLERR(log, "Unknown ARP opcode (opcode=%d).",
1630e6445719SPravin B Shelar 				  arp_key->arp_op);
1631e6445719SPravin B Shelar 			return -EINVAL;
1632e6445719SPravin B Shelar 		}
1633e6445719SPravin B Shelar 
1634e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
1635e6445719SPravin B Shelar 				arp_key->arp_sip, is_mask);
1636e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
1637e6445719SPravin B Shelar 			arp_key->arp_tip, is_mask);
1638e6445719SPravin B Shelar 		SW_FLOW_KEY_PUT(match, ip.proto,
1639e6445719SPravin B Shelar 				ntohs(arp_key->arp_op), is_mask);
1640e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.sha,
1641e6445719SPravin B Shelar 				arp_key->arp_sha, ETH_ALEN, is_mask);
1642e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.tha,
1643e6445719SPravin B Shelar 				arp_key->arp_tha, ETH_ALEN, is_mask);
1644e6445719SPravin B Shelar 
1645e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ARP);
1646e6445719SPravin B Shelar 	}
1647e6445719SPravin B Shelar 
1648b2d0f5d5SYi Yang 	if (attrs & (1 << OVS_KEY_ATTR_NSH)) {
1649b2d0f5d5SYi Yang 		if (nsh_key_put_from_nlattr(a[OVS_KEY_ATTR_NSH], match,
1650b2d0f5d5SYi Yang 					    is_mask, false, log) < 0)
1651b2d0f5d5SYi Yang 			return -EINVAL;
1652b2d0f5d5SYi Yang 		attrs &= ~(1 << OVS_KEY_ATTR_NSH);
1653b2d0f5d5SYi Yang 	}
1654b2d0f5d5SYi Yang 
165525cd9ba0SSimon Horman 	if (attrs & (1 << OVS_KEY_ATTR_MPLS)) {
165625cd9ba0SSimon Horman 		const struct ovs_key_mpls *mpls_key;
1657fbdcdd78SMartin Varghese 		u32 hdr_len;
1658fbdcdd78SMartin Varghese 		u32 label_count, label_count_mask, i;
165925cd9ba0SSimon Horman 
166025cd9ba0SSimon Horman 		mpls_key = nla_data(a[OVS_KEY_ATTR_MPLS]);
1661fbdcdd78SMartin Varghese 		hdr_len = nla_len(a[OVS_KEY_ATTR_MPLS]);
1662fbdcdd78SMartin Varghese 		label_count = hdr_len / sizeof(struct ovs_key_mpls);
1663fbdcdd78SMartin Varghese 
1664fbdcdd78SMartin Varghese 		if (label_count == 0 || label_count > MPLS_LABEL_DEPTH ||
1665fbdcdd78SMartin Varghese 		    hdr_len % sizeof(struct ovs_key_mpls))
1666fbdcdd78SMartin Varghese 			return -EINVAL;
1667fbdcdd78SMartin Varghese 
1668fbdcdd78SMartin Varghese 		label_count_mask =  GENMASK(label_count - 1, 0);
1669fbdcdd78SMartin Varghese 
1670fbdcdd78SMartin Varghese 		for (i = 0 ; i < label_count; i++)
1671fbdcdd78SMartin Varghese 			SW_FLOW_KEY_PUT(match, mpls.lse[i],
1672fbdcdd78SMartin Varghese 					mpls_key[i].mpls_lse, is_mask);
1673fbdcdd78SMartin Varghese 
1674fbdcdd78SMartin Varghese 		SW_FLOW_KEY_PUT(match, mpls.num_labels_mask,
1675fbdcdd78SMartin Varghese 				label_count_mask, is_mask);
167625cd9ba0SSimon Horman 
167725cd9ba0SSimon Horman 		attrs &= ~(1 << OVS_KEY_ATTR_MPLS);
167825cd9ba0SSimon Horman 	 }
167925cd9ba0SSimon Horman 
1680e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_TCP)) {
1681e6445719SPravin B Shelar 		const struct ovs_key_tcp *tcp_key;
1682e6445719SPravin B Shelar 
1683e6445719SPravin B Shelar 		tcp_key = nla_data(a[OVS_KEY_ATTR_TCP]);
16841139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src, tcp_key->tcp_src, is_mask);
16851139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst, tcp_key->tcp_dst, is_mask);
1686e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_TCP);
1687e6445719SPravin B Shelar 	}
1688e6445719SPravin B Shelar 
16895eb26b15SJarno Rajahalme 	if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
16901139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.flags,
16915eb26b15SJarno Rajahalme 				nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
16925eb26b15SJarno Rajahalme 				is_mask);
16935eb26b15SJarno Rajahalme 		attrs &= ~(1 << OVS_KEY_ATTR_TCP_FLAGS);
16945eb26b15SJarno Rajahalme 	}
16955eb26b15SJarno Rajahalme 
1696e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_UDP)) {
1697e6445719SPravin B Shelar 		const struct ovs_key_udp *udp_key;
1698e6445719SPravin B Shelar 
1699e6445719SPravin B Shelar 		udp_key = nla_data(a[OVS_KEY_ATTR_UDP]);
17001139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src, udp_key->udp_src, is_mask);
17011139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst, udp_key->udp_dst, is_mask);
1702e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_UDP);
1703e6445719SPravin B Shelar 	}
1704e6445719SPravin B Shelar 
1705e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
1706e6445719SPravin B Shelar 		const struct ovs_key_sctp *sctp_key;
1707e6445719SPravin B Shelar 
1708e6445719SPravin B Shelar 		sctp_key = nla_data(a[OVS_KEY_ATTR_SCTP]);
17091139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src, sctp_key->sctp_src, is_mask);
17101139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst, sctp_key->sctp_dst, is_mask);
1711e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_SCTP);
1712e6445719SPravin B Shelar 	}
1713e6445719SPravin B Shelar 
1714e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ICMP)) {
1715e6445719SPravin B Shelar 		const struct ovs_key_icmp *icmp_key;
1716e6445719SPravin B Shelar 
1717e6445719SPravin B Shelar 		icmp_key = nla_data(a[OVS_KEY_ATTR_ICMP]);
17181139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src,
1719e6445719SPravin B Shelar 				htons(icmp_key->icmp_type), is_mask);
17201139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst,
1721e6445719SPravin B Shelar 				htons(icmp_key->icmp_code), is_mask);
1722e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ICMP);
1723e6445719SPravin B Shelar 	}
1724e6445719SPravin B Shelar 
1725e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ICMPV6)) {
1726e6445719SPravin B Shelar 		const struct ovs_key_icmpv6 *icmpv6_key;
1727e6445719SPravin B Shelar 
1728e6445719SPravin B Shelar 		icmpv6_key = nla_data(a[OVS_KEY_ATTR_ICMPV6]);
17291139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.src,
1730e6445719SPravin B Shelar 				htons(icmpv6_key->icmpv6_type), is_mask);
17311139e241SJarno Rajahalme 		SW_FLOW_KEY_PUT(match, tp.dst,
1732e6445719SPravin B Shelar 				htons(icmpv6_key->icmpv6_code), is_mask);
1733e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ICMPV6);
1734e6445719SPravin B Shelar 	}
1735e6445719SPravin B Shelar 
1736e6445719SPravin B Shelar 	if (attrs & (1 << OVS_KEY_ATTR_ND)) {
1737e6445719SPravin B Shelar 		const struct ovs_key_nd *nd_key;
1738e6445719SPravin B Shelar 
1739e6445719SPravin B Shelar 		nd_key = nla_data(a[OVS_KEY_ATTR_ND]);
1740e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.target,
1741e6445719SPravin B Shelar 			nd_key->nd_target,
1742e6445719SPravin B Shelar 			sizeof(match->key->ipv6.nd.target),
1743e6445719SPravin B Shelar 			is_mask);
1744e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.sll,
1745e6445719SPravin B Shelar 			nd_key->nd_sll, ETH_ALEN, is_mask);
1746e6445719SPravin B Shelar 		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.tll,
1747e6445719SPravin B Shelar 				nd_key->nd_tll, ETH_ALEN, is_mask);
1748e6445719SPravin B Shelar 		attrs &= ~(1 << OVS_KEY_ATTR_ND);
1749e6445719SPravin B Shelar 	}
1750e6445719SPravin B Shelar 
1751426cda5cSJesse Gross 	if (attrs != 0) {
175205da5898SJarno Rajahalme 		OVS_NLERR(log, "Unknown key attributes %llx",
1753426cda5cSJesse Gross 			  (unsigned long long)attrs);
1754e6445719SPravin B Shelar 		return -EINVAL;
1755426cda5cSJesse Gross 	}
1756e6445719SPravin B Shelar 
1757e6445719SPravin B Shelar 	return 0;
1758e6445719SPravin B Shelar }
1759e6445719SPravin B Shelar 
nlattr_set(struct nlattr * attr,u8 val,const struct ovs_len_tbl * tbl)176081bfe3c3SThomas Graf static void nlattr_set(struct nlattr *attr, u8 val,
176181bfe3c3SThomas Graf 		       const struct ovs_len_tbl *tbl)
1762e6445719SPravin B Shelar {
1763f47de068SPravin B Shelar 	struct nlattr *nla;
1764f47de068SPravin B Shelar 	int rem;
1765e6445719SPravin B Shelar 
1766f47de068SPravin B Shelar 	/* The nlattr stream should already have been validated */
1767f47de068SPravin B Shelar 	nla_for_each_nested(nla, attr, rem) {
176872f17bafSStefano Brivio 		if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
176972f17bafSStefano Brivio 			nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl);
177072f17bafSStefano Brivio 		else
1771f47de068SPravin B Shelar 			memset(nla_data(nla), val, nla_len(nla));
17729e384715SJoe Stringer 
17739e384715SJoe Stringer 		if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
17749e384715SJoe Stringer 			*(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
1775f47de068SPravin B Shelar 	}
1776982b5270SJesse Gross }
1777f47de068SPravin B Shelar 
mask_set_nlattr(struct nlattr * attr,u8 val)1778f47de068SPravin B Shelar static void mask_set_nlattr(struct nlattr *attr, u8 val)
1779f47de068SPravin B Shelar {
178081bfe3c3SThomas Graf 	nlattr_set(attr, val, ovs_key_lens);
1781e6445719SPravin B Shelar }
1782e6445719SPravin B Shelar 
1783e6445719SPravin B Shelar /**
1784e6445719SPravin B Shelar  * ovs_nla_get_match - parses Netlink attributes into a flow key and
1785e6445719SPravin B Shelar  * mask. In case the 'mask' is NULL, the flow is treated as exact match
1786e6445719SPravin B Shelar  * flow. Otherwise, it is treated as a wildcarded flow, except the mask
1787e6445719SPravin B Shelar  * does not include any don't care bit.
1788c2ac6673SJoe Stringer  * @net: Used to determine per-namespace field support.
1789e6445719SPravin B Shelar  * @match: receives the extracted flow match information.
179096678514SAndrew Lunn  * @nla_key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
1791e6445719SPravin B Shelar  * sequence. The fields should of the packet that triggered the creation
1792e6445719SPravin B Shelar  * of this flow.
179396678514SAndrew Lunn  * @nla_mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_*
179496678514SAndrew Lunn  * Netlink attribute specifies the mask field of the wildcarded flow.
179505da5898SJarno Rajahalme  * @log: Boolean to allow kernel error logging.  Normally true, but when
179605da5898SJarno Rajahalme  * probing for feature compatibility this should be passed in as false to
179705da5898SJarno Rajahalme  * suppress unnecessary error logging.
1798e6445719SPravin 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)1799c2ac6673SJoe Stringer int ovs_nla_get_match(struct net *net, struct sw_flow_match *match,
1800a85311bfSPravin B Shelar 		      const struct nlattr *nla_key,
180105da5898SJarno Rajahalme 		      const struct nlattr *nla_mask,
180205da5898SJarno Rajahalme 		      bool log)
1803e6445719SPravin B Shelar {
1804e6445719SPravin B Shelar 	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
1805f47de068SPravin B Shelar 	struct nlattr *newmask = NULL;
1806e6445719SPravin B Shelar 	u64 key_attrs = 0;
1807e6445719SPravin B Shelar 	u64 mask_attrs = 0;
1808e6445719SPravin B Shelar 	int err;
1809e6445719SPravin B Shelar 
181005da5898SJarno Rajahalme 	err = parse_flow_nlattrs(nla_key, a, &key_attrs, log);
1811e6445719SPravin B Shelar 	if (err)
1812e6445719SPravin B Shelar 		return err;
1813e6445719SPravin B Shelar 
1814018c1ddaSEric Garver 	err = parse_vlan_from_nlattrs(match, &key_attrs, a, false, log);
1815e6445719SPravin B Shelar 	if (err)
1816e6445719SPravin B Shelar 		return err;
1817e6445719SPravin B Shelar 
1818c2ac6673SJoe Stringer 	err = ovs_key_from_nlattrs(net, match, key_attrs, a, false, log);
1819e6445719SPravin B Shelar 	if (err)
1820e6445719SPravin B Shelar 		return err;
1821e6445719SPravin B Shelar 
1822a85311bfSPravin B Shelar 	if (match->mask) {
1823a85311bfSPravin B Shelar 		if (!nla_mask) {
1824a85311bfSPravin B Shelar 			/* Create an exact match mask. We need to set to 0xff
1825a85311bfSPravin B Shelar 			 * all the 'match->mask' fields that have been touched
1826a85311bfSPravin B Shelar 			 * in 'match->key'. We cannot simply memset
1827a85311bfSPravin B Shelar 			 * 'match->mask', because padding bytes and fields not
1828a85311bfSPravin B Shelar 			 * specified in 'match->key' should be left to 0.
1829a85311bfSPravin B Shelar 			 * Instead, we use a stream of netlink attributes,
1830a85311bfSPravin B Shelar 			 * copied from 'key' and set to 0xff.
1831a85311bfSPravin B Shelar 			 * ovs_key_from_nlattrs() will take care of filling
1832a85311bfSPravin B Shelar 			 * 'match->mask' appropriately.
1833f47de068SPravin B Shelar 			 */
1834a85311bfSPravin B Shelar 			newmask = kmemdup(nla_key,
1835a85311bfSPravin B Shelar 					  nla_total_size(nla_len(nla_key)),
1836f47de068SPravin B Shelar 					  GFP_KERNEL);
1837f47de068SPravin B Shelar 			if (!newmask)
1838f47de068SPravin B Shelar 				return -ENOMEM;
1839f47de068SPravin B Shelar 
1840f47de068SPravin B Shelar 			mask_set_nlattr(newmask, 0xff);
1841f47de068SPravin B Shelar 
1842a85311bfSPravin B Shelar 			/* The userspace does not send tunnel attributes that
1843a85311bfSPravin B Shelar 			 * are 0, but we should not wildcard them nonetheless.
1844f47de068SPravin B Shelar 			 */
184500a93babSJiri Benc 			if (match->key->tun_proto)
1846a85311bfSPravin B Shelar 				SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
1847a85311bfSPravin B Shelar 							 0xff, true);
1848f47de068SPravin B Shelar 
1849a85311bfSPravin B Shelar 			nla_mask = newmask;
1850f47de068SPravin B Shelar 		}
1851f47de068SPravin B Shelar 
185205da5898SJarno Rajahalme 		err = parse_flow_mask_nlattrs(nla_mask, a, &mask_attrs, log);
1853e6445719SPravin B Shelar 		if (err)
1854f47de068SPravin B Shelar 			goto free_newmask;
1855e6445719SPravin B Shelar 
1856a85311bfSPravin B Shelar 		/* Always match on tci. */
1857018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.vlan.tci, htons(0xffff), true);
1858018c1ddaSEric Garver 		SW_FLOW_KEY_PUT(match, eth.cvlan.tci, htons(0xffff), true);
1859a85311bfSPravin B Shelar 
1860018c1ddaSEric Garver 		err = parse_vlan_from_nlattrs(match, &mask_attrs, a, true, log);
1861f47de068SPravin B Shelar 		if (err)
1862f47de068SPravin B Shelar 			goto free_newmask;
1863e6445719SPravin B Shelar 
1864c2ac6673SJoe Stringer 		err = ovs_key_from_nlattrs(net, match, mask_attrs, a, true,
1865c2ac6673SJoe Stringer 					   log);
1866e6445719SPravin B Shelar 		if (err)
1867f47de068SPravin B Shelar 			goto free_newmask;
1868e6445719SPravin B Shelar 	}
1869e6445719SPravin B Shelar 
187005da5898SJarno Rajahalme 	if (!match_validate(match, key_attrs, mask_attrs, log))
1871f47de068SPravin B Shelar 		err = -EINVAL;
1872e6445719SPravin B Shelar 
1873f47de068SPravin B Shelar free_newmask:
1874f47de068SPravin B Shelar 	kfree(newmask);
1875f47de068SPravin B Shelar 	return err;
1876e6445719SPravin B Shelar }
1877e6445719SPravin B Shelar 
get_ufid_len(const struct nlattr * attr,bool log)187874ed7ab9SJoe Stringer static size_t get_ufid_len(const struct nlattr *attr, bool log)
187974ed7ab9SJoe Stringer {
188074ed7ab9SJoe Stringer 	size_t len;
188174ed7ab9SJoe Stringer 
188274ed7ab9SJoe Stringer 	if (!attr)
188374ed7ab9SJoe Stringer 		return 0;
188474ed7ab9SJoe Stringer 
188574ed7ab9SJoe Stringer 	len = nla_len(attr);
188674ed7ab9SJoe Stringer 	if (len < 1 || len > MAX_UFID_LENGTH) {
188774ed7ab9SJoe Stringer 		OVS_NLERR(log, "ufid size %u bytes exceeds the range (1, %d)",
188874ed7ab9SJoe Stringer 			  nla_len(attr), MAX_UFID_LENGTH);
188974ed7ab9SJoe Stringer 		return 0;
189074ed7ab9SJoe Stringer 	}
189174ed7ab9SJoe Stringer 
189274ed7ab9SJoe Stringer 	return len;
189374ed7ab9SJoe Stringer }
189474ed7ab9SJoe Stringer 
189574ed7ab9SJoe Stringer /* Initializes 'flow->ufid', returning true if 'attr' contains a valid UFID,
189674ed7ab9SJoe Stringer  * or false otherwise.
189774ed7ab9SJoe Stringer  */
ovs_nla_get_ufid(struct sw_flow_id * sfid,const struct nlattr * attr,bool log)189874ed7ab9SJoe Stringer bool ovs_nla_get_ufid(struct sw_flow_id *sfid, const struct nlattr *attr,
189974ed7ab9SJoe Stringer 		      bool log)
190074ed7ab9SJoe Stringer {
190174ed7ab9SJoe Stringer 	sfid->ufid_len = get_ufid_len(attr, log);
190274ed7ab9SJoe Stringer 	if (sfid->ufid_len)
190374ed7ab9SJoe Stringer 		memcpy(sfid->ufid, nla_data(attr), sfid->ufid_len);
190474ed7ab9SJoe Stringer 
190574ed7ab9SJoe Stringer 	return sfid->ufid_len;
190674ed7ab9SJoe Stringer }
190774ed7ab9SJoe Stringer 
ovs_nla_get_identifier(struct sw_flow_id * sfid,const struct nlattr * ufid,const struct sw_flow_key * key,bool log)190874ed7ab9SJoe Stringer int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
190974ed7ab9SJoe Stringer 			   const struct sw_flow_key *key, bool log)
191074ed7ab9SJoe Stringer {
191174ed7ab9SJoe Stringer 	struct sw_flow_key *new_key;
191274ed7ab9SJoe Stringer 
191374ed7ab9SJoe Stringer 	if (ovs_nla_get_ufid(sfid, ufid, log))
191474ed7ab9SJoe Stringer 		return 0;
191574ed7ab9SJoe Stringer 
191674ed7ab9SJoe Stringer 	/* If UFID was not provided, use unmasked key. */
191774ed7ab9SJoe Stringer 	new_key = kmalloc(sizeof(*new_key), GFP_KERNEL);
191874ed7ab9SJoe Stringer 	if (!new_key)
191974ed7ab9SJoe Stringer 		return -ENOMEM;
192074ed7ab9SJoe Stringer 	memcpy(new_key, key, sizeof(*key));
192174ed7ab9SJoe Stringer 	sfid->unmasked_key = new_key;
192274ed7ab9SJoe Stringer 
192374ed7ab9SJoe Stringer 	return 0;
192474ed7ab9SJoe Stringer }
192574ed7ab9SJoe Stringer 
ovs_nla_get_ufid_flags(const struct nlattr * attr)192674ed7ab9SJoe Stringer u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
192774ed7ab9SJoe Stringer {
192874ed7ab9SJoe Stringer 	return attr ? nla_get_u32(attr) : 0;
192974ed7ab9SJoe Stringer }
193074ed7ab9SJoe Stringer 
1931e6445719SPravin B Shelar /**
1932e6445719SPravin B Shelar  * ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
19339dd7f890SJarno Rajahalme  * @net: Network namespace.
19349dd7f890SJarno Rajahalme  * @key: Receives extracted in_port, priority, tun_key, skb_mark and conntrack
19359dd7f890SJarno Rajahalme  * metadata.
19369dd7f890SJarno Rajahalme  * @a: Array of netlink attributes holding parsed %OVS_KEY_ATTR_* Netlink
19379dd7f890SJarno Rajahalme  * attributes.
19389dd7f890SJarno Rajahalme  * @attrs: Bit mask for the netlink attributes included in @a.
193905da5898SJarno Rajahalme  * @log: Boolean to allow kernel error logging.  Normally true, but when
194005da5898SJarno Rajahalme  * probing for feature compatibility this should be passed in as false to
194105da5898SJarno Rajahalme  * suppress unnecessary error logging.
1942e6445719SPravin B Shelar  *
1943e6445719SPravin B Shelar  * This parses a series of Netlink attributes that form a flow key, which must
1944e6445719SPravin B Shelar  * take the same form accepted by flow_from_nlattrs(), but only enough of it to
1945e6445719SPravin B Shelar  * get the metadata, that is, the parts of the flow key that cannot be
1946e6445719SPravin B Shelar  * extracted from the packet itself.
19479dd7f890SJarno Rajahalme  *
19489dd7f890SJarno Rajahalme  * This must be called before the packet key fields are filled in 'key'.
1949e6445719SPravin B Shelar  */
1950e6445719SPravin 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)19519dd7f890SJarno Rajahalme int ovs_nla_get_flow_metadata(struct net *net,
19529dd7f890SJarno Rajahalme 			      const struct nlattr *a[OVS_KEY_ATTR_MAX + 1],
19539dd7f890SJarno Rajahalme 			      u64 attrs, struct sw_flow_key *key, bool log)
1954e6445719SPravin B Shelar {
195583c8df26SPravin B Shelar 	struct sw_flow_match match;
1956e6445719SPravin B Shelar 
1957e6445719SPravin B Shelar 	memset(&match, 0, sizeof(match));
195883c8df26SPravin B Shelar 	match.key = key;
1959e6445719SPravin B Shelar 
1960316d4d78SJarno Rajahalme 	key->ct_state = 0;
1961316d4d78SJarno Rajahalme 	key->ct_zone = 0;
1962316d4d78SJarno Rajahalme 	key->ct_orig_proto = 0;
19637f8a436eSJoe Stringer 	memset(&key->ct, 0, sizeof(key->ct));
19649dd7f890SJarno Rajahalme 	memset(&key->ipv4.ct_orig, 0, sizeof(key->ipv4.ct_orig));
19659dd7f890SJarno Rajahalme 	memset(&key->ipv6.ct_orig, 0, sizeof(key->ipv6.ct_orig));
19669dd7f890SJarno Rajahalme 
196783c8df26SPravin B Shelar 	key->phy.in_port = DP_MAX_PORTS;
1968e6445719SPravin B Shelar 
1969c2ac6673SJoe Stringer 	return metadata_from_nlattrs(net, &match, &attrs, a, false, log);
1970e6445719SPravin B Shelar }
1971e6445719SPravin B Shelar 
ovs_nla_put_vlan(struct sk_buff * skb,const struct vlan_head * vh,bool is_mask)1972018c1ddaSEric Garver static int ovs_nla_put_vlan(struct sk_buff *skb, const struct vlan_head *vh,
1973018c1ddaSEric Garver 			    bool is_mask)
1974018c1ddaSEric Garver {
1975018c1ddaSEric Garver 	__be16 eth_type = !is_mask ? vh->tpid : htons(0xffff);
1976018c1ddaSEric Garver 
1977018c1ddaSEric Garver 	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
1978018c1ddaSEric Garver 	    nla_put_be16(skb, OVS_KEY_ATTR_VLAN, vh->tci))
1979018c1ddaSEric Garver 		return -EMSGSIZE;
1980018c1ddaSEric Garver 	return 0;
1981018c1ddaSEric Garver }
1982018c1ddaSEric Garver 
nsh_key_to_nlattr(const struct ovs_key_nsh * nsh,bool is_mask,struct sk_buff * skb)1983b2d0f5d5SYi Yang static int nsh_key_to_nlattr(const struct ovs_key_nsh *nsh, bool is_mask,
1984b2d0f5d5SYi Yang 			     struct sk_buff *skb)
1985b2d0f5d5SYi Yang {
1986b2d0f5d5SYi Yang 	struct nlattr *start;
1987b2d0f5d5SYi Yang 
1988ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_KEY_ATTR_NSH);
1989b2d0f5d5SYi Yang 	if (!start)
1990b2d0f5d5SYi Yang 		return -EMSGSIZE;
1991b2d0f5d5SYi Yang 
1992b2d0f5d5SYi Yang 	if (nla_put(skb, OVS_NSH_KEY_ATTR_BASE, sizeof(nsh->base), &nsh->base))
1993b2d0f5d5SYi Yang 		goto nla_put_failure;
1994b2d0f5d5SYi Yang 
1995b2d0f5d5SYi Yang 	if (is_mask || nsh->base.mdtype == NSH_M_TYPE1) {
1996b2d0f5d5SYi Yang 		if (nla_put(skb, OVS_NSH_KEY_ATTR_MD1,
1997b2d0f5d5SYi Yang 			    sizeof(nsh->context), nsh->context))
1998b2d0f5d5SYi Yang 			goto nla_put_failure;
1999b2d0f5d5SYi Yang 	}
2000b2d0f5d5SYi Yang 
2001b2d0f5d5SYi Yang 	/* Don't support MD type 2 yet */
2002b2d0f5d5SYi Yang 
2003b2d0f5d5SYi Yang 	nla_nest_end(skb, start);
2004b2d0f5d5SYi Yang 
2005b2d0f5d5SYi Yang 	return 0;
2006b2d0f5d5SYi Yang 
2007b2d0f5d5SYi Yang nla_put_failure:
2008b2d0f5d5SYi Yang 	return -EMSGSIZE;
2009b2d0f5d5SYi Yang }
2010b2d0f5d5SYi Yang 
__ovs_nla_put_key(const struct sw_flow_key * swkey,const struct sw_flow_key * output,bool is_mask,struct sk_buff * skb)20115b4237bbSJoe Stringer static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
20125b4237bbSJoe Stringer 			     const struct sw_flow_key *output, bool is_mask,
20135b4237bbSJoe Stringer 			     struct sk_buff *skb)
2014e6445719SPravin B Shelar {
2015e6445719SPravin B Shelar 	struct ovs_key_ethernet *eth_key;
2016018c1ddaSEric Garver 	struct nlattr *nla;
2017018c1ddaSEric Garver 	struct nlattr *encap = NULL;
2018018c1ddaSEric Garver 	struct nlattr *in_encap = NULL;
2019e6445719SPravin B Shelar 
2020971427f3SAndy Zhou 	if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
2021971427f3SAndy Zhou 		goto nla_put_failure;
2022971427f3SAndy Zhou 
2023971427f3SAndy Zhou 	if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash))
2024971427f3SAndy Zhou 		goto nla_put_failure;
2025971427f3SAndy Zhou 
2026e6445719SPravin B Shelar 	if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
2027e6445719SPravin B Shelar 		goto nla_put_failure;
2028e6445719SPravin B Shelar 
202900a93babSJiri Benc 	if ((swkey->tun_proto || is_mask)) {
2030d91641d9SThomas Graf 		const void *opts = NULL;
2031f5796684SJesse Gross 
2032f5796684SJesse Gross 		if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT)
2033d91641d9SThomas Graf 			opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len);
2034f5796684SJesse Gross 
20356b26ba3aSJiri Benc 		if (ip_tun_to_nlattr(skb, &output->tun_key, opts,
203618b6f717Swenxu 				     swkey->tun_opts_len, swkey->tun_proto, 0))
2037e6445719SPravin B Shelar 			goto nla_put_failure;
2038f5796684SJesse Gross 	}
2039e6445719SPravin B Shelar 
2040e6445719SPravin B Shelar 	if (swkey->phy.in_port == DP_MAX_PORTS) {
2041e6445719SPravin B Shelar 		if (is_mask && (output->phy.in_port == 0xffff))
2042e6445719SPravin B Shelar 			if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, 0xffffffff))
2043e6445719SPravin B Shelar 				goto nla_put_failure;
2044e6445719SPravin B Shelar 	} else {
2045e6445719SPravin B Shelar 		u16 upper_u16;
2046e6445719SPravin B Shelar 		upper_u16 = !is_mask ? 0 : 0xffff;
2047e6445719SPravin B Shelar 
2048e6445719SPravin B Shelar 		if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT,
2049e6445719SPravin B Shelar 				(upper_u16 << 16) | output->phy.in_port))
2050e6445719SPravin B Shelar 			goto nla_put_failure;
2051e6445719SPravin B Shelar 	}
2052e6445719SPravin B Shelar 
2053e6445719SPravin B Shelar 	if (nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark))
2054e6445719SPravin B Shelar 		goto nla_put_failure;
2055e6445719SPravin B Shelar 
20569dd7f890SJarno Rajahalme 	if (ovs_ct_put_key(swkey, output, skb))
20577f8a436eSJoe Stringer 		goto nla_put_failure;
20587f8a436eSJoe Stringer 
20590a6410fbSJiri Benc 	if (ovs_key_mac_proto(swkey) == MAC_PROTO_ETHERNET) {
2060e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
2061e6445719SPravin B Shelar 		if (!nla)
2062e6445719SPravin B Shelar 			goto nla_put_failure;
2063e6445719SPravin B Shelar 
2064e6445719SPravin B Shelar 		eth_key = nla_data(nla);
20658c63ff09SJoe Perches 		ether_addr_copy(eth_key->eth_src, output->eth.src);
20668c63ff09SJoe Perches 		ether_addr_copy(eth_key->eth_dst, output->eth.dst);
2067e6445719SPravin B Shelar 
2068018c1ddaSEric Garver 		if (swkey->eth.vlan.tci || eth_type_vlan(swkey->eth.type)) {
2069018c1ddaSEric Garver 			if (ovs_nla_put_vlan(skb, &output->eth.vlan, is_mask))
2070e6445719SPravin B Shelar 				goto nla_put_failure;
2071ae0be8deSMichal Kubecek 			encap = nla_nest_start_noflag(skb, OVS_KEY_ATTR_ENCAP);
2072018c1ddaSEric Garver 			if (!swkey->eth.vlan.tci)
2073e6445719SPravin B Shelar 				goto unencap;
2074018c1ddaSEric Garver 
2075018c1ddaSEric Garver 			if (swkey->eth.cvlan.tci || eth_type_vlan(swkey->eth.type)) {
2076018c1ddaSEric Garver 				if (ovs_nla_put_vlan(skb, &output->eth.cvlan, is_mask))
2077018c1ddaSEric Garver 					goto nla_put_failure;
2078ae0be8deSMichal Kubecek 				in_encap = nla_nest_start_noflag(skb,
2079ae0be8deSMichal Kubecek 								 OVS_KEY_ATTR_ENCAP);
2080018c1ddaSEric Garver 				if (!swkey->eth.cvlan.tci)
2081018c1ddaSEric Garver 					goto unencap;
2082018c1ddaSEric Garver 			}
2083018c1ddaSEric Garver 		}
2084e6445719SPravin B Shelar 
2085e6445719SPravin B Shelar 		if (swkey->eth.type == htons(ETH_P_802_2)) {
2086e6445719SPravin B Shelar 			/*
2087e6445719SPravin B Shelar 			* Ethertype 802.2 is represented in the netlink with omitted
2088e6445719SPravin B Shelar 			* OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
2089e6445719SPravin B Shelar 			* 0xffff in the mask attribute.  Ethertype can also
2090e6445719SPravin B Shelar 			* be wildcarded.
2091e6445719SPravin B Shelar 			*/
2092e6445719SPravin B Shelar 			if (is_mask && output->eth.type)
2093e6445719SPravin B Shelar 				if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
2094e6445719SPravin B Shelar 							output->eth.type))
2095e6445719SPravin B Shelar 					goto nla_put_failure;
2096e6445719SPravin B Shelar 			goto unencap;
2097e6445719SPravin B Shelar 		}
20980a6410fbSJiri Benc 	}
2099e6445719SPravin B Shelar 
2100e6445719SPravin B Shelar 	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
2101e6445719SPravin B Shelar 		goto nla_put_failure;
2102e6445719SPravin B Shelar 
2103018c1ddaSEric Garver 	if (eth_type_vlan(swkey->eth.type)) {
2104018c1ddaSEric Garver 		/* There are 3 VLAN tags, we don't know anything about the rest
2105018c1ddaSEric Garver 		 * of the packet, so truncate here.
2106018c1ddaSEric Garver 		 */
2107018c1ddaSEric Garver 		WARN_ON_ONCE(!(encap && in_encap));
2108018c1ddaSEric Garver 		goto unencap;
2109018c1ddaSEric Garver 	}
2110018c1ddaSEric Garver 
2111e6445719SPravin B Shelar 	if (swkey->eth.type == htons(ETH_P_IP)) {
2112e6445719SPravin B Shelar 		struct ovs_key_ipv4 *ipv4_key;
2113e6445719SPravin B Shelar 
2114e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV4, sizeof(*ipv4_key));
2115e6445719SPravin B Shelar 		if (!nla)
2116e6445719SPravin B Shelar 			goto nla_put_failure;
2117e6445719SPravin B Shelar 		ipv4_key = nla_data(nla);
2118e6445719SPravin B Shelar 		ipv4_key->ipv4_src = output->ipv4.addr.src;
2119e6445719SPravin B Shelar 		ipv4_key->ipv4_dst = output->ipv4.addr.dst;
2120e6445719SPravin B Shelar 		ipv4_key->ipv4_proto = output->ip.proto;
2121e6445719SPravin B Shelar 		ipv4_key->ipv4_tos = output->ip.tos;
2122e6445719SPravin B Shelar 		ipv4_key->ipv4_ttl = output->ip.ttl;
2123e6445719SPravin B Shelar 		ipv4_key->ipv4_frag = output->ip.frag;
2124e6445719SPravin B Shelar 	} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
2125e6445719SPravin B Shelar 		struct ovs_key_ipv6 *ipv6_key;
212628a3f060SToms Atteka 		struct ovs_key_ipv6_exthdrs *ipv6_exthdrs_key;
2127e6445719SPravin B Shelar 
2128e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6, sizeof(*ipv6_key));
2129e6445719SPravin B Shelar 		if (!nla)
2130e6445719SPravin B Shelar 			goto nla_put_failure;
2131e6445719SPravin B Shelar 		ipv6_key = nla_data(nla);
2132e6445719SPravin B Shelar 		memcpy(ipv6_key->ipv6_src, &output->ipv6.addr.src,
2133e6445719SPravin B Shelar 				sizeof(ipv6_key->ipv6_src));
2134e6445719SPravin B Shelar 		memcpy(ipv6_key->ipv6_dst, &output->ipv6.addr.dst,
2135e6445719SPravin B Shelar 				sizeof(ipv6_key->ipv6_dst));
2136e6445719SPravin B Shelar 		ipv6_key->ipv6_label = output->ipv6.label;
2137e6445719SPravin B Shelar 		ipv6_key->ipv6_proto = output->ip.proto;
2138e6445719SPravin B Shelar 		ipv6_key->ipv6_tclass = output->ip.tos;
2139e6445719SPravin B Shelar 		ipv6_key->ipv6_hlimit = output->ip.ttl;
2140e6445719SPravin B Shelar 		ipv6_key->ipv6_frag = output->ip.frag;
214128a3f060SToms Atteka 
214228a3f060SToms Atteka 		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6_EXTHDRS,
214328a3f060SToms Atteka 				  sizeof(*ipv6_exthdrs_key));
214428a3f060SToms Atteka 		if (!nla)
214528a3f060SToms Atteka 			goto nla_put_failure;
214628a3f060SToms Atteka 		ipv6_exthdrs_key = nla_data(nla);
214728a3f060SToms Atteka 		ipv6_exthdrs_key->hdrs = output->ipv6.exthdrs;
2148b2d0f5d5SYi Yang 	} else if (swkey->eth.type == htons(ETH_P_NSH)) {
2149b2d0f5d5SYi Yang 		if (nsh_key_to_nlattr(&output->nsh, is_mask, skb))
2150b2d0f5d5SYi Yang 			goto nla_put_failure;
2151e6445719SPravin B Shelar 	} else if (swkey->eth.type == htons(ETH_P_ARP) ||
2152e6445719SPravin B Shelar 		   swkey->eth.type == htons(ETH_P_RARP)) {
2153e6445719SPravin B Shelar 		struct ovs_key_arp *arp_key;
2154e6445719SPravin B Shelar 
2155e6445719SPravin B Shelar 		nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
2156e6445719SPravin B Shelar 		if (!nla)
2157e6445719SPravin B Shelar 			goto nla_put_failure;
2158e6445719SPravin B Shelar 		arp_key = nla_data(nla);
2159e6445719SPravin B Shelar 		memset(arp_key, 0, sizeof(struct ovs_key_arp));
2160e6445719SPravin B Shelar 		arp_key->arp_sip = output->ipv4.addr.src;
2161e6445719SPravin B Shelar 		arp_key->arp_tip = output->ipv4.addr.dst;
2162e6445719SPravin B Shelar 		arp_key->arp_op = htons(output->ip.proto);
21638c63ff09SJoe Perches 		ether_addr_copy(arp_key->arp_sha, output->ipv4.arp.sha);
21648c63ff09SJoe Perches 		ether_addr_copy(arp_key->arp_tha, output->ipv4.arp.tha);
216525cd9ba0SSimon Horman 	} else if (eth_p_mpls(swkey->eth.type)) {
2166fbdcdd78SMartin Varghese 		u8 i, num_labels;
216725cd9ba0SSimon Horman 		struct ovs_key_mpls *mpls_key;
216825cd9ba0SSimon Horman 
2169fbdcdd78SMartin Varghese 		num_labels = hweight_long(output->mpls.num_labels_mask);
2170fbdcdd78SMartin Varghese 		nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS,
2171fbdcdd78SMartin Varghese 				  num_labels * sizeof(*mpls_key));
217225cd9ba0SSimon Horman 		if (!nla)
217325cd9ba0SSimon Horman 			goto nla_put_failure;
2174fbdcdd78SMartin Varghese 
217525cd9ba0SSimon Horman 		mpls_key = nla_data(nla);
2176fbdcdd78SMartin Varghese 		for (i = 0; i < num_labels; i++)
2177fbdcdd78SMartin Varghese 			mpls_key[i].mpls_lse = output->mpls.lse[i];
2178e6445719SPravin B Shelar 	}
2179e6445719SPravin B Shelar 
2180e6445719SPravin B Shelar 	if ((swkey->eth.type == htons(ETH_P_IP) ||
2181e6445719SPravin B Shelar 	     swkey->eth.type == htons(ETH_P_IPV6)) &&
2182e6445719SPravin B Shelar 	     swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
2183e6445719SPravin B Shelar 
2184e6445719SPravin B Shelar 		if (swkey->ip.proto == IPPROTO_TCP) {
2185e6445719SPravin B Shelar 			struct ovs_key_tcp *tcp_key;
2186e6445719SPravin B Shelar 
2187e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_TCP, sizeof(*tcp_key));
2188e6445719SPravin B Shelar 			if (!nla)
2189e6445719SPravin B Shelar 				goto nla_put_failure;
2190e6445719SPravin B Shelar 			tcp_key = nla_data(nla);
21911139e241SJarno Rajahalme 			tcp_key->tcp_src = output->tp.src;
21921139e241SJarno Rajahalme 			tcp_key->tcp_dst = output->tp.dst;
21935eb26b15SJarno Rajahalme 			if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS,
21941139e241SJarno Rajahalme 					 output->tp.flags))
21955eb26b15SJarno Rajahalme 				goto nla_put_failure;
2196e6445719SPravin B Shelar 		} else if (swkey->ip.proto == IPPROTO_UDP) {
2197e6445719SPravin B Shelar 			struct ovs_key_udp *udp_key;
2198e6445719SPravin B Shelar 
2199e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_UDP, sizeof(*udp_key));
2200e6445719SPravin B Shelar 			if (!nla)
2201e6445719SPravin B Shelar 				goto nla_put_failure;
2202e6445719SPravin B Shelar 			udp_key = nla_data(nla);
22031139e241SJarno Rajahalme 			udp_key->udp_src = output->tp.src;
22041139e241SJarno Rajahalme 			udp_key->udp_dst = output->tp.dst;
2205e6445719SPravin B Shelar 		} else if (swkey->ip.proto == IPPROTO_SCTP) {
2206e6445719SPravin B Shelar 			struct ovs_key_sctp *sctp_key;
2207e6445719SPravin B Shelar 
2208e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_SCTP, sizeof(*sctp_key));
2209e6445719SPravin B Shelar 			if (!nla)
2210e6445719SPravin B Shelar 				goto nla_put_failure;
2211e6445719SPravin B Shelar 			sctp_key = nla_data(nla);
22121139e241SJarno Rajahalme 			sctp_key->sctp_src = output->tp.src;
22131139e241SJarno Rajahalme 			sctp_key->sctp_dst = output->tp.dst;
2214e6445719SPravin B Shelar 		} else if (swkey->eth.type == htons(ETH_P_IP) &&
2215e6445719SPravin B Shelar 			   swkey->ip.proto == IPPROTO_ICMP) {
2216e6445719SPravin B Shelar 			struct ovs_key_icmp *icmp_key;
2217e6445719SPravin B Shelar 
2218e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMP, sizeof(*icmp_key));
2219e6445719SPravin B Shelar 			if (!nla)
2220e6445719SPravin B Shelar 				goto nla_put_failure;
2221e6445719SPravin B Shelar 			icmp_key = nla_data(nla);
22221139e241SJarno Rajahalme 			icmp_key->icmp_type = ntohs(output->tp.src);
22231139e241SJarno Rajahalme 			icmp_key->icmp_code = ntohs(output->tp.dst);
2224e6445719SPravin B Shelar 		} else if (swkey->eth.type == htons(ETH_P_IPV6) &&
2225e6445719SPravin B Shelar 			   swkey->ip.proto == IPPROTO_ICMPV6) {
2226e6445719SPravin B Shelar 			struct ovs_key_icmpv6 *icmpv6_key;
2227e6445719SPravin B Shelar 
2228e6445719SPravin B Shelar 			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMPV6,
2229e6445719SPravin B Shelar 						sizeof(*icmpv6_key));
2230e6445719SPravin B Shelar 			if (!nla)
2231e6445719SPravin B Shelar 				goto nla_put_failure;
2232e6445719SPravin B Shelar 			icmpv6_key = nla_data(nla);
22331139e241SJarno Rajahalme 			icmpv6_key->icmpv6_type = ntohs(output->tp.src);
22341139e241SJarno Rajahalme 			icmpv6_key->icmpv6_code = ntohs(output->tp.dst);
2235e6445719SPravin B Shelar 
2236f19c4445SMartin Varghese 			if (swkey->tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
2237f19c4445SMartin Varghese 			    swkey->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
2238e6445719SPravin B Shelar 				struct ovs_key_nd *nd_key;
2239e6445719SPravin B Shelar 
2240e6445719SPravin B Shelar 				nla = nla_reserve(skb, OVS_KEY_ATTR_ND, sizeof(*nd_key));
2241e6445719SPravin B Shelar 				if (!nla)
2242e6445719SPravin B Shelar 					goto nla_put_failure;
2243e6445719SPravin B Shelar 				nd_key = nla_data(nla);
2244e6445719SPravin B Shelar 				memcpy(nd_key->nd_target, &output->ipv6.nd.target,
2245e6445719SPravin B Shelar 							sizeof(nd_key->nd_target));
22468c63ff09SJoe Perches 				ether_addr_copy(nd_key->nd_sll, output->ipv6.nd.sll);
22478c63ff09SJoe Perches 				ether_addr_copy(nd_key->nd_tll, output->ipv6.nd.tll);
2248e6445719SPravin B Shelar 			}
2249e6445719SPravin B Shelar 		}
2250e6445719SPravin B Shelar 	}
2251e6445719SPravin B Shelar 
2252e6445719SPravin B Shelar unencap:
2253018c1ddaSEric Garver 	if (in_encap)
2254018c1ddaSEric Garver 		nla_nest_end(skb, in_encap);
2255e6445719SPravin B Shelar 	if (encap)
2256e6445719SPravin B Shelar 		nla_nest_end(skb, encap);
2257e6445719SPravin B Shelar 
2258e6445719SPravin B Shelar 	return 0;
2259e6445719SPravin B Shelar 
2260e6445719SPravin B Shelar nla_put_failure:
2261e6445719SPravin B Shelar 	return -EMSGSIZE;
2262e6445719SPravin B Shelar }
2263e6445719SPravin 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)22645b4237bbSJoe Stringer int ovs_nla_put_key(const struct sw_flow_key *swkey,
22655b4237bbSJoe Stringer 		    const struct sw_flow_key *output, int attr, bool is_mask,
22665b4237bbSJoe Stringer 		    struct sk_buff *skb)
22675b4237bbSJoe Stringer {
22685b4237bbSJoe Stringer 	int err;
22695b4237bbSJoe Stringer 	struct nlattr *nla;
22705b4237bbSJoe Stringer 
2271ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, attr);
22725b4237bbSJoe Stringer 	if (!nla)
22735b4237bbSJoe Stringer 		return -EMSGSIZE;
22745b4237bbSJoe Stringer 	err = __ovs_nla_put_key(swkey, output, is_mask, skb);
22755b4237bbSJoe Stringer 	if (err)
22765b4237bbSJoe Stringer 		return err;
22775b4237bbSJoe Stringer 	nla_nest_end(skb, nla);
22785b4237bbSJoe Stringer 
22795b4237bbSJoe Stringer 	return 0;
22805b4237bbSJoe Stringer }
22815b4237bbSJoe Stringer 
22825b4237bbSJoe Stringer /* Called with ovs_mutex or RCU read lock. */
ovs_nla_put_identifier(const struct sw_flow * flow,struct sk_buff * skb)228374ed7ab9SJoe Stringer int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb)
22845b4237bbSJoe Stringer {
228574ed7ab9SJoe Stringer 	if (ovs_identifier_is_ufid(&flow->id))
228674ed7ab9SJoe Stringer 		return nla_put(skb, OVS_FLOW_ATTR_UFID, flow->id.ufid_len,
228774ed7ab9SJoe Stringer 			       flow->id.ufid);
228874ed7ab9SJoe Stringer 
228974ed7ab9SJoe Stringer 	return ovs_nla_put_key(flow->id.unmasked_key, flow->id.unmasked_key,
229074ed7ab9SJoe Stringer 			       OVS_FLOW_ATTR_KEY, false, skb);
229174ed7ab9SJoe Stringer }
229274ed7ab9SJoe Stringer 
229374ed7ab9SJoe Stringer /* Called with ovs_mutex or RCU read lock. */
ovs_nla_put_masked_key(const struct sw_flow * flow,struct sk_buff * skb)229474ed7ab9SJoe Stringer int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb)
229574ed7ab9SJoe Stringer {
229626ad0b83SPravin B Shelar 	return ovs_nla_put_key(&flow->key, &flow->key,
22975b4237bbSJoe Stringer 				OVS_FLOW_ATTR_KEY, false, skb);
22985b4237bbSJoe Stringer }
22995b4237bbSJoe Stringer 
23005b4237bbSJoe Stringer /* Called with ovs_mutex or RCU read lock. */
ovs_nla_put_mask(const struct sw_flow * flow,struct sk_buff * skb)23015b4237bbSJoe Stringer int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb)
23025b4237bbSJoe Stringer {
23035b4237bbSJoe Stringer 	return ovs_nla_put_key(&flow->key, &flow->mask->key,
23045b4237bbSJoe Stringer 				OVS_FLOW_ATTR_MASK, true, skb);
23055b4237bbSJoe Stringer }
23065b4237bbSJoe Stringer 
230767c8d22aSzhangliping static struct sw_flow_actions *nla_alloc_flow_actions(int size)
2308e6445719SPravin B Shelar {
nla_alloc_flow_actions(int size)2309e6445719SPravin B Shelar 	struct sw_flow_actions *sfa;
2310e6445719SPravin B Shelar 
2311ab3f7828SKees Cook 	sfa = kmalloc(kmalloc_size_roundup(sizeof(*sfa) + size), GFP_KERNEL);
2312e6445719SPravin B Shelar 	if (!sfa)
2313e6445719SPravin B Shelar 		return ERR_PTR(-ENOMEM);
2314e6445719SPravin B Shelar 
2315e6445719SPravin B Shelar 	sfa->actions_len = 0;
2316e6445719SPravin B Shelar 	return sfa;
2317e6445719SPravin B Shelar }
2318e6445719SPravin B Shelar 
23191f30fb91SIlya Maximets static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len);
23201f30fb91SIlya Maximets 
23211f30fb91SIlya Maximets static void ovs_nla_free_check_pkt_len_action(const struct nlattr *action)
23221f30fb91SIlya Maximets {
23231f30fb91SIlya Maximets 	const struct nlattr *a;
23241f30fb91SIlya Maximets 	int rem;
ovs_nla_free_check_pkt_len_action(const struct nlattr * action)23251f30fb91SIlya Maximets 
23261f30fb91SIlya Maximets 	nla_for_each_nested(a, action, rem) {
23271f30fb91SIlya Maximets 		switch (nla_type(a)) {
23281f30fb91SIlya Maximets 		case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL:
23291f30fb91SIlya Maximets 		case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER:
23301f30fb91SIlya Maximets 			ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
23311f30fb91SIlya Maximets 			break;
23321f30fb91SIlya Maximets 		}
23331f30fb91SIlya Maximets 	}
23341f30fb91SIlya Maximets }
23351f30fb91SIlya Maximets 
23361f30fb91SIlya Maximets static void ovs_nla_free_clone_action(const struct nlattr *action)
23371f30fb91SIlya Maximets {
23381f30fb91SIlya Maximets 	const struct nlattr *a = nla_data(action);
23391f30fb91SIlya Maximets 	int rem = nla_len(action);
ovs_nla_free_clone_action(const struct nlattr * action)23401f30fb91SIlya Maximets 
23411f30fb91SIlya Maximets 	switch (nla_type(a)) {
23421f30fb91SIlya Maximets 	case OVS_CLONE_ATTR_EXEC:
23431f30fb91SIlya Maximets 		/* The real list of actions follows this attribute. */
23441f30fb91SIlya Maximets 		a = nla_next(a, &rem);
23451f30fb91SIlya Maximets 		ovs_nla_free_nested_actions(a, rem);
23461f30fb91SIlya Maximets 		break;
23471f30fb91SIlya Maximets 	}
23481f30fb91SIlya Maximets }
23491f30fb91SIlya Maximets 
23501f30fb91SIlya Maximets static void ovs_nla_free_dec_ttl_action(const struct nlattr *action)
23511f30fb91SIlya Maximets {
23521f30fb91SIlya Maximets 	const struct nlattr *a = nla_data(action);
23531f30fb91SIlya Maximets 
ovs_nla_free_dec_ttl_action(const struct nlattr * action)23541f30fb91SIlya Maximets 	switch (nla_type(a)) {
23551f30fb91SIlya Maximets 	case OVS_DEC_TTL_ATTR_ACTION:
23561f30fb91SIlya Maximets 		ovs_nla_free_nested_actions(nla_data(a), nla_len(a));
23571f30fb91SIlya Maximets 		break;
23581f30fb91SIlya Maximets 	}
23591f30fb91SIlya Maximets }
23601f30fb91SIlya Maximets 
23611f30fb91SIlya Maximets static void ovs_nla_free_sample_action(const struct nlattr *action)
23621f30fb91SIlya Maximets {
23631f30fb91SIlya Maximets 	const struct nlattr *a = nla_data(action);
23641f30fb91SIlya Maximets 	int rem = nla_len(action);
ovs_nla_free_sample_action(const struct nlattr * action)23651f30fb91SIlya Maximets 
23661f30fb91SIlya Maximets 	switch (nla_type(a)) {
23671f30fb91SIlya Maximets 	case OVS_SAMPLE_ATTR_ARG:
23681f30fb91SIlya Maximets 		/* The real list of actions follows this attribute. */
23691f30fb91SIlya Maximets 		a = nla_next(a, &rem);
23701f30fb91SIlya Maximets 		ovs_nla_free_nested_actions(a, rem);
23711f30fb91SIlya Maximets 		break;
23721f30fb91SIlya Maximets 	}
23731f30fb91SIlya Maximets }
23741f30fb91SIlya Maximets 
237534ae932aSThomas Graf static void ovs_nla_free_set_action(const struct nlattr *a)
237634ae932aSThomas Graf {
237734ae932aSThomas Graf 	const struct nlattr *ovs_key = nla_data(a);
237834ae932aSThomas Graf 	struct ovs_tunnel_info *ovs_tun;
ovs_nla_free_set_action(const struct nlattr * a)237934ae932aSThomas Graf 
238034ae932aSThomas Graf 	switch (nla_type(ovs_key)) {
238134ae932aSThomas Graf 	case OVS_KEY_ATTR_TUNNEL_INFO:
238234ae932aSThomas Graf 		ovs_tun = nla_data(ovs_key);
238334ae932aSThomas Graf 		dst_release((struct dst_entry *)ovs_tun->tun_dst);
238434ae932aSThomas Graf 		break;
238534ae932aSThomas Graf 	}
238634ae932aSThomas Graf }
238734ae932aSThomas Graf 
23881f30fb91SIlya Maximets static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len)
2389e6445719SPravin B Shelar {
239034ae932aSThomas Graf 	const struct nlattr *a;
239134ae932aSThomas Graf 	int rem;
ovs_nla_free_nested_actions(const struct nlattr * actions,int len)239234ae932aSThomas Graf 
23931f30fb91SIlya Maximets 	/* Whenever new actions are added, the need to update this
23941f30fb91SIlya Maximets 	 * function should be considered.
23951f30fb91SIlya Maximets 	 */
2396e7bc7db9SEric Garver 	BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 24);
23971f30fb91SIlya Maximets 
23981f30fb91SIlya Maximets 	if (!actions)
239934ae932aSThomas Graf 		return;
240034ae932aSThomas Graf 
24011f30fb91SIlya Maximets 	nla_for_each_attr(a, actions, len, rem) {
240234ae932aSThomas Graf 		switch (nla_type(a)) {
24031f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
24041f30fb91SIlya Maximets 			ovs_nla_free_check_pkt_len_action(a);
240534ae932aSThomas Graf 			break;
24061f30fb91SIlya Maximets 
24071f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_CLONE:
24081f30fb91SIlya Maximets 			ovs_nla_free_clone_action(a);
24091f30fb91SIlya Maximets 			break;
24101f30fb91SIlya Maximets 
24117f8a436eSJoe Stringer 		case OVS_ACTION_ATTR_CT:
24127f8a436eSJoe Stringer 			ovs_ct_free_action(a);
24137f8a436eSJoe Stringer 			break;
24141f30fb91SIlya Maximets 
24151f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_DEC_TTL:
24161f30fb91SIlya Maximets 			ovs_nla_free_dec_ttl_action(a);
24171f30fb91SIlya Maximets 			break;
24181f30fb91SIlya Maximets 
24191f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_SAMPLE:
24201f30fb91SIlya Maximets 			ovs_nla_free_sample_action(a);
24211f30fb91SIlya Maximets 			break;
24221f30fb91SIlya Maximets 
24231f30fb91SIlya Maximets 		case OVS_ACTION_ATTR_SET:
24241f30fb91SIlya Maximets 			ovs_nla_free_set_action(a);
24251f30fb91SIlya Maximets 			break;
24261f30fb91SIlya Maximets 		}
242734ae932aSThomas Graf 	}
242834ae932aSThomas Graf }
242934ae932aSThomas Graf 
24301f30fb91SIlya Maximets void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
24311f30fb91SIlya Maximets {
24321f30fb91SIlya Maximets 	if (!sf_acts)
24331f30fb91SIlya Maximets 		return;
ovs_nla_free_flow_actions(struct sw_flow_actions * sf_acts)24341f30fb91SIlya Maximets 
24351f30fb91SIlya Maximets 	ovs_nla_free_nested_actions(sf_acts->actions, sf_acts->actions_len);
243634ae932aSThomas Graf 	kfree(sf_acts);
243734ae932aSThomas Graf }
243834ae932aSThomas Graf 
243934ae932aSThomas Graf static void __ovs_nla_free_flow_actions(struct rcu_head *head)
244034ae932aSThomas Graf {
244134ae932aSThomas Graf 	ovs_nla_free_flow_actions(container_of(head, struct sw_flow_actions, rcu));
244234ae932aSThomas Graf }
__ovs_nla_free_flow_actions(struct rcu_head * head)244334ae932aSThomas Graf 
244434ae932aSThomas Graf /* Schedules 'sf_acts' to be freed after the next RCU grace period.
244534ae932aSThomas Graf  * The caller must hold rcu_read_lock for this to be sensible. */
244634ae932aSThomas Graf void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *sf_acts)
244734ae932aSThomas Graf {
244834ae932aSThomas Graf 	call_rcu(&sf_acts->rcu, __ovs_nla_free_flow_actions);
2449e6445719SPravin B Shelar }
ovs_nla_free_flow_actions_rcu(struct sw_flow_actions * sf_acts)2450e6445719SPravin B Shelar 
2451e6445719SPravin B Shelar static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
245205da5898SJarno Rajahalme 				       int attr_len, bool log)
2453e6445719SPravin B Shelar {
2454e6445719SPravin B Shelar 
2455e6445719SPravin B Shelar 	struct sw_flow_actions *acts;
2456e6445719SPravin B Shelar 	int new_acts_size;
2457f28cd2afSAndrea Righi 	size_t req_size = NLA_ALIGN(attr_len);
2458e6445719SPravin B Shelar 	int next_offset = offsetof(struct sw_flow_actions, actions) +
2459e6445719SPravin B Shelar 					(*sfa)->actions_len;
2460e6445719SPravin B Shelar 
2461e6445719SPravin B Shelar 	if (req_size <= (ksize(*sfa) - next_offset))
2462e6445719SPravin B Shelar 		goto out;
2463e6445719SPravin B Shelar 
2464f28cd2afSAndrea Righi 	new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
2465e6445719SPravin B Shelar 
246667c8d22aSzhangliping 	acts = nla_alloc_flow_actions(new_acts_size);
2467e6445719SPravin B Shelar 	if (IS_ERR(acts))
2468e6445719SPravin B Shelar 		return (void *)acts;
2469e6445719SPravin B Shelar 
2470e6445719SPravin B Shelar 	memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len);
2471e6445719SPravin B Shelar 	acts->actions_len = (*sfa)->actions_len;
24728e2fed1cSJoe Stringer 	acts->orig_len = (*sfa)->orig_len;
2473e6445719SPravin B Shelar 	kfree(*sfa);
2474e6445719SPravin B Shelar 	*sfa = acts;
2475e6445719SPravin B Shelar 
2476e6445719SPravin B Shelar out:
2477e6445719SPravin B Shelar 	(*sfa)->actions_len += req_size;
2478e6445719SPravin B Shelar 	return  (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
2479e6445719SPravin B Shelar }
2480e6445719SPravin B Shelar 
2481f0b128c1SJesse Gross static struct nlattr *__add_action(struct sw_flow_actions **sfa,
248205da5898SJarno Rajahalme 				   int attrtype, void *data, int len, bool log)
2483e6445719SPravin B Shelar {
2484e6445719SPravin B Shelar 	struct nlattr *a;
2485e6445719SPravin B Shelar 
248605da5898SJarno Rajahalme 	a = reserve_sfa_size(sfa, nla_attr_size(len), log);
2487e6445719SPravin B Shelar 	if (IS_ERR(a))
2488f0b128c1SJesse Gross 		return a;
2489e6445719SPravin B Shelar 
2490e6445719SPravin B Shelar 	a->nla_type = attrtype;
2491e6445719SPravin B Shelar 	a->nla_len = nla_attr_size(len);
2492e6445719SPravin B Shelar 
2493e6445719SPravin B Shelar 	if (data)
__add_action(struct sw_flow_actions ** sfa,int attrtype,void * data,int len,bool log)2494e6445719SPravin B Shelar 		memcpy(nla_data(a), data, len);
2495e6445719SPravin B Shelar 	memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));
2496e6445719SPravin B Shelar 
2497f0b128c1SJesse Gross 	return a;
2498f0b128c1SJesse Gross }
2499f0b128c1SJesse Gross 
25007f8a436eSJoe Stringer int ovs_nla_add_action(struct sw_flow_actions **sfa, int attrtype, void *data,
25017f8a436eSJoe Stringer 		       int len, bool log)
2502f0b128c1SJesse Gross {
2503f0b128c1SJesse Gross 	struct nlattr *a;
2504f0b128c1SJesse Gross 
250505da5898SJarno Rajahalme 	a = __add_action(sfa, attrtype, data, len, log);
2506f0b128c1SJesse Gross 
2507f35423c1SFabian Frederick 	return PTR_ERR_OR_ZERO(a);
2508e6445719SPravin B Shelar }
2509e6445719SPravin B Shelar 
2510e6445719SPravin B Shelar static inline int add_nested_action_start(struct sw_flow_actions **sfa,
251105da5898SJarno Rajahalme 					  int attrtype, bool log)
2512e6445719SPravin B Shelar {
ovs_nla_add_action(struct sw_flow_actions ** sfa,int attrtype,void * data,int len,bool log)2513e6445719SPravin B Shelar 	int used = (*sfa)->actions_len;
2514e6445719SPravin B Shelar 	int err;
2515e6445719SPravin B Shelar 
25167f8a436eSJoe Stringer 	err = ovs_nla_add_action(sfa, attrtype, NULL, 0, log);
2517e6445719SPravin B Shelar 	if (err)
2518e6445719SPravin B Shelar 		return err;
2519e6445719SPravin B Shelar 
2520e6445719SPravin B Shelar 	return used;
2521e6445719SPravin B Shelar }
2522e6445719SPravin B Shelar 
add_nested_action_start(struct sw_flow_actions ** sfa,int attrtype,bool log)2523e6445719SPravin B Shelar static inline void add_nested_action_end(struct sw_flow_actions *sfa,
2524e6445719SPravin B Shelar 					 int st_offset)
2525e6445719SPravin B Shelar {
2526e6445719SPravin B Shelar 	struct nlattr *a = (struct nlattr *) ((unsigned char *)sfa->actions +
2527e6445719SPravin B Shelar 							       st_offset);
2528e6445719SPravin B Shelar 
2529e6445719SPravin B Shelar 	a->nla_len = sfa->actions_len - st_offset;
2530e6445719SPravin B Shelar }
2531e6445719SPravin B Shelar 
25327f8a436eSJoe Stringer static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
253325cd9ba0SSimon Horman 				  const struct sw_flow_key *key,
2534798c1661Sandy zhou 				  struct sw_flow_actions **sfa,
2535fbdcdd78SMartin Varghese 				  __be16 eth_type, __be16 vlan_tci,
add_nested_action_end(struct sw_flow_actions * sfa,int st_offset)25365eeb2a9eSAaron Conole 				  u32 mpls_label_count, bool log,
25375eeb2a9eSAaron Conole 				  u32 depth);
253825cd9ba0SSimon Horman 
25397f8a436eSJoe Stringer static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
2540798c1661Sandy zhou 				    const struct sw_flow_key *key,
254125cd9ba0SSimon Horman 				    struct sw_flow_actions **sfa,
2542798c1661Sandy zhou 				    __be16 eth_type, __be16 vlan_tci,
25435eeb2a9eSAaron Conole 				    u32 mpls_label_count, bool log, bool last,
25445eeb2a9eSAaron Conole 				    u32 depth)
2545e6445719SPravin B Shelar {
2546e6445719SPravin B Shelar 	const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
2547e6445719SPravin B Shelar 	const struct nlattr *probability, *actions;
2548e6445719SPravin B Shelar 	const struct nlattr *a;
2549798c1661Sandy zhou 	int rem, start, err;
2550798c1661Sandy zhou 	struct sample_arg arg;
2551e6445719SPravin B Shelar 
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)2552e6445719SPravin B Shelar 	memset(attrs, 0, sizeof(attrs));
2553e6445719SPravin B Shelar 	nla_for_each_nested(a, attr, rem) {
2554e6445719SPravin B Shelar 		int type = nla_type(a);
2555e6445719SPravin B Shelar 		if (!type || type > OVS_SAMPLE_ATTR_MAX || attrs[type])
2556e6445719SPravin B Shelar 			return -EINVAL;
2557e6445719SPravin B Shelar 		attrs[type] = a;
2558e6445719SPravin B Shelar 	}
2559e6445719SPravin B Shelar 	if (rem)
2560e6445719SPravin B Shelar 		return -EINVAL;
2561e6445719SPravin B Shelar 
2562e6445719SPravin B Shelar 	probability = attrs[OVS_SAMPLE_ATTR_PROBABILITY];
2563e6445719SPravin B Shelar 	if (!probability || nla_len(probability) != sizeof(u32))
2564e6445719SPravin B Shelar 		return -EINVAL;
2565e6445719SPravin B Shelar 
2566e6445719SPravin B Shelar 	actions = attrs[OVS_SAMPLE_ATTR_ACTIONS];
2567e6445719SPravin B Shelar 	if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
2568e6445719SPravin B Shelar 		return -EINVAL;
2569e6445719SPravin B Shelar 
2570e6445719SPravin B Shelar 	/* validation done, copy sample action. */
257105da5898SJarno Rajahalme 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE, log);
2572e6445719SPravin B Shelar 	if (start < 0)
2573e6445719SPravin B Shelar 		return start;
2574798c1661Sandy zhou 
2575798c1661Sandy zhou 	/* When both skb and flow may be changed, put the sample
2576798c1661Sandy zhou 	 * into a deferred fifo. On the other hand, if only skb
2577798c1661Sandy zhou 	 * may be modified, the actions can be executed in place.
2578798c1661Sandy zhou 	 *
2579798c1661Sandy zhou 	 * Do this analysis at the flow installation time.
2580798c1661Sandy zhou 	 * Set 'clone_action->exec' to true if the actions can be
2581798c1661Sandy zhou 	 * executed without being deferred.
2582798c1661Sandy zhou 	 *
2583798c1661Sandy zhou 	 * If the sample is the last action, it can always be excuted
2584798c1661Sandy zhou 	 * rather than deferred.
2585798c1661Sandy zhou 	 */
2586798c1661Sandy zhou 	arg.exec = last || !actions_may_change_flow(actions);
2587798c1661Sandy zhou 	arg.probability = nla_get_u32(probability);
2588798c1661Sandy zhou 
2589798c1661Sandy zhou 	err = ovs_nla_add_action(sfa, OVS_SAMPLE_ATTR_ARG, &arg, sizeof(arg),
2590798c1661Sandy zhou 				 log);
2591e6445719SPravin B Shelar 	if (err)
2592e6445719SPravin B Shelar 		return err;
2593e6445719SPravin B Shelar 
2594798c1661Sandy zhou 	err = __ovs_nla_copy_actions(net, actions, key, sfa,
25955eeb2a9eSAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
25965eeb2a9eSAaron Conole 				     depth + 1);
2597798c1661Sandy zhou 
2598e6445719SPravin B Shelar 	if (err)
2599e6445719SPravin B Shelar 		return err;
2600e6445719SPravin B Shelar 
2601e6445719SPravin B Shelar 	add_nested_action_end(*sfa, start);
2602e6445719SPravin B Shelar 
2603e6445719SPravin B Shelar 	return 0;
2604e6445719SPravin B Shelar }
2605e6445719SPravin B Shelar 
2606744676e7SMatteo Croce static int validate_and_copy_dec_ttl(struct net *net,
2607744676e7SMatteo Croce 				     const struct nlattr *attr,
2608744676e7SMatteo Croce 				     const struct sw_flow_key *key,
2609744676e7SMatteo Croce 				     struct sw_flow_actions **sfa,
2610744676e7SMatteo Croce 				     __be16 eth_type, __be16 vlan_tci,
26115eeb2a9eSAaron Conole 				     u32 mpls_label_count, bool log,
26125eeb2a9eSAaron Conole 				     u32 depth)
2613744676e7SMatteo Croce {
261469929d4cSEelco Chaudron 	const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1];
261569929d4cSEelco Chaudron 	int start, action_start, err, rem;
261669929d4cSEelco Chaudron 	const struct nlattr *a, *actions;
2617744676e7SMatteo Croce 
261869929d4cSEelco Chaudron 	memset(attrs, 0, sizeof(attrs));
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)261969929d4cSEelco Chaudron 	nla_for_each_nested(a, attr, rem) {
262069929d4cSEelco Chaudron 		int type = nla_type(a);
262169929d4cSEelco Chaudron 
262269929d4cSEelco Chaudron 		/* Ignore unknown attributes to be future proof. */
262369929d4cSEelco Chaudron 		if (type > OVS_DEC_TTL_ATTR_MAX)
262469929d4cSEelco Chaudron 			continue;
262569929d4cSEelco Chaudron 
2626a5317f3bSEelco Chaudron 		if (!type || attrs[type]) {
2627a5317f3bSEelco Chaudron 			OVS_NLERR(log, "Duplicate or invalid key (type %d).",
2628a5317f3bSEelco Chaudron 				  type);
262969929d4cSEelco Chaudron 			return -EINVAL;
2630a5317f3bSEelco Chaudron 		}
263169929d4cSEelco Chaudron 
263269929d4cSEelco Chaudron 		attrs[type] = a;
263369929d4cSEelco Chaudron 	}
263469929d4cSEelco Chaudron 
2635a5317f3bSEelco Chaudron 	if (rem) {
2636a5317f3bSEelco Chaudron 		OVS_NLERR(log, "Message has %d unknown bytes.", rem);
263769929d4cSEelco Chaudron 		return -EINVAL;
2638a5317f3bSEelco Chaudron 	}
2639a5317f3bSEelco Chaudron 
2640a5317f3bSEelco Chaudron 	actions = attrs[OVS_DEC_TTL_ATTR_ACTION];
2641a5317f3bSEelco Chaudron 	if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN)) {
2642a5317f3bSEelco Chaudron 		OVS_NLERR(log, "Missing valid actions attribute.");
2643a5317f3bSEelco Chaudron 		return -EINVAL;
2644a5317f3bSEelco Chaudron 	}
2645744676e7SMatteo Croce 
2646744676e7SMatteo Croce 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log);
2647744676e7SMatteo Croce 	if (start < 0)
2648744676e7SMatteo Croce 		return start;
2649744676e7SMatteo Croce 
265069929d4cSEelco Chaudron 	action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log);
265169929d4cSEelco Chaudron 	if (action_start < 0)
2652bb2da765SWang Hai 		return action_start;
2653744676e7SMatteo Croce 
265469929d4cSEelco Chaudron 	err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
26555eeb2a9eSAaron Conole 				     vlan_tci, mpls_label_count, log,
26565eeb2a9eSAaron Conole 				     depth + 1);
2657744676e7SMatteo Croce 	if (err)
2658744676e7SMatteo Croce 		return err;
2659744676e7SMatteo Croce 
266069929d4cSEelco Chaudron 	add_nested_action_end(*sfa, action_start);
2661744676e7SMatteo Croce 	add_nested_action_end(*sfa, start);
2662744676e7SMatteo Croce 	return 0;
2663744676e7SMatteo Croce }
2664744676e7SMatteo Croce 
2665b2335040SYifeng Sun static int validate_and_copy_clone(struct net *net,
2666b2335040SYifeng Sun 				   const struct nlattr *attr,
2667b2335040SYifeng Sun 				   const struct sw_flow_key *key,
2668b2335040SYifeng Sun 				   struct sw_flow_actions **sfa,
2669b2335040SYifeng Sun 				   __be16 eth_type, __be16 vlan_tci,
26705eeb2a9eSAaron Conole 				   u32 mpls_label_count, bool log, bool last,
26715eeb2a9eSAaron Conole 				   u32 depth)
2672b2335040SYifeng Sun {
2673b2335040SYifeng Sun 	int start, err;
2674b2335040SYifeng Sun 	u32 exec;
2675b2335040SYifeng Sun 
2676b2335040SYifeng Sun 	if (nla_len(attr) && nla_len(attr) < NLA_HDRLEN)
2677b2335040SYifeng Sun 		return -EINVAL;
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)2678b2335040SYifeng Sun 
2679b2335040SYifeng Sun 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CLONE, log);
2680b2335040SYifeng Sun 	if (start < 0)
2681b2335040SYifeng Sun 		return start;
2682b2335040SYifeng Sun 
2683b2335040SYifeng Sun 	exec = last || !actions_may_change_flow(attr);
2684b2335040SYifeng Sun 
2685b2335040SYifeng Sun 	err = ovs_nla_add_action(sfa, OVS_CLONE_ATTR_EXEC, &exec,
2686b2335040SYifeng Sun 				 sizeof(exec), log);
2687b2335040SYifeng Sun 	if (err)
2688b2335040SYifeng Sun 		return err;
2689b2335040SYifeng Sun 
2690b2335040SYifeng Sun 	err = __ovs_nla_copy_actions(net, attr, key, sfa,
26915eeb2a9eSAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
26925eeb2a9eSAaron Conole 				     depth + 1);
2693b2335040SYifeng Sun 	if (err)
2694b2335040SYifeng Sun 		return err;
2695b2335040SYifeng Sun 
2696b2335040SYifeng Sun 	add_nested_action_end(*sfa, start);
2697b2335040SYifeng Sun 
2698b2335040SYifeng Sun 	return 0;
2699b2335040SYifeng Sun }
2700b2335040SYifeng Sun 
2701e6445719SPravin B Shelar void ovs_match_init(struct sw_flow_match *match,
2702e6445719SPravin B Shelar 		    struct sw_flow_key *key,
27032279994dSpravin shelar 		    bool reset_key,
2704e6445719SPravin B Shelar 		    struct sw_flow_mask *mask)
2705e6445719SPravin B Shelar {
2706e6445719SPravin B Shelar 	memset(match, 0, sizeof(*match));
2707e6445719SPravin B Shelar 	match->key = key;
2708e6445719SPravin B Shelar 	match->mask = mask;
2709e6445719SPravin B Shelar 
27102279994dSpravin shelar 	if (reset_key)
2711e6445719SPravin B Shelar 		memset(key, 0, sizeof(*key));
2712e6445719SPravin B Shelar 
2713e6445719SPravin B Shelar 	if (mask) {
ovs_match_init(struct sw_flow_match * match,struct sw_flow_key * key,bool reset_key,struct sw_flow_mask * mask)2714e6445719SPravin B Shelar 		memset(&mask->key, 0, sizeof(mask->key));
2715e6445719SPravin B Shelar 		mask->range.start = mask->range.end = 0;
2716e6445719SPravin B Shelar 	}
2717e6445719SPravin B Shelar }
2718e6445719SPravin B Shelar 
2719d91641d9SThomas Graf static int validate_geneve_opts(struct sw_flow_key *key)
2720e6445719SPravin B Shelar {
2721d91641d9SThomas Graf 	struct geneve_opt *option;
2722d91641d9SThomas Graf 	int opts_len = key->tun_opts_len;
2723f5796684SJesse Gross 	bool crit_opt = false;
2724f5796684SJesse Gross 
2725d91641d9SThomas Graf 	option = (struct geneve_opt *)TUN_METADATA_OPTS(key, key->tun_opts_len);
2726f5796684SJesse Gross 	while (opts_len > 0) {
2727f5796684SJesse Gross 		int len;
2728f5796684SJesse Gross 
2729f5796684SJesse Gross 		if (opts_len < sizeof(*option))
2730f5796684SJesse Gross 			return -EINVAL;
2731f5796684SJesse Gross 
validate_geneve_opts(struct sw_flow_key * key)2732f5796684SJesse Gross 		len = sizeof(*option) + option->length * 4;
2733f5796684SJesse Gross 		if (len > opts_len)
2734f5796684SJesse Gross 			return -EINVAL;
2735f5796684SJesse Gross 
2736f5796684SJesse Gross 		crit_opt |= !!(option->type & GENEVE_CRIT_OPT_TYPE);
2737f5796684SJesse Gross 
2738f5796684SJesse Gross 		option = (struct geneve_opt *)((u8 *)option + len);
2739f5796684SJesse Gross 		opts_len -= len;
274089290b83SChristopher Díaz Riveros 	}
2741f5796684SJesse Gross 
2742d91641d9SThomas Graf 	key->tun_key.tun_flags |= crit_opt ? TUNNEL_CRIT_OPT : 0;
2743d91641d9SThomas Graf 
2744d91641d9SThomas Graf 	return 0;
2745d91641d9SThomas Graf }
2746d91641d9SThomas Graf 
2747d91641d9SThomas Graf static int validate_and_copy_set_tun(const struct nlattr *attr,
2748d91641d9SThomas Graf 				     struct sw_flow_actions **sfa, bool log)
2749d91641d9SThomas Graf {
2750d91641d9SThomas Graf 	struct sw_flow_match match;
2751d91641d9SThomas Graf 	struct sw_flow_key key;
275234ae932aSThomas Graf 	struct metadata_dst *tun_dst;
27531d8fff90SThomas Graf 	struct ip_tunnel_info *tun_info;
275434ae932aSThomas Graf 	struct ovs_tunnel_info *ovs_tun;
2755d91641d9SThomas Graf 	struct nlattr *a;
275613101602SGeert Uytterhoeven 	int err = 0, start, opts_type;
2757256c87c1SPieter Jansen van Vuuren 	__be16 dst_opt_type;
2758d91641d9SThomas Graf 
2759256c87c1SPieter Jansen van Vuuren 	dst_opt_type = 0;
validate_and_copy_set_tun(const struct nlattr * attr,struct sw_flow_actions ** sfa,bool log)27602279994dSpravin shelar 	ovs_match_init(&match, &key, true, NULL);
27616b26ba3aSJiri Benc 	opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
27621dd144cfSThomas Graf 	if (opts_type < 0)
27631dd144cfSThomas Graf 		return opts_type;
2764d91641d9SThomas Graf 
2765d91641d9SThomas Graf 	if (key.tun_opts_len) {
27661dd144cfSThomas Graf 		switch (opts_type) {
27671dd144cfSThomas Graf 		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
2768d91641d9SThomas Graf 			err = validate_geneve_opts(&key);
2769d91641d9SThomas Graf 			if (err < 0)
2770d91641d9SThomas Graf 				return err;
2771256c87c1SPieter Jansen van Vuuren 			dst_opt_type = TUNNEL_GENEVE_OPT;
27721dd144cfSThomas Graf 			break;
27731dd144cfSThomas Graf 		case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
2774256c87c1SPieter Jansen van Vuuren 			dst_opt_type = TUNNEL_VXLAN_OPT;
27751dd144cfSThomas Graf 			break;
2776fc1372f8SWilliam Tu 		case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS:
2777256c87c1SPieter Jansen van Vuuren 			dst_opt_type = TUNNEL_ERSPAN_OPT;
2778fc1372f8SWilliam Tu 			break;
27791dd144cfSThomas Graf 		}
278089290b83SChristopher Díaz Riveros 	}
2781f5796684SJesse Gross 
278205da5898SJarno Rajahalme 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET, log);
2783e6445719SPravin B Shelar 	if (start < 0)
2784e6445719SPravin B Shelar 		return start;
2785e6445719SPravin B Shelar 
27863fcece12SJakub Kicinski 	tun_dst = metadata_dst_alloc(key.tun_opts_len, METADATA_IP_TUNNEL,
27873fcece12SJakub Kicinski 				     GFP_KERNEL);
27883fcece12SJakub Kicinski 
278934ae932aSThomas Graf 	if (!tun_dst)
279034ae932aSThomas Graf 		return -ENOMEM;
2791f0b128c1SJesse Gross 
2792d71785ffSPaolo Abeni 	err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
2793d71785ffSPaolo Abeni 	if (err) {
2794d71785ffSPaolo Abeni 		dst_release((struct dst_entry *)tun_dst);
2795d71785ffSPaolo Abeni 		return err;
2796d71785ffSPaolo Abeni 	}
2797d71785ffSPaolo Abeni 
279834ae932aSThomas Graf 	a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
279934ae932aSThomas Graf 			 sizeof(*ovs_tun), log);
280034ae932aSThomas Graf 	if (IS_ERR(a)) {
280134ae932aSThomas Graf 		dst_release((struct dst_entry *)tun_dst);
280234ae932aSThomas Graf 		return PTR_ERR(a);
280334ae932aSThomas Graf 	}
280434ae932aSThomas Graf 
280534ae932aSThomas Graf 	ovs_tun = nla_data(a);
280634ae932aSThomas Graf 	ovs_tun->tun_dst = tun_dst;
280734ae932aSThomas Graf 
280834ae932aSThomas Graf 	tun_info = &tun_dst->u.tun_info;
280934ae932aSThomas Graf 	tun_info->mode = IP_TUNNEL_INFO_TX;
281000a93babSJiri Benc 	if (key.tun_proto == AF_INET6)
281100a93babSJiri Benc 		tun_info->mode |= IP_TUNNEL_INFO_IPV6;
281218b6f717Swenxu 	else if (key.tun_proto == AF_INET && key.tun_key.u.ipv4.dst == 0)
281318b6f717Swenxu 		tun_info->mode |= IP_TUNNEL_INFO_BRIDGE;
28141d8fff90SThomas Graf 	tun_info->key = key.tun_key;
2815f5796684SJesse Gross 
2816f5796684SJesse Gross 	/* We need to store the options in the action itself since
2817f5796684SJesse Gross 	 * everything else will go away after flow setup. We can append
2818f5796684SJesse Gross 	 * it to tun_info and then point there.
2819f5796684SJesse Gross 	 */
28204c222798SPravin B Shelar 	ip_tunnel_info_opts_set(tun_info,
28214c222798SPravin B Shelar 				TUN_METADATA_OPTS(&key, key.tun_opts_len),
2822256c87c1SPieter Jansen van Vuuren 				key.tun_opts_len, dst_opt_type);
2823e6445719SPravin B Shelar 	add_nested_action_end(*sfa, start);
2824e6445719SPravin B Shelar 
2825e6445719SPravin B Shelar 	return err;
2826e6445719SPravin B Shelar }
2827e6445719SPravin B Shelar 
2828b2d0f5d5SYi Yang static bool validate_nsh(const struct nlattr *attr, bool is_mask,
2829b2d0f5d5SYi Yang 			 bool is_push_nsh, bool log)
2830b2d0f5d5SYi Yang {
2831b2d0f5d5SYi Yang 	struct sw_flow_match match;
2832b2d0f5d5SYi Yang 	struct sw_flow_key key;
2833b2d0f5d5SYi Yang 	int ret = 0;
2834b2d0f5d5SYi Yang 
2835b2d0f5d5SYi Yang 	ovs_match_init(&match, &key, true, NULL);
2836b2d0f5d5SYi Yang 	ret = nsh_key_put_from_nlattr(attr, &match, is_mask,
2837b2d0f5d5SYi Yang 				      is_push_nsh, log);
2838b2d0f5d5SYi Yang 	return !ret;
2839b2d0f5d5SYi Yang }
2840b2d0f5d5SYi Yang 
validate_nsh(const struct nlattr * attr,bool is_mask,bool is_push_nsh,bool log)284183d2b9baSJarno Rajahalme /* Return false if there are any non-masked bits set.
284283d2b9baSJarno Rajahalme  * Mask follows data immediately, before any netlink padding.
284383d2b9baSJarno Rajahalme  */
284483d2b9baSJarno Rajahalme static bool validate_masked(u8 *data, int len)
284583d2b9baSJarno Rajahalme {
284683d2b9baSJarno Rajahalme 	u8 *mask = data + len;
284783d2b9baSJarno Rajahalme 
284883d2b9baSJarno Rajahalme 	while (len--)
284983d2b9baSJarno Rajahalme 		if (*data++ & ~*mask++)
285083d2b9baSJarno Rajahalme 			return false;
285183d2b9baSJarno Rajahalme 
285283d2b9baSJarno Rajahalme 	return true;
285383d2b9baSJarno Rajahalme }
285483d2b9baSJarno Rajahalme 
2855e6445719SPravin B Shelar static int validate_set(const struct nlattr *a,
2856e6445719SPravin B Shelar 			const struct sw_flow_key *flow_key,
validate_masked(u8 * data,int len)28570a6410fbSJiri Benc 			struct sw_flow_actions **sfa, bool *skip_copy,
28580a6410fbSJiri Benc 			u8 mac_proto, __be16 eth_type, bool masked, bool log)
2859e6445719SPravin B Shelar {
2860e6445719SPravin B Shelar 	const struct nlattr *ovs_key = nla_data(a);
2861e6445719SPravin B Shelar 	int key_type = nla_type(ovs_key);
286283d2b9baSJarno Rajahalme 	size_t key_len;
2863e6445719SPravin B Shelar 
2864e6445719SPravin B Shelar 	/* There can be only one key in a action */
2865e6445719SPravin B Shelar 	if (nla_total_size(nla_len(ovs_key)) != nla_len(a))
2866e6445719SPravin B Shelar 		return -EINVAL;
2867e6445719SPravin B Shelar 
286883d2b9baSJarno Rajahalme 	key_len = nla_len(ovs_key);
286983d2b9baSJarno Rajahalme 	if (masked)
287083d2b9baSJarno Rajahalme 		key_len /= 2;
287183d2b9baSJarno Rajahalme 
2872e6445719SPravin B Shelar 	if (key_type > OVS_KEY_ATTR_MAX ||
2873982b5270SJesse Gross 	    !check_attr_len(key_len, ovs_key_lens[key_type].len))
2874e6445719SPravin B Shelar 		return -EINVAL;
2875e6445719SPravin B Shelar 
287683d2b9baSJarno Rajahalme 	if (masked && !validate_masked(nla_data(ovs_key), key_len))
287783d2b9baSJarno Rajahalme 		return -EINVAL;
287883d2b9baSJarno Rajahalme 
2879e6445719SPravin B Shelar 	switch (key_type) {
2880e6445719SPravin B Shelar 	case OVS_KEY_ATTR_PRIORITY:
2881e6445719SPravin B Shelar 	case OVS_KEY_ATTR_SKB_MARK:
2882182e3042SJoe Stringer 	case OVS_KEY_ATTR_CT_MARK:
288333db4125SJoe Stringer 	case OVS_KEY_ATTR_CT_LABELS:
2884e6445719SPravin B Shelar 		break;
2885e6445719SPravin B Shelar 
28860a6410fbSJiri Benc 	case OVS_KEY_ATTR_ETHERNET:
28870a6410fbSJiri Benc 		if (mac_proto != MAC_PROTO_ETHERNET)
28880a6410fbSJiri Benc 			return -EINVAL;
288987e159c5SJarno Rajahalme 		break;
28900a6410fbSJiri Benc 
289116a556eeSKees Cook 	case OVS_KEY_ATTR_TUNNEL: {
289216a556eeSKees Cook 		int err;
289316a556eeSKees Cook 
289483d2b9baSJarno Rajahalme 		if (masked)
289583d2b9baSJarno Rajahalme 			return -EINVAL; /* Masked tunnel set not supported. */
289683d2b9baSJarno Rajahalme 
289783d2b9baSJarno Rajahalme 		*skip_copy = true;
289805da5898SJarno Rajahalme 		err = validate_and_copy_set_tun(a, sfa, log);
2899e6445719SPravin B Shelar 		if (err)
2900e6445719SPravin B Shelar 			return err;
2901e6445719SPravin B Shelar 		break;
290216a556eeSKees Cook 	}
290316a556eeSKees Cook 	case OVS_KEY_ATTR_IPV4: {
290416a556eeSKees Cook 		const struct ovs_key_ipv4 *ipv4_key;
2905e6445719SPravin B Shelar 
290625cd9ba0SSimon Horman 		if (eth_type != htons(ETH_P_IP))
2907e6445719SPravin B Shelar 			return -EINVAL;
2908e6445719SPravin B Shelar 
2909e6445719SPravin B Shelar 		ipv4_key = nla_data(ovs_key);
291083d2b9baSJarno Rajahalme 
291183d2b9baSJarno Rajahalme 		if (masked) {
291283d2b9baSJarno Rajahalme 			const struct ovs_key_ipv4 *mask = ipv4_key + 1;
291383d2b9baSJarno Rajahalme 
291483d2b9baSJarno Rajahalme 			/* Non-writeable fields. */
291583d2b9baSJarno Rajahalme 			if (mask->ipv4_proto || mask->ipv4_frag)
291683d2b9baSJarno Rajahalme 				return -EINVAL;
291783d2b9baSJarno Rajahalme 		} else {
2918e6445719SPravin B Shelar 			if (ipv4_key->ipv4_proto != flow_key->ip.proto)
2919e6445719SPravin B Shelar 				return -EINVAL;
2920e6445719SPravin B Shelar 
2921e6445719SPravin B Shelar 			if (ipv4_key->ipv4_frag != flow_key->ip.frag)
2922e6445719SPravin B Shelar 				return -EINVAL;
292383d2b9baSJarno Rajahalme 		}
2924e6445719SPravin B Shelar 		break;
292516a556eeSKees Cook 	}
292616a556eeSKees Cook 	case OVS_KEY_ATTR_IPV6: {
292716a556eeSKees Cook 		const struct ovs_key_ipv6 *ipv6_key;
2928e6445719SPravin B Shelar 
292925cd9ba0SSimon Horman 		if (eth_type != htons(ETH_P_IPV6))
2930e6445719SPravin B Shelar 			return -EINVAL;
2931e6445719SPravin B Shelar 
293283d2b9baSJarno Rajahalme 		ipv6_key = nla_data(ovs_key);
293383d2b9baSJarno Rajahalme 
293483d2b9baSJarno Rajahalme 		if (masked) {
293583d2b9baSJarno Rajahalme 			const struct ovs_key_ipv6 *mask = ipv6_key + 1;
293683d2b9baSJarno Rajahalme 
293783d2b9baSJarno Rajahalme 			/* Non-writeable fields. */
293883d2b9baSJarno Rajahalme 			if (mask->ipv6_proto || mask->ipv6_frag)
2939e6445719SPravin B Shelar 				return -EINVAL;
2940e6445719SPravin B Shelar 
294183d2b9baSJarno Rajahalme 			/* Invalid bits in the flow label mask? */
294283d2b9baSJarno Rajahalme 			if (ntohl(mask->ipv6_label) & 0xFFF00000)
294383d2b9baSJarno Rajahalme 				return -EINVAL;
294483d2b9baSJarno Rajahalme 		} else {
2945e6445719SPravin B Shelar 			if (ipv6_key->ipv6_proto != flow_key->ip.proto)
2946e6445719SPravin B Shelar 				return -EINVAL;
2947e6445719SPravin B Shelar 
2948e6445719SPravin B Shelar 			if (ipv6_key->ipv6_frag != flow_key->ip.frag)
2949e6445719SPravin B Shelar 				return -EINVAL;
295083d2b9baSJarno Rajahalme 		}
2951e6445719SPravin B Shelar 		if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000)
2952e6445719SPravin B Shelar 			return -EINVAL;
2953e6445719SPravin B Shelar 
2954e6445719SPravin B Shelar 		break;
295516a556eeSKees Cook 	}
2956e6445719SPravin B Shelar 	case OVS_KEY_ATTR_TCP:
295783d2b9baSJarno Rajahalme 		if ((eth_type != htons(ETH_P_IP) &&
295883d2b9baSJarno Rajahalme 		     eth_type != htons(ETH_P_IPV6)) ||
295983d2b9baSJarno Rajahalme 		    flow_key->ip.proto != IPPROTO_TCP)
2960e6445719SPravin B Shelar 			return -EINVAL;
2961e6445719SPravin B Shelar 
296283d2b9baSJarno Rajahalme 		break;
2963e6445719SPravin B Shelar 
2964e6445719SPravin B Shelar 	case OVS_KEY_ATTR_UDP:
296583d2b9baSJarno Rajahalme 		if ((eth_type != htons(ETH_P_IP) &&
296683d2b9baSJarno Rajahalme 		     eth_type != htons(ETH_P_IPV6)) ||
296783d2b9baSJarno Rajahalme 		    flow_key->ip.proto != IPPROTO_UDP)
2968e6445719SPravin B Shelar 			return -EINVAL;
2969e6445719SPravin B Shelar 
297083d2b9baSJarno Rajahalme 		break;
297125cd9ba0SSimon Horman 
297225cd9ba0SSimon Horman 	case OVS_KEY_ATTR_MPLS:
297325cd9ba0SSimon Horman 		if (!eth_p_mpls(eth_type))
297425cd9ba0SSimon Horman 			return -EINVAL;
297525cd9ba0SSimon Horman 		break;
2976e6445719SPravin B Shelar 
2977e6445719SPravin B Shelar 	case OVS_KEY_ATTR_SCTP:
297883d2b9baSJarno Rajahalme 		if ((eth_type != htons(ETH_P_IP) &&
297983d2b9baSJarno Rajahalme 		     eth_type != htons(ETH_P_IPV6)) ||
298083d2b9baSJarno Rajahalme 		    flow_key->ip.proto != IPPROTO_SCTP)
2981e6445719SPravin B Shelar 			return -EINVAL;
2982e6445719SPravin B Shelar 
298383d2b9baSJarno Rajahalme 		break;
2984e6445719SPravin B Shelar 
2985b2d0f5d5SYi Yang 	case OVS_KEY_ATTR_NSH:
2986b2d0f5d5SYi Yang 		if (eth_type != htons(ETH_P_NSH))
2987b2d0f5d5SYi Yang 			return -EINVAL;
2988b2d0f5d5SYi Yang 		if (!validate_nsh(nla_data(a), masked, false, log))
2989b2d0f5d5SYi Yang 			return -EINVAL;
2990b2d0f5d5SYi Yang 		break;
2991b2d0f5d5SYi Yang 
2992e6445719SPravin B Shelar 	default:
2993e6445719SPravin B Shelar 		return -EINVAL;
2994e6445719SPravin B Shelar 	}
2995e6445719SPravin B Shelar 
299683d2b9baSJarno Rajahalme 	/* Convert non-masked non-tunnel set actions to masked set actions. */
299783d2b9baSJarno Rajahalme 	if (!masked && key_type != OVS_KEY_ATTR_TUNNEL) {
299883d2b9baSJarno Rajahalme 		int start, len = key_len * 2;
299983d2b9baSJarno Rajahalme 		struct nlattr *at;
300083d2b9baSJarno Rajahalme 
300183d2b9baSJarno Rajahalme 		*skip_copy = true;
300283d2b9baSJarno Rajahalme 
300383d2b9baSJarno Rajahalme 		start = add_nested_action_start(sfa,
300483d2b9baSJarno Rajahalme 						OVS_ACTION_ATTR_SET_TO_MASKED,
300583d2b9baSJarno Rajahalme 						log);
300683d2b9baSJarno Rajahalme 		if (start < 0)
300783d2b9baSJarno Rajahalme 			return start;
300883d2b9baSJarno Rajahalme 
300983d2b9baSJarno Rajahalme 		at = __add_action(sfa, key_type, NULL, len, log);
301083d2b9baSJarno Rajahalme 		if (IS_ERR(at))
301183d2b9baSJarno Rajahalme 			return PTR_ERR(at);
301283d2b9baSJarno Rajahalme 
301383d2b9baSJarno Rajahalme 		memcpy(nla_data(at), nla_data(ovs_key), key_len); /* Key. */
301483d2b9baSJarno Rajahalme 		memset(nla_data(at) + key_len, 0xff, key_len);    /* Mask. */
301583d2b9baSJarno Rajahalme 		/* Clear non-writeable bits from otherwise writeable fields. */
301683d2b9baSJarno Rajahalme 		if (key_type == OVS_KEY_ATTR_IPV6) {
301783d2b9baSJarno Rajahalme 			struct ovs_key_ipv6 *mask = nla_data(at) + key_len;
301883d2b9baSJarno Rajahalme 
301983d2b9baSJarno Rajahalme 			mask->ipv6_label &= htonl(0x000FFFFF);
302083d2b9baSJarno Rajahalme 		}
302183d2b9baSJarno Rajahalme 		add_nested_action_end(*sfa, start);
302283d2b9baSJarno Rajahalme 	}
302383d2b9baSJarno Rajahalme 
3024e6445719SPravin B Shelar 	return 0;
3025e6445719SPravin B Shelar }
3026e6445719SPravin B Shelar 
3027e6445719SPravin B Shelar static int validate_userspace(const struct nlattr *attr)
3028e6445719SPravin B Shelar {
3029e6445719SPravin B Shelar 	static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = {
3030e6445719SPravin B Shelar 		[OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
3031e6445719SPravin B Shelar 		[OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
30328f0aad6fSWenyu Zhang 		[OVS_USERSPACE_ATTR_EGRESS_TUN_PORT] = {.type = NLA_U32 },
3033e6445719SPravin B Shelar 	};
3034e6445719SPravin B Shelar 	struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
3035e6445719SPravin B Shelar 	int error;
3036e6445719SPravin B Shelar 
30378cb08174SJohannes Berg 	error = nla_parse_nested_deprecated(a, OVS_USERSPACE_ATTR_MAX, attr,
3038fceb6435SJohannes Berg 					    userspace_policy, NULL);
3039e6445719SPravin B Shelar 	if (error)
validate_userspace(const struct nlattr * attr)3040e6445719SPravin B Shelar 		return error;
3041e6445719SPravin B Shelar 
3042e6445719SPravin B Shelar 	if (!a[OVS_USERSPACE_ATTR_PID] ||
3043e6445719SPravin B Shelar 	    !nla_get_u32(a[OVS_USERSPACE_ATTR_PID]))
3044e6445719SPravin B Shelar 		return -EINVAL;
3045e6445719SPravin B Shelar 
3046e6445719SPravin B Shelar 	return 0;
3047e6445719SPravin B Shelar }
3048e6445719SPravin B Shelar 
30494d5ec89fSNuman Siddique static const struct nla_policy cpl_policy[OVS_CHECK_PKT_LEN_ATTR_MAX + 1] = {
30504d5ec89fSNuman Siddique 	[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] = {.type = NLA_U16 },
30514d5ec89fSNuman Siddique 	[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER] = {.type = NLA_NESTED },
30524d5ec89fSNuman Siddique 	[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL] = {.type = NLA_NESTED },
30534d5ec89fSNuman Siddique };
30544d5ec89fSNuman Siddique 
30554d5ec89fSNuman Siddique static int validate_and_copy_check_pkt_len(struct net *net,
30564d5ec89fSNuman Siddique 					   const struct nlattr *attr,
30574d5ec89fSNuman Siddique 					   const struct sw_flow_key *key,
30584d5ec89fSNuman Siddique 					   struct sw_flow_actions **sfa,
30594d5ec89fSNuman Siddique 					   __be16 eth_type, __be16 vlan_tci,
3060fbdcdd78SMartin Varghese 					   u32 mpls_label_count,
30615eeb2a9eSAaron Conole 					   bool log, bool last, u32 depth)
30624d5ec89fSNuman Siddique {
30634d5ec89fSNuman Siddique 	const struct nlattr *acts_if_greater, *acts_if_lesser_eq;
30644d5ec89fSNuman Siddique 	struct nlattr *a[OVS_CHECK_PKT_LEN_ATTR_MAX + 1];
30654d5ec89fSNuman Siddique 	struct check_pkt_len_arg arg;
30664d5ec89fSNuman Siddique 	int nested_acts_start;
30674d5ec89fSNuman Siddique 	int start, err;
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)30684d5ec89fSNuman Siddique 
30698cb08174SJohannes Berg 	err = nla_parse_deprecated_strict(a, OVS_CHECK_PKT_LEN_ATTR_MAX,
30708cb08174SJohannes Berg 					  nla_data(attr), nla_len(attr),
30718cb08174SJohannes Berg 					  cpl_policy, NULL);
30724d5ec89fSNuman Siddique 	if (err)
30734d5ec89fSNuman Siddique 		return err;
30744d5ec89fSNuman Siddique 
30754d5ec89fSNuman Siddique 	if (!a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] ||
30764d5ec89fSNuman Siddique 	    !nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]))
30774d5ec89fSNuman Siddique 		return -EINVAL;
30784d5ec89fSNuman Siddique 
30794d5ec89fSNuman Siddique 	acts_if_lesser_eq = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL];
30804d5ec89fSNuman Siddique 	acts_if_greater = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER];
30814d5ec89fSNuman Siddique 
30824d5ec89fSNuman Siddique 	/* Both the nested action should be present. */
30834d5ec89fSNuman Siddique 	if (!acts_if_greater || !acts_if_lesser_eq)
30844d5ec89fSNuman Siddique 		return -EINVAL;
30854d5ec89fSNuman Siddique 
30864d5ec89fSNuman Siddique 	/* validation done, copy the nested actions. */
30874d5ec89fSNuman Siddique 	start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CHECK_PKT_LEN,
30884d5ec89fSNuman Siddique 					log);
30894d5ec89fSNuman Siddique 	if (start < 0)
30904d5ec89fSNuman Siddique 		return start;
30914d5ec89fSNuman Siddique 
30924d5ec89fSNuman Siddique 	arg.pkt_len = nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]);
30934d5ec89fSNuman Siddique 	arg.exec_for_lesser_equal =
30944d5ec89fSNuman Siddique 		last || !actions_may_change_flow(acts_if_lesser_eq);
30954d5ec89fSNuman Siddique 	arg.exec_for_greater =
30964d5ec89fSNuman Siddique 		last || !actions_may_change_flow(acts_if_greater);
30974d5ec89fSNuman Siddique 
30984d5ec89fSNuman Siddique 	err = ovs_nla_add_action(sfa, OVS_CHECK_PKT_LEN_ATTR_ARG, &arg,
30994d5ec89fSNuman Siddique 				 sizeof(arg), log);
31004d5ec89fSNuman Siddique 	if (err)
31014d5ec89fSNuman Siddique 		return err;
31024d5ec89fSNuman Siddique 
31034d5ec89fSNuman Siddique 	nested_acts_start = add_nested_action_start(sfa,
31044d5ec89fSNuman Siddique 		OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL, log);
31054d5ec89fSNuman Siddique 	if (nested_acts_start < 0)
31064d5ec89fSNuman Siddique 		return nested_acts_start;
31074d5ec89fSNuman Siddique 
31084d5ec89fSNuman Siddique 	err = __ovs_nla_copy_actions(net, acts_if_lesser_eq, key, sfa,
31095eeb2a9eSAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
31105eeb2a9eSAaron Conole 				     depth + 1);
31114d5ec89fSNuman Siddique 
31124d5ec89fSNuman Siddique 	if (err)
31134d5ec89fSNuman Siddique 		return err;
31144d5ec89fSNuman Siddique 
31154d5ec89fSNuman Siddique 	add_nested_action_end(*sfa, nested_acts_start);
31164d5ec89fSNuman Siddique 
31174d5ec89fSNuman Siddique 	nested_acts_start = add_nested_action_start(sfa,
31184d5ec89fSNuman Siddique 		OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER, log);
31194d5ec89fSNuman Siddique 	if (nested_acts_start < 0)
31204d5ec89fSNuman Siddique 		return nested_acts_start;
31214d5ec89fSNuman Siddique 
31224d5ec89fSNuman Siddique 	err = __ovs_nla_copy_actions(net, acts_if_greater, key, sfa,
31235eeb2a9eSAaron Conole 				     eth_type, vlan_tci, mpls_label_count, log,
31245eeb2a9eSAaron Conole 				     depth + 1);
31254d5ec89fSNuman Siddique 
31264d5ec89fSNuman Siddique 	if (err)
31274d5ec89fSNuman Siddique 		return err;
31284d5ec89fSNuman Siddique 
31294d5ec89fSNuman Siddique 	add_nested_action_end(*sfa, nested_acts_start);
31304d5ec89fSNuman Siddique 	add_nested_action_end(*sfa, start);
31314d5ec89fSNuman Siddique 	return 0;
31324d5ec89fSNuman Siddique }
31334d5ec89fSNuman Siddique 
3134e6445719SPravin B Shelar static int copy_action(const struct nlattr *from,
313505da5898SJarno Rajahalme 		       struct sw_flow_actions **sfa, bool log)
3136e6445719SPravin B Shelar {
3137e6445719SPravin B Shelar 	int totlen = NLA_ALIGN(from->nla_len);
3138e6445719SPravin B Shelar 	struct nlattr *to;
3139e6445719SPravin B Shelar 
314005da5898SJarno Rajahalme 	to = reserve_sfa_size(sfa, from->nla_len, log);
3141e6445719SPravin B Shelar 	if (IS_ERR(to))
3142e6445719SPravin B Shelar 		return PTR_ERR(to);
3143e6445719SPravin B Shelar 
3144e6445719SPravin B Shelar 	memcpy(to, from, totlen);
3145e6445719SPravin B Shelar 	return 0;
3146e6445719SPravin B Shelar }
copy_action(const struct nlattr * from,struct sw_flow_actions ** sfa,bool log)3147e6445719SPravin B Shelar 
31487f8a436eSJoe Stringer static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3149e6445719SPravin B Shelar 				  const struct sw_flow_key *key,
3150798c1661Sandy zhou 				  struct sw_flow_actions **sfa,
3151fbdcdd78SMartin Varghese 				  __be16 eth_type, __be16 vlan_tci,
31525eeb2a9eSAaron Conole 				  u32 mpls_label_count, bool log,
31535eeb2a9eSAaron Conole 				  u32 depth)
3154e6445719SPravin B Shelar {
31550a6410fbSJiri Benc 	u8 mac_proto = ovs_key_mac_proto(key);
3156e6445719SPravin B Shelar 	const struct nlattr *a;
3157e6445719SPravin B Shelar 	int rem, err;
3158e6445719SPravin B Shelar 
31595eeb2a9eSAaron Conole 	if (depth > OVS_COPY_ACTIONS_MAX_DEPTH)
31605eeb2a9eSAaron Conole 		return -EOVERFLOW;
31615eeb2a9eSAaron Conole 
3162e6445719SPravin B Shelar 	nla_for_each_nested(a, attr, rem) {
3163e6445719SPravin B Shelar 		/* Expected argument lengths, (u32)-1 for variable length. */
3164e6445719SPravin B Shelar 		static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
3165e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
3166971427f3SAndy Zhou 			[OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
3167e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
316825cd9ba0SSimon Horman 			[OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls),
316925cd9ba0SSimon Horman 			[OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
3170e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
3171e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_POP_VLAN] = 0,
3172e6445719SPravin B Shelar 			[OVS_ACTION_ATTR_SET] = (u32)-1,
317383d2b9baSJarno Rajahalme 			[OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
3174971427f3SAndy Zhou 			[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
31757f8a436eSJoe Stringer 			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
31767f8a436eSJoe Stringer 			[OVS_ACTION_ATTR_CT] = (u32)-1,
3177b8226962SEric Garver 			[OVS_ACTION_ATTR_CT_CLEAR] = 0,
3178f2a4d086SWilliam Tu 			[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
317991820da6SJiri Benc 			[OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
318091820da6SJiri Benc 			[OVS_ACTION_ATTR_POP_ETH] = 0,
3181b2d0f5d5SYi Yang 			[OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
3182b2d0f5d5SYi Yang 			[OVS_ACTION_ATTR_POP_NSH] = 0,
3183cd8a6c33SAndy Zhou 			[OVS_ACTION_ATTR_METER] = sizeof(u32),
3184b2335040SYifeng Sun 			[OVS_ACTION_ATTR_CLONE] = (u32)-1,
31854d5ec89fSNuman Siddique 			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
3186f66b53fdSMartin Varghese 			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
3187744676e7SMatteo Croce 			[OVS_ACTION_ATTR_DEC_TTL] = (u32)-1,
3188e7bc7db9SEric Garver 			[OVS_ACTION_ATTR_DROP] = sizeof(u32),
3189e6445719SPravin B Shelar 		};
3190e6445719SPravin B Shelar 		const struct ovs_action_push_vlan *vlan;
3191e6445719SPravin B Shelar 		int type = nla_type(a);
3192e6445719SPravin B Shelar 		bool skip_copy;
3193e6445719SPravin B Shelar 
3194e6445719SPravin B Shelar 		if (type > OVS_ACTION_ATTR_MAX ||
3195e6445719SPravin B Shelar 		    (action_lens[type] != nla_len(a) &&
3196e6445719SPravin B Shelar 		     action_lens[type] != (u32)-1))
3197e6445719SPravin B Shelar 			return -EINVAL;
3198e6445719SPravin B Shelar 
3199e6445719SPravin B Shelar 		skip_copy = false;
3200e6445719SPravin B Shelar 		switch (type) {
3201e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_UNSPEC:
3202e6445719SPravin B Shelar 			return -EINVAL;
3203e6445719SPravin B Shelar 
3204e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_USERSPACE:
3205e6445719SPravin B Shelar 			err = validate_userspace(a);
3206e6445719SPravin B Shelar 			if (err)
3207e6445719SPravin B Shelar 				return err;
3208e6445719SPravin B Shelar 			break;
3209e6445719SPravin B Shelar 
3210e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_OUTPUT:
3211e6445719SPravin B Shelar 			if (nla_get_u32(a) >= DP_MAX_PORTS)
3212e6445719SPravin B Shelar 				return -EINVAL;
3213e6445719SPravin B Shelar 			break;
3214e6445719SPravin B Shelar 
3215f2a4d086SWilliam Tu 		case OVS_ACTION_ATTR_TRUNC: {
3216f2a4d086SWilliam Tu 			const struct ovs_action_trunc *trunc = nla_data(a);
3217f2a4d086SWilliam Tu 
3218f2a4d086SWilliam Tu 			if (trunc->max_len < ETH_HLEN)
3219f2a4d086SWilliam Tu 				return -EINVAL;
3220f2a4d086SWilliam Tu 			break;
3221f2a4d086SWilliam Tu 		}
3222f2a4d086SWilliam Tu 
3223971427f3SAndy Zhou 		case OVS_ACTION_ATTR_HASH: {
3224971427f3SAndy Zhou 			const struct ovs_action_hash *act_hash = nla_data(a);
3225971427f3SAndy Zhou 
3226971427f3SAndy Zhou 			switch (act_hash->hash_alg) {
3227971427f3SAndy Zhou 			case OVS_HASH_ALG_L4:
3228e069ba07SAaron Conole 				fallthrough;
3229e069ba07SAaron Conole 			case OVS_HASH_ALG_SYM_L4:
3230971427f3SAndy Zhou 				break;
3231971427f3SAndy Zhou 			default:
3232971427f3SAndy Zhou 				return  -EINVAL;
3233971427f3SAndy Zhou 			}
3234971427f3SAndy Zhou 
3235971427f3SAndy Zhou 			break;
3236971427f3SAndy Zhou 		}
3237e6445719SPravin B Shelar 
3238e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_POP_VLAN:
32390a6410fbSJiri Benc 			if (mac_proto != MAC_PROTO_ETHERNET)
32400a6410fbSJiri Benc 				return -EINVAL;
324125cd9ba0SSimon Horman 			vlan_tci = htons(0);
3242e6445719SPravin B Shelar 			break;
3243e6445719SPravin B Shelar 
3244e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_PUSH_VLAN:
32450a6410fbSJiri Benc 			if (mac_proto != MAC_PROTO_ETHERNET)
32460a6410fbSJiri Benc 				return -EINVAL;
3247e6445719SPravin B Shelar 			vlan = nla_data(a);
3248018c1ddaSEric Garver 			if (!eth_type_vlan(vlan->vlan_tpid))
3249e6445719SPravin B Shelar 				return -EINVAL;
32509df46aefSMichał Mirosław 			if (!(vlan->vlan_tci & htons(VLAN_CFI_MASK)))
3251e6445719SPravin B Shelar 				return -EINVAL;
325225cd9ba0SSimon Horman 			vlan_tci = vlan->vlan_tci;
3253e6445719SPravin B Shelar 			break;
3254e6445719SPravin B Shelar 
3255971427f3SAndy Zhou 		case OVS_ACTION_ATTR_RECIRC:
3256971427f3SAndy Zhou 			break;
3257971427f3SAndy Zhou 
3258f66b53fdSMartin Varghese 		case OVS_ACTION_ATTR_ADD_MPLS: {
3259f66b53fdSMartin Varghese 			const struct ovs_action_add_mpls *mpls = nla_data(a);
3260f66b53fdSMartin Varghese 
3261f66b53fdSMartin Varghese 			if (!eth_p_mpls(mpls->mpls_ethertype))
3262f66b53fdSMartin Varghese 				return -EINVAL;
3263f66b53fdSMartin Varghese 
3264f66b53fdSMartin Varghese 			if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK) {
3265f66b53fdSMartin Varghese 				if (vlan_tci & htons(VLAN_CFI_MASK) ||
3266f66b53fdSMartin Varghese 				    (eth_type != htons(ETH_P_IP) &&
3267f66b53fdSMartin Varghese 				     eth_type != htons(ETH_P_IPV6) &&
3268f66b53fdSMartin Varghese 				     eth_type != htons(ETH_P_ARP) &&
3269f66b53fdSMartin Varghese 				     eth_type != htons(ETH_P_RARP) &&
3270f66b53fdSMartin Varghese 				     !eth_p_mpls(eth_type)))
3271f66b53fdSMartin Varghese 					return -EINVAL;
3272f66b53fdSMartin Varghese 				mpls_label_count++;
3273f66b53fdSMartin Varghese 			} else {
3274f66b53fdSMartin Varghese 				if (mac_proto == MAC_PROTO_ETHERNET) {
3275f66b53fdSMartin Varghese 					mpls_label_count = 1;
3276f66b53fdSMartin Varghese 					mac_proto = MAC_PROTO_NONE;
3277f66b53fdSMartin Varghese 				} else {
3278f66b53fdSMartin Varghese 					mpls_label_count++;
3279f66b53fdSMartin Varghese 				}
3280f66b53fdSMartin Varghese 			}
3281f66b53fdSMartin Varghese 			eth_type = mpls->mpls_ethertype;
3282f66b53fdSMartin Varghese 			break;
3283f66b53fdSMartin Varghese 		}
3284f66b53fdSMartin Varghese 
328525cd9ba0SSimon Horman 		case OVS_ACTION_ATTR_PUSH_MPLS: {
328625cd9ba0SSimon Horman 			const struct ovs_action_push_mpls *mpls = nla_data(a);
328725cd9ba0SSimon Horman 
328825cd9ba0SSimon Horman 			if (!eth_p_mpls(mpls->mpls_ethertype))
328925cd9ba0SSimon Horman 				return -EINVAL;
329025cd9ba0SSimon Horman 			/* Prohibit push MPLS other than to a white list
329125cd9ba0SSimon Horman 			 * for packets that have a known tag order.
329225cd9ba0SSimon Horman 			 */
32939df46aefSMichał Mirosław 			if (vlan_tci & htons(VLAN_CFI_MASK) ||
329425cd9ba0SSimon Horman 			    (eth_type != htons(ETH_P_IP) &&
329525cd9ba0SSimon Horman 			     eth_type != htons(ETH_P_IPV6) &&
329625cd9ba0SSimon Horman 			     eth_type != htons(ETH_P_ARP) &&
329725cd9ba0SSimon Horman 			     eth_type != htons(ETH_P_RARP) &&
329825cd9ba0SSimon Horman 			     !eth_p_mpls(eth_type)))
329925cd9ba0SSimon Horman 				return -EINVAL;
330025cd9ba0SSimon Horman 			eth_type = mpls->mpls_ethertype;
3301fbdcdd78SMartin Varghese 			mpls_label_count++;
330225cd9ba0SSimon Horman 			break;
330325cd9ba0SSimon Horman 		}
330425cd9ba0SSimon Horman 
3305fbdcdd78SMartin Varghese 		case OVS_ACTION_ATTR_POP_MPLS: {
3306fbdcdd78SMartin Varghese 			__be16  proto;
33079df46aefSMichał Mirosław 			if (vlan_tci & htons(VLAN_CFI_MASK) ||
330825cd9ba0SSimon Horman 			    !eth_p_mpls(eth_type))
330925cd9ba0SSimon Horman 				return -EINVAL;
331025cd9ba0SSimon Horman 
3311fbdcdd78SMartin Varghese 			/* Disallow subsequent L2.5+ set actions and mpls_pop
3312fbdcdd78SMartin Varghese 			 * actions once the last MPLS label in the packet is
3313169ccf0eSJilin Yuan 			 * popped as there is no check here to ensure that
3314fbdcdd78SMartin Varghese 			 * the new eth type is valid and thus set actions could
3315fbdcdd78SMartin Varghese 			 * write off the end of the packet or otherwise corrupt
3316fbdcdd78SMartin Varghese 			 * it.
331725cd9ba0SSimon Horman 			 *
331825cd9ba0SSimon Horman 			 * Support for these actions is planned using packet
331925cd9ba0SSimon Horman 			 * recirculation.
332025cd9ba0SSimon Horman 			 */
3321fbdcdd78SMartin Varghese 			proto = nla_get_be16(a);
3322f66b53fdSMartin Varghese 
3323f66b53fdSMartin Varghese 			if (proto == htons(ETH_P_TEB) &&
3324f66b53fdSMartin Varghese 			    mac_proto != MAC_PROTO_NONE)
3325f66b53fdSMartin Varghese 				return -EINVAL;
3326f66b53fdSMartin Varghese 
3327fbdcdd78SMartin Varghese 			mpls_label_count--;
3328fbdcdd78SMartin Varghese 
3329fbdcdd78SMartin Varghese 			if (!eth_p_mpls(proto) || !mpls_label_count)
333025cd9ba0SSimon Horman 				eth_type = htons(0);
3331fbdcdd78SMartin Varghese 			else
3332fbdcdd78SMartin Varghese 				eth_type =  proto;
3333fbdcdd78SMartin Varghese 
333425cd9ba0SSimon Horman 			break;
3335fbdcdd78SMartin Varghese 		}
333625cd9ba0SSimon Horman 
3337e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_SET:
333825cd9ba0SSimon Horman 			err = validate_set(a, key, sfa,
33390a6410fbSJiri Benc 					   &skip_copy, mac_proto, eth_type,
33400a6410fbSJiri Benc 					   false, log);
334183d2b9baSJarno Rajahalme 			if (err)
334283d2b9baSJarno Rajahalme 				return err;
334383d2b9baSJarno Rajahalme 			break;
334483d2b9baSJarno Rajahalme 
334583d2b9baSJarno Rajahalme 		case OVS_ACTION_ATTR_SET_MASKED:
334683d2b9baSJarno Rajahalme 			err = validate_set(a, key, sfa,
33470a6410fbSJiri Benc 					   &skip_copy, mac_proto, eth_type,
33480a6410fbSJiri Benc 					   true, log);
3349e6445719SPravin B Shelar 			if (err)
3350e6445719SPravin B Shelar 				return err;
3351e6445719SPravin B Shelar 			break;
3352e6445719SPravin B Shelar 
3353798c1661Sandy zhou 		case OVS_ACTION_ATTR_SAMPLE: {
3354798c1661Sandy zhou 			bool last = nla_is_last(a, rem);
3355798c1661Sandy zhou 
3356798c1661Sandy zhou 			err = validate_and_copy_sample(net, a, key, sfa,
3357798c1661Sandy zhou 						       eth_type, vlan_tci,
3358fbdcdd78SMartin Varghese 						       mpls_label_count,
33595eeb2a9eSAaron Conole 						       log, last, depth);
3360e6445719SPravin B Shelar 			if (err)
3361e6445719SPravin B Shelar 				return err;
3362e6445719SPravin B Shelar 			skip_copy = true;
3363e6445719SPravin B Shelar 			break;
3364798c1661Sandy zhou 		}
3365e6445719SPravin B Shelar 
33667f8a436eSJoe Stringer 		case OVS_ACTION_ATTR_CT:
33677f8a436eSJoe Stringer 			err = ovs_ct_copy_action(net, a, key, sfa, log);
33687f8a436eSJoe Stringer 			if (err)
33697f8a436eSJoe Stringer 				return err;
33707f8a436eSJoe Stringer 			skip_copy = true;
33717f8a436eSJoe Stringer 			break;
33727f8a436eSJoe Stringer 
3373b8226962SEric Garver 		case OVS_ACTION_ATTR_CT_CLEAR:
3374b8226962SEric Garver 			break;
3375b8226962SEric Garver 
337691820da6SJiri Benc 		case OVS_ACTION_ATTR_PUSH_ETH:
337791820da6SJiri Benc 			/* Disallow pushing an Ethernet header if one
337891820da6SJiri Benc 			 * is already present */
337991820da6SJiri Benc 			if (mac_proto != MAC_PROTO_NONE)
338091820da6SJiri Benc 				return -EINVAL;
338146ebe283SJaime Caamaño Ruiz 			mac_proto = MAC_PROTO_ETHERNET;
338291820da6SJiri Benc 			break;
338391820da6SJiri Benc 
338491820da6SJiri Benc 		case OVS_ACTION_ATTR_POP_ETH:
338591820da6SJiri Benc 			if (mac_proto != MAC_PROTO_ETHERNET)
338691820da6SJiri Benc 				return -EINVAL;
33879df46aefSMichał Mirosław 			if (vlan_tci & htons(VLAN_CFI_MASK))
338891820da6SJiri Benc 				return -EINVAL;
338946ebe283SJaime Caamaño Ruiz 			mac_proto = MAC_PROTO_NONE;
339091820da6SJiri Benc 			break;
339191820da6SJiri Benc 
3392b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_PUSH_NSH:
3393b2d0f5d5SYi Yang 			if (mac_proto != MAC_PROTO_ETHERNET) {
3394b2d0f5d5SYi Yang 				u8 next_proto;
3395b2d0f5d5SYi Yang 
3396b2d0f5d5SYi Yang 				next_proto = tun_p_from_eth_p(eth_type);
3397b2d0f5d5SYi Yang 				if (!next_proto)
3398b2d0f5d5SYi Yang 					return -EINVAL;
3399b2d0f5d5SYi Yang 			}
3400b2d0f5d5SYi Yang 			mac_proto = MAC_PROTO_NONE;
3401b2d0f5d5SYi Yang 			if (!validate_nsh(nla_data(a), false, true, true))
3402b2d0f5d5SYi Yang 				return -EINVAL;
3403b2d0f5d5SYi Yang 			break;
3404b2d0f5d5SYi Yang 
3405b2d0f5d5SYi Yang 		case OVS_ACTION_ATTR_POP_NSH: {
3406b2d0f5d5SYi Yang 			__be16 inner_proto;
3407b2d0f5d5SYi Yang 
3408b2d0f5d5SYi Yang 			if (eth_type != htons(ETH_P_NSH))
3409b2d0f5d5SYi Yang 				return -EINVAL;
3410b2d0f5d5SYi Yang 			inner_proto = tun_p_to_eth_p(key->nsh.base.np);
3411b2d0f5d5SYi Yang 			if (!inner_proto)
3412b2d0f5d5SYi Yang 				return -EINVAL;
3413b2d0f5d5SYi Yang 			if (key->nsh.base.np == TUN_P_ETHERNET)
3414b2d0f5d5SYi Yang 				mac_proto = MAC_PROTO_ETHERNET;
3415b2d0f5d5SYi Yang 			else
3416b2d0f5d5SYi Yang 				mac_proto = MAC_PROTO_NONE;
3417b2d0f5d5SYi Yang 			break;
3418b2d0f5d5SYi Yang 		}
3419b2d0f5d5SYi Yang 
3420cd8a6c33SAndy Zhou 		case OVS_ACTION_ATTR_METER:
3421cd8a6c33SAndy Zhou 			/* Non-existent meters are simply ignored.  */
3422cd8a6c33SAndy Zhou 			break;
3423cd8a6c33SAndy Zhou 
3424b2335040SYifeng Sun 		case OVS_ACTION_ATTR_CLONE: {
3425b2335040SYifeng Sun 			bool last = nla_is_last(a, rem);
3426b2335040SYifeng Sun 
3427b2335040SYifeng Sun 			err = validate_and_copy_clone(net, a, key, sfa,
3428b2335040SYifeng Sun 						      eth_type, vlan_tci,
3429fbdcdd78SMartin Varghese 						      mpls_label_count,
34305eeb2a9eSAaron Conole 						      log, last, depth);
3431b2335040SYifeng Sun 			if (err)
3432b2335040SYifeng Sun 				return err;
3433b2335040SYifeng Sun 			skip_copy = true;
3434b2335040SYifeng Sun 			break;
3435b2335040SYifeng Sun 		}
3436b2335040SYifeng Sun 
34374d5ec89fSNuman Siddique 		case OVS_ACTION_ATTR_CHECK_PKT_LEN: {
34384d5ec89fSNuman Siddique 			bool last = nla_is_last(a, rem);
34394d5ec89fSNuman Siddique 
34404d5ec89fSNuman Siddique 			err = validate_and_copy_check_pkt_len(net, a, key, sfa,
34414d5ec89fSNuman Siddique 							      eth_type,
3442fbdcdd78SMartin Varghese 							      vlan_tci,
3443fbdcdd78SMartin Varghese 							      mpls_label_count,
34445eeb2a9eSAaron Conole 							      log, last,
34455eeb2a9eSAaron Conole 							      depth);
34464d5ec89fSNuman Siddique 			if (err)
34474d5ec89fSNuman Siddique 				return err;
34484d5ec89fSNuman Siddique 			skip_copy = true;
34494d5ec89fSNuman Siddique 			break;
34504d5ec89fSNuman Siddique 		}
34514d5ec89fSNuman Siddique 
3452744676e7SMatteo Croce 		case OVS_ACTION_ATTR_DEC_TTL:
3453744676e7SMatteo Croce 			err = validate_and_copy_dec_ttl(net, a, key, sfa,
3454744676e7SMatteo Croce 							eth_type, vlan_tci,
34555eeb2a9eSAaron Conole 							mpls_label_count, log,
34565eeb2a9eSAaron Conole 							depth);
3457744676e7SMatteo Croce 			if (err)
3458744676e7SMatteo Croce 				return err;
3459744676e7SMatteo Croce 			skip_copy = true;
3460744676e7SMatteo Croce 			break;
3461744676e7SMatteo Croce 
3462e7bc7db9SEric Garver 		case OVS_ACTION_ATTR_DROP:
3463e7bc7db9SEric Garver 			if (!nla_is_last(a, rem))
3464e7bc7db9SEric Garver 				return -EINVAL;
3465e7bc7db9SEric Garver 			break;
3466e7bc7db9SEric Garver 
3467e6445719SPravin B Shelar 		default:
346805da5898SJarno Rajahalme 			OVS_NLERR(log, "Unknown Action type %d", type);
3469e6445719SPravin B Shelar 			return -EINVAL;
3470e6445719SPravin B Shelar 		}
3471e6445719SPravin B Shelar 		if (!skip_copy) {
347205da5898SJarno Rajahalme 			err = copy_action(a, sfa, log);
3473e6445719SPravin B Shelar 			if (err)
3474e6445719SPravin B Shelar 				return err;
3475e6445719SPravin B Shelar 		}
3476e6445719SPravin B Shelar 	}
3477e6445719SPravin B Shelar 
3478e6445719SPravin B Shelar 	if (rem > 0)
3479e6445719SPravin B Shelar 		return -EINVAL;
3480e6445719SPravin B Shelar 
3481e6445719SPravin B Shelar 	return 0;
3482e6445719SPravin B Shelar }
3483e6445719SPravin B Shelar 
348483d2b9baSJarno Rajahalme /* 'key' must be the masked key. */
34857f8a436eSJoe Stringer int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
348625cd9ba0SSimon Horman 			 const struct sw_flow_key *key,
348705da5898SJarno Rajahalme 			 struct sw_flow_actions **sfa, bool log)
348825cd9ba0SSimon Horman {
34892fdb957dSPravin B Shelar 	int err;
3490fbdcdd78SMartin Varghese 	u32 mpls_label_count = 0;
34912fdb957dSPravin B Shelar 
3492*4b1a0ee6SIlya Maximets 	*sfa = nla_alloc_flow_actions(nla_len(attr));
34932fdb957dSPravin B Shelar 	if (IS_ERR(*sfa))
34942fdb957dSPravin B Shelar 		return PTR_ERR(*sfa);
34952fdb957dSPravin B Shelar 
3496fbdcdd78SMartin Varghese 	if (eth_p_mpls(key->eth.type))
3497fbdcdd78SMartin Varghese 		mpls_label_count = hweight_long(key->mpls.num_labels_mask);
ovs_nla_copy_actions(struct net * net,const struct nlattr * attr,const struct sw_flow_key * key,struct sw_flow_actions ** sfa,bool log)3498fbdcdd78SMartin Varghese 
34998e2fed1cSJoe Stringer 	(*sfa)->orig_len = nla_len(attr);
3500798c1661Sandy zhou 	err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type,
35015eeb2a9eSAaron Conole 				     key->eth.vlan.tci, mpls_label_count, log,
35025eeb2a9eSAaron Conole 				     0);
35032fdb957dSPravin B Shelar 	if (err)
350434ae932aSThomas Graf 		ovs_nla_free_flow_actions(*sfa);
35052fdb957dSPravin B Shelar 
35062fdb957dSPravin B Shelar 	return err;
350725cd9ba0SSimon Horman }
350825cd9ba0SSimon Horman 
3509798c1661Sandy zhou static int sample_action_to_attr(const struct nlattr *attr,
3510798c1661Sandy zhou 				 struct sk_buff *skb)
3511e6445719SPravin B Shelar {
3512798c1661Sandy zhou 	struct nlattr *start, *ac_start = NULL, *sample_arg;
3513798c1661Sandy zhou 	int err = 0, rem = nla_len(attr);
3514798c1661Sandy zhou 	const struct sample_arg *arg;
3515798c1661Sandy zhou 	struct nlattr *actions;
3516e6445719SPravin B Shelar 
3517ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SAMPLE);
3518e6445719SPravin B Shelar 	if (!start)
3519e6445719SPravin B Shelar 		return -EMSGSIZE;
3520e6445719SPravin B Shelar 
3521798c1661Sandy zhou 	sample_arg = nla_data(attr);
sample_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)3522798c1661Sandy zhou 	arg = nla_data(sample_arg);
3523798c1661Sandy zhou 	actions = nla_next(sample_arg, &rem);
3524e6445719SPravin B Shelar 
3525798c1661Sandy zhou 	if (nla_put_u32(skb, OVS_SAMPLE_ATTR_PROBABILITY, arg->probability)) {
3526798c1661Sandy zhou 		err = -EMSGSIZE;
3527798c1661Sandy zhou 		goto out;
3528e6445719SPravin B Shelar 	}
3529e6445719SPravin B Shelar 
3530ae0be8deSMichal Kubecek 	ac_start = nla_nest_start_noflag(skb, OVS_SAMPLE_ATTR_ACTIONS);
3531798c1661Sandy zhou 	if (!ac_start) {
3532798c1661Sandy zhou 		err = -EMSGSIZE;
3533798c1661Sandy zhou 		goto out;
3534798c1661Sandy zhou 	}
3535798c1661Sandy zhou 
3536798c1661Sandy zhou 	err = ovs_nla_put_actions(actions, rem, skb);
3537798c1661Sandy zhou 
3538798c1661Sandy zhou out:
3539798c1661Sandy zhou 	if (err) {
3540798c1661Sandy zhou 		nla_nest_cancel(skb, ac_start);
3541798c1661Sandy zhou 		nla_nest_cancel(skb, start);
3542798c1661Sandy zhou 	} else {
3543798c1661Sandy zhou 		nla_nest_end(skb, ac_start);
3544e6445719SPravin B Shelar 		nla_nest_end(skb, start);
3545798c1661Sandy zhou 	}
3546798c1661Sandy zhou 
3547e6445719SPravin B Shelar 	return err;
3548e6445719SPravin B Shelar }
3549e6445719SPravin B Shelar 
3550b2335040SYifeng Sun static int clone_action_to_attr(const struct nlattr *attr,
3551b2335040SYifeng Sun 				struct sk_buff *skb)
3552b2335040SYifeng Sun {
3553b2335040SYifeng Sun 	struct nlattr *start;
3554b2335040SYifeng Sun 	int err = 0, rem = nla_len(attr);
3555b2335040SYifeng Sun 
3556ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CLONE);
3557b2335040SYifeng Sun 	if (!start)
3558b2335040SYifeng Sun 		return -EMSGSIZE;
3559b2335040SYifeng Sun 
35603f2a3050SIlya Maximets 	/* Skipping the OVS_CLONE_ATTR_EXEC that is always the first attribute. */
35613f2a3050SIlya Maximets 	attr = nla_next(nla_data(attr), &rem);
35623f2a3050SIlya Maximets 	err = ovs_nla_put_actions(attr, rem, skb);
clone_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)3563b2335040SYifeng Sun 
3564b2335040SYifeng Sun 	if (err)
3565b2335040SYifeng Sun 		nla_nest_cancel(skb, start);
3566b2335040SYifeng Sun 	else
3567b2335040SYifeng Sun 		nla_nest_end(skb, start);
3568b2335040SYifeng Sun 
3569b2335040SYifeng Sun 	return err;
3570b2335040SYifeng Sun }
3571b2335040SYifeng Sun 
35724d5ec89fSNuman Siddique static int check_pkt_len_action_to_attr(const struct nlattr *attr,
35734d5ec89fSNuman Siddique 					struct sk_buff *skb)
35744d5ec89fSNuman Siddique {
35754d5ec89fSNuman Siddique 	struct nlattr *start, *ac_start = NULL;
35764d5ec89fSNuman Siddique 	const struct check_pkt_len_arg *arg;
35774d5ec89fSNuman Siddique 	const struct nlattr *a, *cpl_arg;
35784d5ec89fSNuman Siddique 	int err = 0, rem = nla_len(attr);
35794d5ec89fSNuman Siddique 
3580ae0be8deSMichal Kubecek 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CHECK_PKT_LEN);
35814d5ec89fSNuman Siddique 	if (!start)
35824d5ec89fSNuman Siddique 		return -EMSGSIZE;
35834d5ec89fSNuman Siddique 
35844d5ec89fSNuman Siddique 	/* The first nested attribute in 'attr' is always
check_pkt_len_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)35854d5ec89fSNuman Siddique 	 * 'OVS_CHECK_PKT_LEN_ATTR_ARG'.
35864d5ec89fSNuman Siddique 	 */
35874d5ec89fSNuman Siddique 	cpl_arg = nla_data(attr);
35884d5ec89fSNuman Siddique 	arg = nla_data(cpl_arg);
35894d5ec89fSNuman Siddique 
35904d5ec89fSNuman Siddique 	if (nla_put_u16(skb, OVS_CHECK_PKT_LEN_ATTR_PKT_LEN, arg->pkt_len)) {
35914d5ec89fSNuman Siddique 		err = -EMSGSIZE;
35924d5ec89fSNuman Siddique 		goto out;
35934d5ec89fSNuman Siddique 	}
35944d5ec89fSNuman Siddique 
35954d5ec89fSNuman Siddique 	/* Second nested attribute in 'attr' is always
35964d5ec89fSNuman Siddique 	 * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL'.
35974d5ec89fSNuman Siddique 	 */
35984d5ec89fSNuman Siddique 	a = nla_next(cpl_arg, &rem);
3599ae0be8deSMichal Kubecek 	ac_start =  nla_nest_start_noflag(skb,
36004d5ec89fSNuman Siddique 					  OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL);
36014d5ec89fSNuman Siddique 	if (!ac_start) {
36024d5ec89fSNuman Siddique 		err = -EMSGSIZE;
36034d5ec89fSNuman Siddique 		goto out;
36044d5ec89fSNuman Siddique 	}
36054d5ec89fSNuman Siddique 
36064d5ec89fSNuman Siddique 	err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
36074d5ec89fSNuman Siddique 	if (err) {
36084d5ec89fSNuman Siddique 		nla_nest_cancel(skb, ac_start);
36094d5ec89fSNuman Siddique 		goto out;
36104d5ec89fSNuman Siddique 	} else {
36114d5ec89fSNuman Siddique 		nla_nest_end(skb, ac_start);
36124d5ec89fSNuman Siddique 	}
36134d5ec89fSNuman Siddique 
36144d5ec89fSNuman Siddique 	/* Third nested attribute in 'attr' is always
36154d5ec89fSNuman Siddique 	 * OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER.
36164d5ec89fSNuman Siddique 	 */
36174d5ec89fSNuman Siddique 	a = nla_next(a, &rem);
3618ae0be8deSMichal Kubecek 	ac_start =  nla_nest_start_noflag(skb,
36194d5ec89fSNuman Siddique 					  OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER);
36204d5ec89fSNuman Siddique 	if (!ac_start) {
36214d5ec89fSNuman Siddique 		err = -EMSGSIZE;
36224d5ec89fSNuman Siddique 		goto out;
36234d5ec89fSNuman Siddique 	}
36244d5ec89fSNuman Siddique 
36254d5ec89fSNuman Siddique 	err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
36264d5ec89fSNuman Siddique 	if (err) {
36274d5ec89fSNuman Siddique 		nla_nest_cancel(skb, ac_start);
36284d5ec89fSNuman Siddique 		goto out;
36294d5ec89fSNuman Siddique 	} else {
36304d5ec89fSNuman Siddique 		nla_nest_end(skb, ac_start);
36314d5ec89fSNuman Siddique 	}
36324d5ec89fSNuman Siddique 
36334d5ec89fSNuman Siddique 	nla_nest_end(skb, start);
36344d5ec89fSNuman Siddique 	return 0;
36354d5ec89fSNuman Siddique 
36364d5ec89fSNuman Siddique out:
36374d5ec89fSNuman Siddique 	nla_nest_cancel(skb, start);
36384d5ec89fSNuman Siddique 	return err;
36394d5ec89fSNuman Siddique }
36404d5ec89fSNuman Siddique 
3641744676e7SMatteo Croce static int dec_ttl_action_to_attr(const struct nlattr *attr,
3642744676e7SMatteo Croce 				  struct sk_buff *skb)
3643744676e7SMatteo Croce {
364469929d4cSEelco Chaudron 	struct nlattr *start, *action_start;
364569929d4cSEelco Chaudron 	const struct nlattr *a;
364669929d4cSEelco Chaudron 	int err = 0, rem;
3647744676e7SMatteo Croce 
3648744676e7SMatteo Croce 	start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL);
3649744676e7SMatteo Croce 	if (!start)
3650744676e7SMatteo Croce 		return -EMSGSIZE;
3651744676e7SMatteo Croce 
365269929d4cSEelco Chaudron 	nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) {
365369929d4cSEelco Chaudron 		switch (nla_type(a)) {
dec_ttl_action_to_attr(const struct nlattr * attr,struct sk_buff * skb)365469929d4cSEelco Chaudron 		case OVS_DEC_TTL_ATTR_ACTION:
3655744676e7SMatteo Croce 
365669929d4cSEelco Chaudron 			action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION);
365769929d4cSEelco Chaudron 			if (!action_start) {
365869929d4cSEelco Chaudron 				err = -EMSGSIZE;
365969929d4cSEelco Chaudron 				goto out;
366069929d4cSEelco Chaudron 			}
366169929d4cSEelco Chaudron 
366269929d4cSEelco Chaudron 			err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb);
366369929d4cSEelco Chaudron 			if (err)
366469929d4cSEelco Chaudron 				goto out;
366569929d4cSEelco Chaudron 
366669929d4cSEelco Chaudron 			nla_nest_end(skb, action_start);
366769929d4cSEelco Chaudron 			break;
366869929d4cSEelco Chaudron 
366969929d4cSEelco Chaudron 		default:
367069929d4cSEelco Chaudron 			/* Ignore all other option to be future compatible */
367169929d4cSEelco Chaudron 			break;
367269929d4cSEelco Chaudron 		}
367369929d4cSEelco Chaudron 	}
367469929d4cSEelco Chaudron 
367569929d4cSEelco Chaudron 	nla_nest_end(skb, start);
367669929d4cSEelco Chaudron 	return 0;
367769929d4cSEelco Chaudron 
367869929d4cSEelco Chaudron out:
367969929d4cSEelco Chaudron 	nla_nest_cancel(skb, start);
3680744676e7SMatteo Croce 	return err;
3681744676e7SMatteo Croce }
3682744676e7SMatteo Croce 
3683e6445719SPravin B Shelar static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
3684e6445719SPravin B Shelar {
3685e6445719SPravin B Shelar 	const struct nlattr *ovs_key = nla_data(a);
3686e6445719SPravin B Shelar 	int key_type = nla_type(ovs_key);
3687e6445719SPravin B Shelar 	struct nlattr *start;
3688e6445719SPravin B Shelar 	int err;
3689e6445719SPravin B Shelar 
3690e6445719SPravin B Shelar 	switch (key_type) {
3691f0b128c1SJesse Gross 	case OVS_KEY_ATTR_TUNNEL_INFO: {
369234ae932aSThomas Graf 		struct ovs_tunnel_info *ovs_tun = nla_data(ovs_key);
369334ae932aSThomas Graf 		struct ip_tunnel_info *tun_info = &ovs_tun->tun_dst->u.tun_info;
3694f0b128c1SJesse Gross 
3695ae0be8deSMichal Kubecek 		start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET);
set_action_to_attr(const struct nlattr * a,struct sk_buff * skb)3696e6445719SPravin B Shelar 		if (!start)
3697e6445719SPravin B Shelar 			return -EMSGSIZE;
3698e6445719SPravin B Shelar 
3699e905eabcSSimon Horman 		err =  ip_tun_to_nlattr(skb, &tun_info->key,
3700e905eabcSSimon Horman 					ip_tunnel_info_opts(tun_info),
3701e905eabcSSimon Horman 					tun_info->options_len,
370218b6f717Swenxu 					ip_tunnel_info_af(tun_info), tun_info->mode);
3703e6445719SPravin B Shelar 		if (err)
3704e6445719SPravin B Shelar 			return err;
3705e6445719SPravin B Shelar 		nla_nest_end(skb, start);
3706e6445719SPravin B Shelar 		break;
3707f0b128c1SJesse Gross 	}
3708e6445719SPravin B Shelar 	default:
3709e6445719SPravin B Shelar 		if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
3710e6445719SPravin B Shelar 			return -EMSGSIZE;
3711e6445719SPravin B Shelar 		break;
3712e6445719SPravin B Shelar 	}
3713e6445719SPravin B Shelar 
3714e6445719SPravin B Shelar 	return 0;
3715e6445719SPravin B Shelar }
3716e6445719SPravin B Shelar 
371783d2b9baSJarno Rajahalme static int masked_set_action_to_set_action_attr(const struct nlattr *a,
371883d2b9baSJarno Rajahalme 						struct sk_buff *skb)
371983d2b9baSJarno Rajahalme {
372083d2b9baSJarno Rajahalme 	const struct nlattr *ovs_key = nla_data(a);
3721f4f8e738SJoe Stringer 	struct nlattr *nla;
372283d2b9baSJarno Rajahalme 	size_t key_len = nla_len(ovs_key) / 2;
372383d2b9baSJarno Rajahalme 
372483d2b9baSJarno Rajahalme 	/* Revert the conversion we did from a non-masked set action to
372583d2b9baSJarno Rajahalme 	 * masked set action.
372683d2b9baSJarno Rajahalme 	 */
3727ae0be8deSMichal Kubecek 	nla = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET);
3728f4f8e738SJoe Stringer 	if (!nla)
372983d2b9baSJarno Rajahalme 		return -EMSGSIZE;
masked_set_action_to_set_action_attr(const struct nlattr * a,struct sk_buff * skb)373083d2b9baSJarno Rajahalme 
3731f4f8e738SJoe Stringer 	if (nla_put(skb, nla_type(ovs_key), key_len, nla_data(ovs_key)))
3732f4f8e738SJoe Stringer 		return -EMSGSIZE;
3733f4f8e738SJoe Stringer 
3734f4f8e738SJoe Stringer 	nla_nest_end(skb, nla);
373583d2b9baSJarno Rajahalme 	return 0;
373683d2b9baSJarno Rajahalme }
373783d2b9baSJarno Rajahalme 
3738e6445719SPravin B Shelar int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb)
3739e6445719SPravin B Shelar {
3740e6445719SPravin B Shelar 	const struct nlattr *a;
3741e6445719SPravin B Shelar 	int rem, err;
3742e6445719SPravin B Shelar 
3743e6445719SPravin B Shelar 	nla_for_each_attr(a, attr, len, rem) {
3744e6445719SPravin B Shelar 		int type = nla_type(a);
3745e6445719SPravin B Shelar 
3746e6445719SPravin B Shelar 		switch (type) {
3747e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_SET:
3748e6445719SPravin B Shelar 			err = set_action_to_attr(a, skb);
3749e6445719SPravin B Shelar 			if (err)
3750e6445719SPravin B Shelar 				return err;
ovs_nla_put_actions(const struct nlattr * attr,int len,struct sk_buff * skb)3751e6445719SPravin B Shelar 			break;
3752e6445719SPravin B Shelar 
375383d2b9baSJarno Rajahalme 		case OVS_ACTION_ATTR_SET_TO_MASKED:
375483d2b9baSJarno Rajahalme 			err = masked_set_action_to_set_action_attr(a, skb);
375583d2b9baSJarno Rajahalme 			if (err)
375683d2b9baSJarno Rajahalme 				return err;
375783d2b9baSJarno Rajahalme 			break;
375883d2b9baSJarno Rajahalme 
3759e6445719SPravin B Shelar 		case OVS_ACTION_ATTR_SAMPLE:
3760e6445719SPravin B Shelar 			err = sample_action_to_attr(a, skb);
3761e6445719SPravin B Shelar 			if (err)
3762e6445719SPravin B Shelar 				return err;
3763e6445719SPravin B Shelar 			break;
37647f8a436eSJoe Stringer 
37657f8a436eSJoe Stringer 		case OVS_ACTION_ATTR_CT:
37667f8a436eSJoe Stringer 			err = ovs_ct_action_to_attr(nla_data(a), skb);
37677f8a436eSJoe Stringer 			if (err)
37687f8a436eSJoe Stringer 				return err;
37697f8a436eSJoe Stringer 			break;
37707f8a436eSJoe Stringer 
3771b2335040SYifeng Sun 		case OVS_ACTION_ATTR_CLONE:
3772b2335040SYifeng Sun 			err = clone_action_to_attr(a, skb);
3773b2335040SYifeng Sun 			if (err)
3774b2335040SYifeng Sun 				return err;
3775b2335040SYifeng Sun 			break;
3776b2335040SYifeng Sun 
37774d5ec89fSNuman Siddique 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
37784d5ec89fSNuman Siddique 			err = check_pkt_len_action_to_attr(a, skb);
37794d5ec89fSNuman Siddique 			if (err)
37804d5ec89fSNuman Siddique 				return err;
37814d5ec89fSNuman Siddique 			break;
37824d5ec89fSNuman Siddique 
3783744676e7SMatteo Croce 		case OVS_ACTION_ATTR_DEC_TTL:
3784744676e7SMatteo Croce 			err = dec_ttl_action_to_attr(a, skb);
3785744676e7SMatteo Croce 			if (err)
3786744676e7SMatteo Croce 				return err;
3787744676e7SMatteo Croce 			break;
3788744676e7SMatteo Croce 
3789e6445719SPravin B Shelar 		default:
3790e6445719SPravin B Shelar 			if (nla_put(skb, type, nla_len(a), nla_data(a)))
3791e6445719SPravin B Shelar 				return -EMSGSIZE;
3792e6445719SPravin B Shelar 			break;
3793e6445719SPravin B Shelar 		}
3794e6445719SPravin B Shelar 	}
3795e6445719SPravin B Shelar 
3796e6445719SPravin B Shelar 	return 0;
3797e6445719SPravin B Shelar }
3798