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