]> git.proxmox.com Git - mirror_ovs.git/blob - lib/tc.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / tc.c
1 /*
2 * Copyright (c) 2009-2017 Nicira, Inc.
3 * Copyright (c) 2016 Mellanox Technologies, Ltd.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <config.h>
19 #include "tc.h"
20
21 #include <errno.h>
22 #include <linux/if_ether.h>
23 #include <linux/if_packet.h>
24 #include <linux/rtnetlink.h>
25 #include <linux/tc_act/tc_csum.h>
26 #include <linux/tc_act/tc_gact.h>
27 #include <linux/tc_act/tc_mirred.h>
28 #include <linux/tc_act/tc_mpls.h>
29 #include <linux/tc_act/tc_pedit.h>
30 #include <linux/tc_act/tc_skbedit.h>
31 #include <linux/tc_act/tc_tunnel_key.h>
32 #include <linux/tc_act/tc_vlan.h>
33 #include <linux/tc_act/tc_ct.h>
34 #include <linux/gen_stats.h>
35 #include <net/if.h>
36 #include <unistd.h>
37
38 #include "byte-order.h"
39 #include "netlink-socket.h"
40 #include "netlink.h"
41 #include "openvswitch/ofpbuf.h"
42 #include "openvswitch/util.h"
43 #include "openvswitch/vlog.h"
44 #include "packets.h"
45 #include "timeval.h"
46 #include "unaligned.h"
47
48 #define MAX_PEDIT_OFFSETS 32
49
50 #ifndef TCM_IFINDEX_MAGIC_BLOCK
51 #define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU)
52 #endif
53
54 #ifndef TCA_DUMP_FLAGS_TERSE
55 #define TCA_DUMP_FLAGS_TERSE (1 << 0)
56 #endif
57
58 #if TCA_MAX < 15
59 #define TCA_CHAIN 11
60 #define TCA_INGRESS_BLOCK 13
61 #define TCA_DUMP_FLAGS 15
62 #endif
63
64 VLOG_DEFINE_THIS_MODULE(tc);
65
66 static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
67
68 static enum tc_offload_policy tc_policy = TC_POLICY_NONE;
69
70 struct tc_pedit_key_ex {
71 enum pedit_header_type htype;
72 enum pedit_cmd cmd;
73 };
74
75 struct flower_key_to_pedit {
76 enum pedit_header_type htype;
77 int offset;
78 int flower_offset;
79 int size;
80 int boundary_shift;
81 };
82
83 static struct flower_key_to_pedit flower_pedit_map[] = {
84 {
85 TCA_PEDIT_KEY_EX_HDR_TYPE_IP4,
86 12,
87 offsetof(struct tc_flower_key, ipv4.ipv4_src),
88 MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_src),
89 0
90 }, {
91 TCA_PEDIT_KEY_EX_HDR_TYPE_IP4,
92 16,
93 offsetof(struct tc_flower_key, ipv4.ipv4_dst),
94 MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_dst),
95 0
96 }, {
97 TCA_PEDIT_KEY_EX_HDR_TYPE_IP4,
98 8,
99 offsetof(struct tc_flower_key, ipv4.rewrite_ttl),
100 MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_ttl),
101 0
102 }, {
103 TCA_PEDIT_KEY_EX_HDR_TYPE_IP4,
104 1,
105 offsetof(struct tc_flower_key, ipv4.rewrite_tos),
106 MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_tos),
107 0
108 }, {
109 TCA_PEDIT_KEY_EX_HDR_TYPE_IP6,
110 7,
111 offsetof(struct tc_flower_key, ipv6.rewrite_hlimit),
112 MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_hlimit),
113 0
114 }, {
115 TCA_PEDIT_KEY_EX_HDR_TYPE_IP6,
116 8,
117 offsetof(struct tc_flower_key, ipv6.ipv6_src),
118 MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_src),
119 0
120 }, {
121 TCA_PEDIT_KEY_EX_HDR_TYPE_IP6,
122 24,
123 offsetof(struct tc_flower_key, ipv6.ipv6_dst),
124 MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_dst),
125 0
126 }, {
127 TCA_PEDIT_KEY_EX_HDR_TYPE_IP6,
128 0,
129 offsetof(struct tc_flower_key, ipv6.rewrite_tclass),
130 MEMBER_SIZEOF(struct tc_flower_key, ipv6.rewrite_tclass),
131 4
132 }, {
133 TCA_PEDIT_KEY_EX_HDR_TYPE_ETH,
134 6,
135 offsetof(struct tc_flower_key, src_mac),
136 MEMBER_SIZEOF(struct tc_flower_key, src_mac),
137 0
138 }, {
139 TCA_PEDIT_KEY_EX_HDR_TYPE_ETH,
140 0,
141 offsetof(struct tc_flower_key, dst_mac),
142 MEMBER_SIZEOF(struct tc_flower_key, dst_mac),
143 0
144 }, {
145 TCA_PEDIT_KEY_EX_HDR_TYPE_ETH,
146 12,
147 offsetof(struct tc_flower_key, eth_type),
148 MEMBER_SIZEOF(struct tc_flower_key, eth_type),
149 0
150 }, {
151 TCA_PEDIT_KEY_EX_HDR_TYPE_TCP,
152 0,
153 offsetof(struct tc_flower_key, tcp_src),
154 MEMBER_SIZEOF(struct tc_flower_key, tcp_src),
155 0
156 }, {
157 TCA_PEDIT_KEY_EX_HDR_TYPE_TCP,
158 2,
159 offsetof(struct tc_flower_key, tcp_dst),
160 MEMBER_SIZEOF(struct tc_flower_key, tcp_dst),
161 0
162 }, {
163 TCA_PEDIT_KEY_EX_HDR_TYPE_UDP,
164 0,
165 offsetof(struct tc_flower_key, udp_src),
166 MEMBER_SIZEOF(struct tc_flower_key, udp_src),
167 0
168 }, {
169 TCA_PEDIT_KEY_EX_HDR_TYPE_UDP,
170 2,
171 offsetof(struct tc_flower_key, udp_dst),
172 MEMBER_SIZEOF(struct tc_flower_key, udp_dst),
173 0
174 },
175 };
176
177 static inline int
178 csum_update_flag(struct tc_flower *flower,
179 enum pedit_header_type htype);
180
181 struct tcmsg *
182 tc_make_request(int ifindex, int type, unsigned int flags,
183 struct ofpbuf *request)
184 {
185 struct tcmsg *tcmsg;
186
187 ofpbuf_init(request, 512);
188 nl_msg_put_nlmsghdr(request, sizeof *tcmsg, type, NLM_F_REQUEST | flags);
189 tcmsg = ofpbuf_put_zeros(request, sizeof *tcmsg);
190 tcmsg->tcm_family = AF_UNSPEC;
191 tcmsg->tcm_ifindex = ifindex;
192 /* Caller should fill in tcmsg->tcm_handle. */
193 /* Caller should fill in tcmsg->tcm_parent. */
194
195 return tcmsg;
196 }
197
198 static void request_from_tcf_id(struct tcf_id *id, uint16_t eth_type,
199 int type, unsigned int flags,
200 struct ofpbuf *request)
201 {
202 int ifindex = id->block_id ? TCM_IFINDEX_MAGIC_BLOCK : id->ifindex;
203 uint32_t ingress_parent = id->block_id ? : TC_INGRESS_PARENT;
204 struct tcmsg *tcmsg;
205
206 tcmsg = tc_make_request(ifindex, type, flags, request);
207 tcmsg->tcm_parent = (id->hook == TC_EGRESS) ?
208 TC_EGRESS_PARENT : ingress_parent;
209 tcmsg->tcm_info = tc_make_handle(id->prio, eth_type);
210 tcmsg->tcm_handle = id->handle;
211
212 if (id->chain) {
213 nl_msg_put_u32(request, TCA_CHAIN, id->chain);
214 }
215 }
216
217 int
218 tc_transact(struct ofpbuf *request, struct ofpbuf **replyp)
219 {
220 int error = nl_transact(NETLINK_ROUTE, request, replyp);
221 ofpbuf_uninit(request);
222 return error;
223 }
224
225 /* Adds or deletes a root qdisc on device with specified ifindex.
226 *
227 * The tc_qdisc_hook parameter determines if the qdisc is added on device
228 * ingress or egress.
229 *
230 * If tc_qdisc_hook is TC_INGRESS, this function is equivalent to running the
231 * following when 'add' is true:
232 * /sbin/tc qdisc add dev <devname> handle ffff: ingress
233 *
234 * This function is equivalent to running the following when 'add' is false:
235 * /sbin/tc qdisc del dev <devname> handle ffff: ingress
236 *
237 * If tc_qdisc_hook is TC_EGRESS, this function is equivalent to:
238 * /sbin/tc qdisc (add|del) dev <devname> handle ffff: clsact
239 *
240 * Where dev <devname> is the device with specified ifindex name.
241 *
242 * The configuration and stats may be seen with the following command:
243 * /sbin/tc -s qdisc show dev <devname>
244 *
245 * If block_id is greater than 0, then the ingress qdisc is added to a block.
246 * In this case, it is equivalent to running (when 'add' is true):
247 * /sbin/tc qdisc add dev <devname> ingress_block <block_id> ingress
248 *
249 * Returns 0 if successful, otherwise a positive errno value.
250 */
251 int
252 tc_add_del_qdisc(int ifindex, bool add, uint32_t block_id,
253 enum tc_qdisc_hook hook)
254 {
255 struct ofpbuf request;
256 struct tcmsg *tcmsg;
257 int error;
258 int type = add ? RTM_NEWQDISC : RTM_DELQDISC;
259 int flags = add ? NLM_F_EXCL | NLM_F_CREATE : 0;
260
261 tcmsg = tc_make_request(ifindex, type, flags, &request);
262
263 if (hook == TC_EGRESS) {
264 tcmsg->tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0);
265 tcmsg->tcm_parent = TC_H_CLSACT;
266 nl_msg_put_string(&request, TCA_KIND, "clsact");
267 } else {
268 tcmsg->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0);
269 tcmsg->tcm_parent = TC_H_INGRESS;
270 nl_msg_put_string(&request, TCA_KIND, "ingress");
271 }
272
273 nl_msg_put_unspec(&request, TCA_OPTIONS, NULL, 0);
274 if (hook == TC_INGRESS && block_id) {
275 nl_msg_put_u32(&request, TCA_INGRESS_BLOCK, block_id);
276 }
277
278 error = tc_transact(&request, NULL);
279 if (error) {
280 /* If we're deleting the qdisc, don't worry about some of the
281 * error conditions. */
282 if (!add && (error == ENOENT || error == EINVAL)) {
283 return 0;
284 }
285 return error;
286 }
287
288 return 0;
289 }
290
291 static const struct nl_policy tca_policy[] = {
292 [TCA_KIND] = { .type = NL_A_STRING, .optional = false, },
293 [TCA_OPTIONS] = { .type = NL_A_NESTED, .optional = false, },
294 [TCA_CHAIN] = { .type = NL_A_U32, .optional = true, },
295 [TCA_STATS] = { .type = NL_A_UNSPEC,
296 .min_len = sizeof(struct tc_stats), .optional = true, },
297 [TCA_STATS2] = { .type = NL_A_NESTED, .optional = true, },
298 };
299
300 static const struct nl_policy tca_flower_policy[] = {
301 [TCA_FLOWER_CLASSID] = { .type = NL_A_U32, .optional = true, },
302 [TCA_FLOWER_INDEV] = { .type = NL_A_STRING, .max_len = IFNAMSIZ,
303 .optional = true, },
304 [TCA_FLOWER_KEY_ETH_SRC] = { .type = NL_A_UNSPEC,
305 .min_len = ETH_ALEN, .optional = true, },
306 [TCA_FLOWER_KEY_ETH_DST] = { .type = NL_A_UNSPEC,
307 .min_len = ETH_ALEN, .optional = true, },
308 [TCA_FLOWER_KEY_ETH_SRC_MASK] = { .type = NL_A_UNSPEC,
309 .min_len = ETH_ALEN,
310 .optional = true, },
311 [TCA_FLOWER_KEY_ETH_DST_MASK] = { .type = NL_A_UNSPEC,
312 .min_len = ETH_ALEN,
313 .optional = true, },
314 [TCA_FLOWER_KEY_ETH_TYPE] = { .type = NL_A_U16, .optional = false, },
315 [TCA_FLOWER_KEY_ARP_SIP] = { .type = NL_A_U32, .optional = true, },
316 [TCA_FLOWER_KEY_ARP_TIP] = { .type = NL_A_U32, .optional = true, },
317 [TCA_FLOWER_KEY_ARP_SHA] = { .type = NL_A_UNSPEC,
318 .min_len = ETH_ALEN,
319 .optional = true, },
320 [TCA_FLOWER_KEY_ARP_THA] = { .type = NL_A_UNSPEC,
321 .min_len = ETH_ALEN,
322 .optional = true, },
323 [TCA_FLOWER_KEY_ARP_OP] = { .type = NL_A_U8, .optional = true, },
324 [TCA_FLOWER_KEY_ARP_SIP_MASK] = { .type = NL_A_U32, .optional = true, },
325 [TCA_FLOWER_KEY_ARP_TIP_MASK] = { .type = NL_A_U32, .optional = true, },
326 [TCA_FLOWER_KEY_ARP_SHA_MASK] = { .type = NL_A_UNSPEC,
327 .min_len = ETH_ALEN,
328 .optional = true, },
329 [TCA_FLOWER_KEY_ARP_THA_MASK] = { .type = NL_A_UNSPEC,
330 .min_len = ETH_ALEN,
331 .optional = true, },
332 [TCA_FLOWER_KEY_ARP_OP_MASK] = { .type = NL_A_U8, .optional = true, },
333 [TCA_FLOWER_FLAGS] = { .type = NL_A_U32, .optional = false, },
334 [TCA_FLOWER_ACT] = { .type = NL_A_NESTED, .optional = false, },
335 [TCA_FLOWER_KEY_IP_PROTO] = { .type = NL_A_U8, .optional = true, },
336 [TCA_FLOWER_KEY_IPV4_SRC] = { .type = NL_A_U32, .optional = true, },
337 [TCA_FLOWER_KEY_IPV4_DST] = {.type = NL_A_U32, .optional = true, },
338 [TCA_FLOWER_KEY_IPV4_SRC_MASK] = { .type = NL_A_U32, .optional = true, },
339 [TCA_FLOWER_KEY_IPV4_DST_MASK] = { .type = NL_A_U32, .optional = true, },
340 [TCA_FLOWER_KEY_IPV6_SRC] = { .type = NL_A_UNSPEC,
341 .min_len = sizeof(struct in6_addr),
342 .optional = true, },
343 [TCA_FLOWER_KEY_IPV6_DST] = { .type = NL_A_UNSPEC,
344 .min_len = sizeof(struct in6_addr),
345 .optional = true, },
346 [TCA_FLOWER_KEY_IPV6_SRC_MASK] = { .type = NL_A_UNSPEC,
347 .min_len = sizeof(struct in6_addr),
348 .optional = true, },
349 [TCA_FLOWER_KEY_IPV6_DST_MASK] = { .type = NL_A_UNSPEC,
350 .min_len = sizeof(struct in6_addr),
351 .optional = true, },
352 [TCA_FLOWER_KEY_TCP_SRC] = { .type = NL_A_U16, .optional = true, },
353 [TCA_FLOWER_KEY_TCP_DST] = { .type = NL_A_U16, .optional = true, },
354 [TCA_FLOWER_KEY_TCP_SRC_MASK] = { .type = NL_A_U16, .optional = true, },
355 [TCA_FLOWER_KEY_TCP_DST_MASK] = { .type = NL_A_U16, .optional = true, },
356 [TCA_FLOWER_KEY_UDP_SRC] = { .type = NL_A_U16, .optional = true, },
357 [TCA_FLOWER_KEY_UDP_DST] = { .type = NL_A_U16, .optional = true, },
358 [TCA_FLOWER_KEY_UDP_SRC_MASK] = { .type = NL_A_U16, .optional = true, },
359 [TCA_FLOWER_KEY_UDP_DST_MASK] = { .type = NL_A_U16, .optional = true, },
360 [TCA_FLOWER_KEY_SCTP_SRC] = { .type = NL_A_U16, .optional = true, },
361 [TCA_FLOWER_KEY_SCTP_DST] = { .type = NL_A_U16, .optional = true, },
362 [TCA_FLOWER_KEY_SCTP_SRC_MASK] = { .type = NL_A_U16, .optional = true, },
363 [TCA_FLOWER_KEY_SCTP_DST_MASK] = { .type = NL_A_U16, .optional = true, },
364 [TCA_FLOWER_KEY_MPLS_TTL] = { .type = NL_A_U8, .optional = true, },
365 [TCA_FLOWER_KEY_MPLS_TC] = { .type = NL_A_U8, .optional = true, },
366 [TCA_FLOWER_KEY_MPLS_BOS] = { .type = NL_A_U8, .optional = true, },
367 [TCA_FLOWER_KEY_MPLS_LABEL] = { .type = NL_A_U32, .optional = true, },
368 [TCA_FLOWER_KEY_VLAN_ID] = { .type = NL_A_U16, .optional = true, },
369 [TCA_FLOWER_KEY_VLAN_PRIO] = { .type = NL_A_U8, .optional = true, },
370 [TCA_FLOWER_KEY_VLAN_ETH_TYPE] = { .type = NL_A_U16, .optional = true, },
371 [TCA_FLOWER_KEY_ENC_KEY_ID] = { .type = NL_A_U32, .optional = true, },
372 [TCA_FLOWER_KEY_ENC_IPV4_SRC] = { .type = NL_A_U32, .optional = true, },
373 [TCA_FLOWER_KEY_ENC_IPV4_DST] = { .type = NL_A_U32, .optional = true, },
374 [TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] = { .type = NL_A_U32,
375 .optional = true, },
376 [TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] = { .type = NL_A_U32,
377 .optional = true, },
378 [TCA_FLOWER_KEY_ENC_IPV6_SRC] = { .type = NL_A_UNSPEC,
379 .min_len = sizeof(struct in6_addr),
380 .optional = true, },
381 [TCA_FLOWER_KEY_ENC_IPV6_DST] = { .type = NL_A_UNSPEC,
382 .min_len = sizeof(struct in6_addr),
383 .optional = true, },
384 [TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK] = { .type = NL_A_UNSPEC,
385 .min_len = sizeof(struct in6_addr),
386 .optional = true, },
387 [TCA_FLOWER_KEY_ENC_IPV6_DST_MASK] = { .type = NL_A_UNSPEC,
388 .min_len = sizeof(struct in6_addr),
389 .optional = true, },
390 [TCA_FLOWER_KEY_ENC_UDP_DST_PORT] = { .type = NL_A_U16,
391 .optional = true, },
392 [TCA_FLOWER_KEY_FLAGS] = { .type = NL_A_BE32, .optional = true, },
393 [TCA_FLOWER_KEY_FLAGS_MASK] = { .type = NL_A_BE32, .optional = true, },
394 [TCA_FLOWER_KEY_IP_TTL] = { .type = NL_A_U8,
395 .optional = true, },
396 [TCA_FLOWER_KEY_IP_TTL_MASK] = { .type = NL_A_U8,
397 .optional = true, },
398 [TCA_FLOWER_KEY_IP_TOS] = { .type = NL_A_U8,
399 .optional = true, },
400 [TCA_FLOWER_KEY_IP_TOS_MASK] = { .type = NL_A_U8,
401 .optional = true, },
402 [TCA_FLOWER_KEY_TCP_FLAGS] = { .type = NL_A_U16,
403 .optional = true, },
404 [TCA_FLOWER_KEY_TCP_FLAGS_MASK] = { .type = NL_A_U16,
405 .optional = true, },
406 [TCA_FLOWER_KEY_CVLAN_ID] = { .type = NL_A_U16, .optional = true, },
407 [TCA_FLOWER_KEY_CVLAN_PRIO] = { .type = NL_A_U8, .optional = true, },
408 [TCA_FLOWER_KEY_CVLAN_ETH_TYPE] = { .type = NL_A_U16, .optional = true, },
409 [TCA_FLOWER_KEY_ENC_IP_TOS] = { .type = NL_A_U8,
410 .optional = true, },
411 [TCA_FLOWER_KEY_ENC_IP_TOS_MASK] = { .type = NL_A_U8,
412 .optional = true, },
413 [TCA_FLOWER_KEY_ENC_IP_TTL] = { .type = NL_A_U8,
414 .optional = true, },
415 [TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NL_A_U8,
416 .optional = true, },
417 [TCA_FLOWER_KEY_ENC_OPTS] = { .type = NL_A_NESTED, .optional = true, },
418 [TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NL_A_NESTED,
419 .optional = true, },
420 [TCA_FLOWER_KEY_CT_STATE] = { .type = NL_A_U16, .optional = true, },
421 [TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NL_A_U16, .optional = true, },
422 [TCA_FLOWER_KEY_CT_ZONE] = { .type = NL_A_U16, .optional = true, },
423 [TCA_FLOWER_KEY_CT_ZONE_MASK] = { .type = NL_A_U16, .optional = true, },
424 [TCA_FLOWER_KEY_CT_MARK] = { .type = NL_A_U32, .optional = true, },
425 [TCA_FLOWER_KEY_CT_MARK_MASK] = { .type = NL_A_U32, .optional = true, },
426 [TCA_FLOWER_KEY_CT_LABELS] = { .type = NL_A_U128, .optional = true, },
427 [TCA_FLOWER_KEY_CT_LABELS_MASK] = { .type = NL_A_U128,
428 .optional = true, },
429 };
430
431 static const struct nl_policy tca_flower_terse_policy[] = {
432 [TCA_FLOWER_FLAGS] = { .type = NL_A_U32, .optional = false, },
433 [TCA_FLOWER_ACT] = { .type = NL_A_NESTED, .optional = false, },
434 };
435
436 static void
437 nl_parse_flower_arp(struct nlattr **attrs, struct tc_flower *flower)
438 {
439 const struct eth_addr *eth;
440
441 if (attrs[TCA_FLOWER_KEY_ARP_SIP_MASK]) {
442 flower->key.arp.spa =
443 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_SIP]);
444 flower->mask.arp.spa =
445 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_SIP_MASK]);
446 }
447 if (attrs[TCA_FLOWER_KEY_ARP_TIP_MASK]) {
448 flower->key.arp.tpa =
449 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_TIP]);
450 flower->mask.arp.tpa =
451 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ARP_TIP_MASK]);
452 }
453 if (attrs[TCA_FLOWER_KEY_ARP_SHA_MASK]) {
454 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_SHA], ETH_ALEN);
455 memcpy(&flower->key.arp.sha, eth, sizeof flower->key.arp.sha);
456
457 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_SHA_MASK], ETH_ALEN);
458 memcpy(&flower->mask.arp.sha, eth, sizeof flower->mask.arp.sha);
459 }
460 if (attrs[TCA_FLOWER_KEY_ARP_THA_MASK]) {
461 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_THA], ETH_ALEN);
462 memcpy(&flower->key.arp.tha, eth, sizeof flower->key.arp.tha);
463
464 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ARP_THA_MASK], ETH_ALEN);
465 memcpy(&flower->mask.arp.tha, eth, sizeof flower->mask.arp.tha);
466 }
467 if (attrs[TCA_FLOWER_KEY_ARP_OP_MASK]) {
468 flower->key.arp.opcode =
469 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ARP_OP]);
470 flower->mask.arp.opcode =
471 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ARP_OP_MASK]);
472 }
473 }
474
475 static void
476 nl_parse_flower_eth(struct nlattr **attrs, struct tc_flower *flower)
477 {
478 const struct eth_addr *eth;
479
480 if (attrs[TCA_FLOWER_KEY_ETH_SRC_MASK]) {
481 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ETH_SRC], ETH_ALEN);
482 memcpy(&flower->key.src_mac, eth, sizeof flower->key.src_mac);
483
484 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ETH_SRC_MASK], ETH_ALEN);
485 memcpy(&flower->mask.src_mac, eth, sizeof flower->mask.src_mac);
486 }
487 if (attrs[TCA_FLOWER_KEY_ETH_DST_MASK]) {
488 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ETH_DST], ETH_ALEN);
489 memcpy(&flower->key.dst_mac, eth, sizeof flower->key.dst_mac);
490
491 eth = nl_attr_get_unspec(attrs[TCA_FLOWER_KEY_ETH_DST_MASK], ETH_ALEN);
492 memcpy(&flower->mask.dst_mac, eth, sizeof flower->mask.dst_mac);
493 }
494 }
495
496 static void
497 nl_parse_flower_mpls(struct nlattr **attrs, struct tc_flower *flower)
498 {
499 uint8_t ttl, tc, bos;
500 uint32_t label;
501
502 if (!eth_type_mpls(flower->key.eth_type)) {
503 return;
504 }
505
506 flower->key.encap_eth_type[0] =
507 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ETH_TYPE]);
508 flower->key.mpls_lse = 0;
509 flower->mask.mpls_lse = 0;
510
511 if (attrs[TCA_FLOWER_KEY_MPLS_TTL]) {
512 ttl = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_MPLS_TTL]);
513 set_mpls_lse_ttl(&flower->key.mpls_lse, ttl);
514 set_mpls_lse_ttl(&flower->mask.mpls_lse, 0xff);
515 }
516
517 if (attrs[TCA_FLOWER_KEY_MPLS_BOS]) {
518 bos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_MPLS_BOS]);
519 set_mpls_lse_bos(&flower->key.mpls_lse, bos);
520 set_mpls_lse_ttl(&flower->mask.mpls_lse, 0xff);
521 }
522
523 if (attrs[TCA_FLOWER_KEY_MPLS_TC]) {
524 tc = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_MPLS_TC]);
525 set_mpls_lse_tc(&flower->key.mpls_lse, tc);
526 set_mpls_lse_tc(&flower->mask.mpls_lse, 0xff);
527 }
528
529 if (attrs[TCA_FLOWER_KEY_MPLS_LABEL]) {
530 label = nl_attr_get_u32(attrs[TCA_FLOWER_KEY_MPLS_LABEL]);
531 set_mpls_lse_label(&flower->key.mpls_lse, htonl(label));
532 set_mpls_lse_label(&flower->mask.mpls_lse, OVS_BE32_MAX);
533 }
534 }
535
536 static void
537 nl_parse_flower_vlan(struct nlattr **attrs, struct tc_flower *flower)
538 {
539 ovs_be16 encap_ethtype;
540
541 if (!eth_type_vlan(flower->key.eth_type)) {
542 return;
543 }
544
545 flower->key.encap_eth_type[0] =
546 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ETH_TYPE]);
547
548 if (attrs[TCA_FLOWER_KEY_VLAN_ID]) {
549 flower->key.vlan_id[0] =
550 nl_attr_get_u16(attrs[TCA_FLOWER_KEY_VLAN_ID]);
551 flower->mask.vlan_id[0] = 0xffff;
552 }
553 if (attrs[TCA_FLOWER_KEY_VLAN_PRIO]) {
554 flower->key.vlan_prio[0] =
555 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_VLAN_PRIO]);
556 flower->mask.vlan_prio[0] = 0xff;
557 }
558
559 if (!attrs[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
560 return;
561 }
562
563 encap_ethtype = nl_attr_get_be16(attrs[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
564 if (!eth_type_vlan(encap_ethtype)) {
565 return;
566 }
567
568 flower->key.encap_eth_type[1] = flower->key.encap_eth_type[0];
569 flower->key.encap_eth_type[0] = encap_ethtype;
570
571 if (attrs[TCA_FLOWER_KEY_CVLAN_ID]) {
572 flower->key.vlan_id[1] =
573 nl_attr_get_u16(attrs[TCA_FLOWER_KEY_CVLAN_ID]);
574 flower->mask.vlan_id[1] = 0xffff;
575 }
576 if (attrs[TCA_FLOWER_KEY_CVLAN_PRIO]) {
577 flower->key.vlan_prio[1] =
578 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_CVLAN_PRIO]);
579 flower->mask.vlan_prio[1] = 0xff;
580 }
581 }
582
583 static int
584 nl_parse_geneve_key(const struct nlattr *in_nlattr,
585 struct tun_metadata *metadata)
586 {
587 struct geneve_opt *opt = NULL;
588 const struct ofpbuf *msg;
589 uint16_t last_opt_type;
590 struct nlattr *nla;
591 struct ofpbuf buf;
592 size_t left;
593 int cnt;
594
595 nl_attr_get_nested(in_nlattr, &buf);
596 msg = &buf;
597
598 last_opt_type = TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC;
599 cnt = 0;
600 NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
601 uint16_t type = nl_attr_type(nla);
602
603 switch (type) {
604 case TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS:
605 if (cnt && last_opt_type != TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA) {
606 VLOG_ERR_RL(&error_rl, "failed to parse tun options class");
607 return EINVAL;
608 }
609
610 opt = &metadata->opts.gnv[cnt];
611 opt->opt_class = nl_attr_get_be16(nla);
612 cnt += sizeof(struct geneve_opt) / 4;
613 metadata->present.len += sizeof(struct geneve_opt);
614 last_opt_type = TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS;
615 break;
616 case TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE:
617 if (last_opt_type != TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS) {
618 VLOG_ERR_RL(&error_rl, "failed to parse tun options type");
619 return EINVAL;
620 }
621
622 opt->type = nl_attr_get_u8(nla);
623 last_opt_type = TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE;
624 break;
625 case TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA:
626 if (last_opt_type != TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE) {
627 VLOG_ERR_RL(&error_rl, "failed to parse tun options data");
628 return EINVAL;
629 }
630
631 opt->length = nl_attr_get_size(nla) / 4;
632 memcpy(opt + 1, nl_attr_get_unspec(nla, 1), opt->length * 4);
633 cnt += opt->length;
634 metadata->present.len += opt->length * 4;
635 last_opt_type = TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA;
636 break;
637 }
638 }
639
640 if (last_opt_type != TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA) {
641 VLOG_ERR_RL(&error_rl, "failed to parse tun options without data");
642 return EINVAL;
643 }
644
645 return 0;
646 }
647
648 static int
649 nl_parse_flower_tunnel_opts(struct nlattr *options,
650 struct tun_metadata *metadata)
651 {
652 const struct ofpbuf *msg;
653 struct nlattr *nla;
654 struct ofpbuf buf;
655 size_t left;
656 int err;
657
658 nl_attr_get_nested(options, &buf);
659 msg = &buf;
660
661 NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
662 uint16_t type = nl_attr_type(nla);
663 switch (type) {
664 case TCA_FLOWER_KEY_ENC_OPTS_GENEVE:
665 err = nl_parse_geneve_key(nla, metadata);
666 if (err) {
667 return err;
668 }
669
670 break;
671 }
672 }
673
674 return 0;
675 }
676
677 static int
678 flower_tun_geneve_opt_check_len(struct tun_metadata *key,
679 struct tun_metadata *mask)
680 {
681 const struct geneve_opt *opt, *opt_mask;
682 int len, cnt = 0;
683
684 len = key->present.len;
685 while (len) {
686 opt = &key->opts.gnv[cnt];
687 opt_mask = &mask->opts.gnv[cnt];
688
689 if (opt->length != opt_mask->length) {
690 VLOG_ERR_RL(&error_rl,
691 "failed to parse tun options; key/mask length differ");
692 return EINVAL;
693 }
694
695 cnt += sizeof(struct geneve_opt) / 4 + opt->length;
696 len -= sizeof(struct geneve_opt) + opt->length * 4;
697 }
698
699 return 0;
700 }
701
702 static int
703 nl_parse_flower_tunnel(struct nlattr **attrs, struct tc_flower *flower)
704 {
705 int err;
706
707 if (attrs[TCA_FLOWER_KEY_ENC_KEY_ID]) {
708 ovs_be32 id = nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_KEY_ID]);
709
710 flower->key.tunnel.id = be32_to_be64(id);
711 flower->mask.tunnel.id = OVS_BE64_MAX;
712 }
713 if (attrs[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK]) {
714 flower->mask.tunnel.ipv4.ipv4_src =
715 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK]);
716 flower->key.tunnel.ipv4.ipv4_src =
717 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_IPV4_SRC]);
718 }
719 if (attrs[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK]) {
720 flower->mask.tunnel.ipv4.ipv4_dst =
721 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK]);
722 flower->key.tunnel.ipv4.ipv4_dst =
723 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_ENC_IPV4_DST]);
724 }
725 if (attrs[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]) {
726 flower->mask.tunnel.ipv6.ipv6_src =
727 nl_attr_get_in6_addr(attrs[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]);
728 flower->key.tunnel.ipv6.ipv6_src =
729 nl_attr_get_in6_addr(attrs[TCA_FLOWER_KEY_ENC_IPV6_SRC]);
730 }
731 if (attrs[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]) {
732 flower->mask.tunnel.ipv6.ipv6_dst =
733 nl_attr_get_in6_addr(attrs[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]);
734 flower->key.tunnel.ipv6.ipv6_dst =
735 nl_attr_get_in6_addr(attrs[TCA_FLOWER_KEY_ENC_IPV6_DST]);
736 }
737 if (attrs[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]) {
738 flower->key.tunnel.tp_dst =
739 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
740 }
741 if (attrs[TCA_FLOWER_KEY_ENC_IP_TOS_MASK]) {
742 flower->key.tunnel.tos =
743 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ENC_IP_TOS]);
744 flower->mask.tunnel.tos =
745 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ENC_IP_TOS_MASK]);
746 }
747 if (attrs[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]) {
748 flower->key.tunnel.ttl =
749 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ENC_IP_TTL]);
750 flower->mask.tunnel.ttl =
751 nl_attr_get_u8(attrs[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]);
752 }
753
754 if (!is_all_zeros(&flower->mask.tunnel, sizeof flower->mask.tunnel) ||
755 !is_all_zeros(&flower->key.tunnel, sizeof flower->key.tunnel)) {
756 flower->tunnel = true;
757 }
758
759 if (attrs[TCA_FLOWER_KEY_ENC_OPTS] &&
760 attrs[TCA_FLOWER_KEY_ENC_OPTS_MASK]) {
761 err = nl_parse_flower_tunnel_opts(attrs[TCA_FLOWER_KEY_ENC_OPTS],
762 &flower->key.tunnel.metadata);
763 if (err) {
764 return err;
765 }
766
767 err = nl_parse_flower_tunnel_opts(attrs[TCA_FLOWER_KEY_ENC_OPTS_MASK],
768 &flower->mask.tunnel.metadata);
769 if (err) {
770 return err;
771 }
772
773 err = flower_tun_geneve_opt_check_len(&flower->key.tunnel.metadata,
774 &flower->mask.tunnel.metadata);
775 if (err) {
776 return err;
777 }
778 } else if (attrs[TCA_FLOWER_KEY_ENC_OPTS]) {
779 VLOG_ERR_RL(&error_rl,
780 "failed to parse tun options; no mask supplied");
781 return EINVAL;
782 } else if (attrs[TCA_FLOWER_KEY_ENC_OPTS_MASK]) {
783 VLOG_ERR_RL(&error_rl, "failed to parse tun options; no key supplied");
784 return EINVAL;
785 }
786
787 return 0;
788 }
789
790 static void
791 nl_parse_flower_ct_match(struct nlattr **attrs, struct tc_flower *flower) {
792 struct tc_flower_key *key = &flower->key;
793 struct tc_flower_key *mask = &flower->mask;
794 struct nlattr *attr_key, *attr_mask;
795
796 attr_key = attrs[TCA_FLOWER_KEY_CT_STATE];
797 attr_mask = attrs[TCA_FLOWER_KEY_CT_STATE_MASK];
798 if (attr_mask) {
799 key->ct_state = nl_attr_get_u16(attr_key);
800 mask->ct_state = nl_attr_get_u16(attr_mask);
801 }
802
803 attr_key = attrs[TCA_FLOWER_KEY_CT_ZONE];
804 attr_mask = attrs[TCA_FLOWER_KEY_CT_ZONE_MASK];
805 if (attrs[TCA_FLOWER_KEY_CT_ZONE_MASK]) {
806 key->ct_zone = nl_attr_get_u16(attr_key);
807 mask->ct_zone = nl_attr_get_u16(attr_mask);
808 }
809
810 attr_key = attrs[TCA_FLOWER_KEY_CT_MARK];
811 attr_mask = attrs[TCA_FLOWER_KEY_CT_MARK_MASK];
812 if (attrs[TCA_FLOWER_KEY_CT_MARK_MASK]) {
813 key->ct_mark = nl_attr_get_u32(attr_key);
814 mask->ct_mark = nl_attr_get_u32(attr_mask);
815 }
816
817 attr_key = attrs[TCA_FLOWER_KEY_CT_LABELS];
818 attr_mask = attrs[TCA_FLOWER_KEY_CT_LABELS_MASK];
819 if (attrs[TCA_FLOWER_KEY_CT_LABELS_MASK]) {
820 key->ct_label = nl_attr_get_u128(attr_key);
821 mask->ct_label = nl_attr_get_u128(attr_mask);
822 }
823 }
824
825 static void
826 nl_parse_flower_ip(struct nlattr **attrs, struct tc_flower *flower) {
827 uint8_t ip_proto = 0;
828 struct tc_flower_key *key = &flower->key;
829 struct tc_flower_key *mask = &flower->mask;
830
831 if (attrs[TCA_FLOWER_KEY_IP_PROTO]) {
832 ip_proto = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_PROTO]);
833 key->ip_proto = ip_proto;
834 mask->ip_proto = UINT8_MAX;
835 }
836
837 if (attrs[TCA_FLOWER_KEY_FLAGS_MASK]) {
838 key->flags = ntohl(nl_attr_get_be32(attrs[TCA_FLOWER_KEY_FLAGS]));
839 mask->flags =
840 ntohl(nl_attr_get_be32(attrs[TCA_FLOWER_KEY_FLAGS_MASK]));
841 }
842
843 if (attrs[TCA_FLOWER_KEY_IPV4_SRC_MASK]) {
844 key->ipv4.ipv4_src =
845 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_IPV4_SRC]);
846 mask->ipv4.ipv4_src =
847 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_IPV4_SRC_MASK]);
848 }
849 if (attrs[TCA_FLOWER_KEY_IPV4_DST_MASK]) {
850 key->ipv4.ipv4_dst =
851 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_IPV4_DST]);
852 mask->ipv4.ipv4_dst =
853 nl_attr_get_be32(attrs[TCA_FLOWER_KEY_IPV4_DST_MASK]);
854 }
855 if (attrs[TCA_FLOWER_KEY_IPV6_SRC_MASK]) {
856 struct nlattr *attr = attrs[TCA_FLOWER_KEY_IPV6_SRC];
857 struct nlattr *attr_mask = attrs[TCA_FLOWER_KEY_IPV6_SRC_MASK];
858
859 key->ipv6.ipv6_src = nl_attr_get_in6_addr(attr);
860 mask->ipv6.ipv6_src = nl_attr_get_in6_addr(attr_mask);
861 }
862 if (attrs[TCA_FLOWER_KEY_IPV6_DST_MASK]) {
863 struct nlattr *attr = attrs[TCA_FLOWER_KEY_IPV6_DST];
864 struct nlattr *attr_mask = attrs[TCA_FLOWER_KEY_IPV6_DST_MASK];
865
866 key->ipv6.ipv6_dst = nl_attr_get_in6_addr(attr);
867 mask->ipv6.ipv6_dst = nl_attr_get_in6_addr(attr_mask);
868 }
869
870 if (ip_proto == IPPROTO_TCP) {
871 if (attrs[TCA_FLOWER_KEY_TCP_SRC_MASK]) {
872 key->tcp_src =
873 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_TCP_SRC]);
874 mask->tcp_src =
875 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_TCP_SRC_MASK]);
876 }
877 if (attrs[TCA_FLOWER_KEY_TCP_DST_MASK]) {
878 key->tcp_dst =
879 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_TCP_DST]);
880 mask->tcp_dst =
881 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_TCP_DST_MASK]);
882 }
883 if (attrs[TCA_FLOWER_KEY_TCP_FLAGS_MASK]) {
884 key->tcp_flags =
885 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_TCP_FLAGS]);
886 mask->tcp_flags =
887 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
888 }
889 } else if (ip_proto == IPPROTO_UDP) {
890 if (attrs[TCA_FLOWER_KEY_UDP_SRC_MASK]) {
891 key->udp_src = nl_attr_get_be16(attrs[TCA_FLOWER_KEY_UDP_SRC]);
892 mask->udp_src =
893 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_UDP_SRC_MASK]);
894 }
895 if (attrs[TCA_FLOWER_KEY_UDP_DST_MASK]) {
896 key->udp_dst = nl_attr_get_be16(attrs[TCA_FLOWER_KEY_UDP_DST]);
897 mask->udp_dst =
898 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_UDP_DST_MASK]);
899 }
900 } else if (ip_proto == IPPROTO_SCTP) {
901 if (attrs[TCA_FLOWER_KEY_SCTP_SRC_MASK]) {
902 key->sctp_src = nl_attr_get_be16(attrs[TCA_FLOWER_KEY_SCTP_SRC]);
903 mask->sctp_src =
904 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_SCTP_SRC_MASK]);
905 }
906 if (attrs[TCA_FLOWER_KEY_SCTP_DST_MASK]) {
907 key->sctp_dst = nl_attr_get_be16(attrs[TCA_FLOWER_KEY_SCTP_DST]);
908 mask->sctp_dst =
909 nl_attr_get_be16(attrs[TCA_FLOWER_KEY_SCTP_DST_MASK]);
910 }
911 }
912
913 if (attrs[TCA_FLOWER_KEY_IP_TTL_MASK]) {
914 key->ip_ttl = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TTL]);
915 mask->ip_ttl = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TTL_MASK]);
916 }
917
918 if (attrs[TCA_FLOWER_KEY_IP_TOS_MASK]) {
919 key->ip_tos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TOS]);
920 mask->ip_tos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_IP_TOS_MASK]);
921 }
922
923 nl_parse_flower_ct_match(attrs, flower);
924 }
925
926 static enum tc_offloaded_state
927 nl_get_flower_offloaded_state(struct nlattr **attrs)
928 {
929 uint32_t flower_flags = 0;
930
931 if (attrs[TCA_FLOWER_FLAGS]) {
932 flower_flags = nl_attr_get_u32(attrs[TCA_FLOWER_FLAGS]);
933 if (flower_flags & TCA_CLS_FLAGS_NOT_IN_HW) {
934 return TC_OFFLOADED_STATE_NOT_IN_HW;
935 } else if (flower_flags & TCA_CLS_FLAGS_IN_HW) {
936 return TC_OFFLOADED_STATE_IN_HW;
937 }
938 }
939 return TC_OFFLOADED_STATE_UNDEFINED;
940 }
941
942 static void
943 nl_parse_flower_flags(struct nlattr **attrs, struct tc_flower *flower)
944 {
945 flower->offloaded_state = nl_get_flower_offloaded_state(attrs);
946 }
947
948 static const struct nl_policy pedit_policy[] = {
949 [TCA_PEDIT_PARMS_EX] = { .type = NL_A_UNSPEC,
950 .min_len = sizeof(struct tc_pedit),
951 .optional = false, },
952 [TCA_PEDIT_KEYS_EX] = { .type = NL_A_NESTED,
953 .optional = false, },
954 };
955
956 static int
957 nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower)
958 {
959 struct tc_action *action;
960 struct nlattr *pe_attrs[ARRAY_SIZE(pedit_policy)];
961 const struct tc_pedit *pe;
962 const struct tc_pedit_key *keys;
963 const struct nlattr *nla, *keys_ex, *ex_type;
964 const void *keys_attr;
965 char *rewrite_key = (void *) &flower->rewrite.key;
966 char *rewrite_mask = (void *) &flower->rewrite.mask;
967 size_t keys_ex_size, left;
968 int type, i = 0, err;
969
970 if (!nl_parse_nested(options, pedit_policy, pe_attrs,
971 ARRAY_SIZE(pedit_policy))) {
972 VLOG_ERR_RL(&error_rl, "failed to parse pedit action options");
973 return EPROTO;
974 }
975
976 pe = nl_attr_get_unspec(pe_attrs[TCA_PEDIT_PARMS_EX], sizeof *pe);
977 keys = pe->keys;
978 keys_attr = pe_attrs[TCA_PEDIT_KEYS_EX];
979 keys_ex = nl_attr_get(keys_attr);
980 keys_ex_size = nl_attr_get_size(keys_attr);
981
982 NL_ATTR_FOR_EACH (nla, left, keys_ex, keys_ex_size) {
983 if (i >= pe->nkeys) {
984 break;
985 }
986
987 if (nl_attr_type(nla) != TCA_PEDIT_KEY_EX) {
988 VLOG_ERR_RL(&error_rl, "unable to parse legacy pedit type: %d",
989 nl_attr_type(nla));
990 return EOPNOTSUPP;
991 }
992
993 ex_type = nl_attr_find_nested(nla, TCA_PEDIT_KEY_EX_HTYPE);
994 type = nl_attr_get_u16(ex_type);
995
996 err = csum_update_flag(flower, type);
997 if (err) {
998 return err;
999 }
1000
1001 for (int j = 0; j < ARRAY_SIZE(flower_pedit_map); j++) {
1002 struct flower_key_to_pedit *m = &flower_pedit_map[j];
1003 int flower_off = m->flower_offset;
1004 int sz = m->size;
1005 int mf = m->offset;
1006
1007 if (m->htype != type) {
1008 continue;
1009 }
1010
1011 /* check overlap between current pedit key, which is always
1012 * 4 bytes (range [off, off + 3]), and a map entry in
1013 * flower_pedit_map (range [mf, mf + sz - 1]) */
1014 if ((keys->off >= mf && keys->off < mf + sz)
1015 || (keys->off + 3 >= mf && keys->off + 3 < mf + sz)) {
1016 int diff = flower_off + (keys->off - mf);
1017 ovs_be32 *dst = (void *) (rewrite_key + diff);
1018 ovs_be32 *dst_m = (void *) (rewrite_mask + diff);
1019 ovs_be32 mask, mask_word, data_word;
1020 uint32_t zero_bits;
1021
1022 mask_word = htonl(ntohl(keys->mask) << m->boundary_shift);
1023 data_word = htonl(ntohl(keys->val) << m->boundary_shift);
1024 mask = ~(mask_word);
1025
1026 if (keys->off < mf) {
1027 zero_bits = 8 * (mf - keys->off);
1028 mask &= htonl(UINT32_MAX >> zero_bits);
1029 } else if (keys->off + 4 > mf + m->size) {
1030 zero_bits = 8 * (keys->off + 4 - mf - m->size);
1031 mask &= htonl(UINT32_MAX << zero_bits);
1032 }
1033
1034 *dst_m |= mask;
1035 *dst |= data_word & mask;
1036 }
1037 }
1038
1039 keys++;
1040 i++;
1041 }
1042
1043 action = &flower->actions[flower->action_count++];
1044 action->type = TC_ACT_PEDIT;
1045
1046 return 0;
1047 }
1048
1049 static const struct nl_policy tunnel_key_policy[] = {
1050 [TCA_TUNNEL_KEY_PARMS] = { .type = NL_A_UNSPEC,
1051 .min_len = sizeof(struct tc_tunnel_key),
1052 .optional = false, },
1053 [TCA_TUNNEL_KEY_ENC_IPV4_SRC] = { .type = NL_A_U32, .optional = true, },
1054 [TCA_TUNNEL_KEY_ENC_IPV4_DST] = { .type = NL_A_U32, .optional = true, },
1055 [TCA_TUNNEL_KEY_ENC_IPV6_SRC] = { .type = NL_A_UNSPEC,
1056 .min_len = sizeof(struct in6_addr),
1057 .optional = true, },
1058 [TCA_TUNNEL_KEY_ENC_IPV6_DST] = { .type = NL_A_UNSPEC,
1059 .min_len = sizeof(struct in6_addr),
1060 .optional = true, },
1061 [TCA_TUNNEL_KEY_ENC_KEY_ID] = { .type = NL_A_U32, .optional = true, },
1062 [TCA_TUNNEL_KEY_ENC_DST_PORT] = { .type = NL_A_U16, .optional = true, },
1063 [TCA_TUNNEL_KEY_ENC_TOS] = { .type = NL_A_U8, .optional = true, },
1064 [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NL_A_U8, .optional = true, },
1065 [TCA_TUNNEL_KEY_ENC_OPTS] = { .type = NL_A_NESTED, .optional = true, },
1066 [TCA_TUNNEL_KEY_NO_CSUM] = { .type = NL_A_U8, .optional = true, },
1067 };
1068
1069 static int
1070 nl_parse_act_geneve_opts(const struct nlattr *in_nlattr,
1071 struct tc_action *action)
1072 {
1073 struct geneve_opt *opt = NULL;
1074 const struct ofpbuf *msg;
1075 uint16_t last_opt_type;
1076 struct nlattr *nla;
1077 struct ofpbuf buf;
1078 size_t left;
1079 int cnt;
1080
1081 nl_attr_get_nested(in_nlattr, &buf);
1082 msg = &buf;
1083
1084 last_opt_type = TCA_TUNNEL_KEY_ENC_OPT_GENEVE_UNSPEC;
1085 cnt = 0;
1086 NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
1087 uint16_t type = nl_attr_type(nla);
1088
1089 switch (type) {
1090 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS:
1091 if (cnt && last_opt_type != TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA) {
1092 VLOG_ERR_RL(&error_rl,
1093 "failed to parse action geneve options class");
1094 return EINVAL;
1095 }
1096
1097 opt = &action->encap.data.opts.gnv[cnt];
1098 opt->opt_class = nl_attr_get_be16(nla);
1099 cnt += sizeof(struct geneve_opt) / 4;
1100 action->encap.data.present.len += sizeof(struct geneve_opt);
1101 last_opt_type = TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS;
1102 break;
1103 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE:
1104 if (last_opt_type != TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS) {
1105 VLOG_ERR_RL(&error_rl,
1106 "failed to parse action geneve options type");
1107 return EINVAL;
1108 }
1109
1110 opt->type = nl_attr_get_u8(nla);
1111 last_opt_type = TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE;
1112 break;
1113 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA:
1114 if (last_opt_type != TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE) {
1115 VLOG_ERR_RL(&error_rl,
1116 "failed to parse action geneve options data");
1117 return EINVAL;
1118 }
1119
1120 opt->length = nl_attr_get_size(nla) / 4;
1121 memcpy(opt + 1, nl_attr_get_unspec(nla, 1), opt->length * 4);
1122 cnt += opt->length;
1123 action->encap.data.present.len += opt->length * 4;
1124 last_opt_type = TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA;
1125 break;
1126 }
1127 }
1128
1129 if (last_opt_type != TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA) {
1130 VLOG_ERR_RL(&error_rl,
1131 "failed to parse action geneve options without data");
1132 return EINVAL;
1133 }
1134
1135 return 0;
1136 }
1137
1138 static int
1139 nl_parse_act_tunnel_opts(struct nlattr *options, struct tc_action *action)
1140 {
1141 const struct ofpbuf *msg;
1142 struct nlattr *nla;
1143 struct ofpbuf buf;
1144 size_t left;
1145 int err;
1146
1147 if (!options) {
1148 return 0;
1149 }
1150
1151 nl_attr_get_nested(options, &buf);
1152 msg = &buf;
1153
1154 NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, 0, 0), msg->size) {
1155 uint16_t type = nl_attr_type(nla);
1156 switch (type) {
1157 case TCA_TUNNEL_KEY_ENC_OPTS_GENEVE:
1158 err = nl_parse_act_geneve_opts(nla, action);
1159 if (err) {
1160 return err;
1161 }
1162
1163 break;
1164 }
1165 }
1166
1167 return 0;
1168 }
1169
1170 static int
1171 nl_parse_act_tunnel_key(struct nlattr *options, struct tc_flower *flower)
1172 {
1173 struct nlattr *tun_attrs[ARRAY_SIZE(tunnel_key_policy)];
1174 const struct nlattr *tun_parms;
1175 const struct tc_tunnel_key *tun;
1176 struct tc_action *action;
1177 int err;
1178
1179 if (!nl_parse_nested(options, tunnel_key_policy, tun_attrs,
1180 ARRAY_SIZE(tunnel_key_policy))) {
1181 VLOG_ERR_RL(&error_rl, "failed to parse tunnel_key action options");
1182 return EPROTO;
1183 }
1184
1185 tun_parms = tun_attrs[TCA_TUNNEL_KEY_PARMS];
1186 tun = nl_attr_get_unspec(tun_parms, sizeof *tun);
1187 if (tun->t_action == TCA_TUNNEL_KEY_ACT_SET) {
1188 struct nlattr *id = tun_attrs[TCA_TUNNEL_KEY_ENC_KEY_ID];
1189 struct nlattr *dst_port = tun_attrs[TCA_TUNNEL_KEY_ENC_DST_PORT];
1190 struct nlattr *ipv4_src = tun_attrs[TCA_TUNNEL_KEY_ENC_IPV4_SRC];
1191 struct nlattr *ipv4_dst = tun_attrs[TCA_TUNNEL_KEY_ENC_IPV4_DST];
1192 struct nlattr *ipv6_src = tun_attrs[TCA_TUNNEL_KEY_ENC_IPV6_SRC];
1193 struct nlattr *ipv6_dst = tun_attrs[TCA_TUNNEL_KEY_ENC_IPV6_DST];
1194 struct nlattr *tos = tun_attrs[TCA_TUNNEL_KEY_ENC_TOS];
1195 struct nlattr *ttl = tun_attrs[TCA_TUNNEL_KEY_ENC_TTL];
1196 struct nlattr *tun_opt = tun_attrs[TCA_TUNNEL_KEY_ENC_OPTS];
1197 struct nlattr *no_csum = tun_attrs[TCA_TUNNEL_KEY_NO_CSUM];
1198
1199 action = &flower->actions[flower->action_count++];
1200 action->type = TC_ACT_ENCAP;
1201 action->encap.ipv4.ipv4_src = ipv4_src ? nl_attr_get_be32(ipv4_src) : 0;
1202 action->encap.ipv4.ipv4_dst = ipv4_dst ? nl_attr_get_be32(ipv4_dst) : 0;
1203 if (ipv6_src) {
1204 action->encap.ipv6.ipv6_src = nl_attr_get_in6_addr(ipv6_src);
1205 }
1206 if (ipv6_dst) {
1207 action->encap.ipv6.ipv6_dst = nl_attr_get_in6_addr(ipv6_dst);
1208 }
1209 action->encap.id = id ? be32_to_be64(nl_attr_get_be32(id)) : 0;
1210 action->encap.id_present = id ? true : false;
1211 action->encap.tp_dst = dst_port ? nl_attr_get_be16(dst_port) : 0;
1212 action->encap.tos = tos ? nl_attr_get_u8(tos) : 0;
1213 action->encap.ttl = ttl ? nl_attr_get_u8(ttl) : 0;
1214 action->encap.no_csum = no_csum ? nl_attr_get_u8(no_csum) : 0;
1215
1216 err = nl_parse_act_tunnel_opts(tun_opt, action);
1217 if (err) {
1218 return err;
1219 }
1220 } else if (tun->t_action == TCA_TUNNEL_KEY_ACT_RELEASE) {
1221 flower->tunnel = true;
1222 } else {
1223 VLOG_ERR_RL(&error_rl, "unknown tunnel actions: %d, %d",
1224 tun->action, tun->t_action);
1225 return EINVAL;
1226 }
1227 return 0;
1228 }
1229
1230 static const struct nl_policy gact_policy[] = {
1231 [TCA_GACT_PARMS] = { .type = NL_A_UNSPEC,
1232 .min_len = sizeof(struct tc_gact),
1233 .optional = false, },
1234 [TCA_GACT_TM] = { .type = NL_A_UNSPEC,
1235 .min_len = sizeof(struct tcf_t),
1236 .optional = false, },
1237 };
1238
1239 static int
1240 get_user_hz(void)
1241 {
1242 static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
1243 static int user_hz = 100;
1244
1245 if (ovsthread_once_start(&once)) {
1246 user_hz = sysconf(_SC_CLK_TCK);
1247 ovsthread_once_done(&once);
1248 }
1249
1250 return user_hz;
1251 }
1252
1253 static void
1254 nl_parse_tcf(const struct tcf_t *tm, struct tc_flower *flower)
1255 {
1256 flower->lastused = time_msec() - (tm->lastuse * 1000 / get_user_hz());
1257 }
1258
1259 static int
1260 nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower)
1261 {
1262 struct nlattr *gact_attrs[ARRAY_SIZE(gact_policy)];
1263 const struct tc_gact *p;
1264 struct nlattr *gact_parms;
1265 const struct tcf_t *tm;
1266 struct tc_action *action;
1267
1268 if (!nl_parse_nested(options, gact_policy, gact_attrs,
1269 ARRAY_SIZE(gact_policy))) {
1270 VLOG_ERR_RL(&error_rl, "failed to parse gact action options");
1271 return EPROTO;
1272 }
1273
1274 gact_parms = gact_attrs[TCA_GACT_PARMS];
1275 p = nl_attr_get_unspec(gact_parms, sizeof *p);
1276
1277 if (TC_ACT_EXT_CMP(p->action, TC_ACT_GOTO_CHAIN)) {
1278 action = &flower->actions[flower->action_count++];
1279 action->chain = p->action & TC_ACT_EXT_VAL_MASK;
1280 action->type = TC_ACT_GOTO;
1281 } else if (p->action != TC_ACT_SHOT) {
1282 VLOG_ERR_RL(&error_rl, "unknown gact action: %d", p->action);
1283 return EINVAL;
1284 }
1285
1286 tm = nl_attr_get_unspec(gact_attrs[TCA_GACT_TM], sizeof *tm);
1287 nl_parse_tcf(tm, flower);
1288
1289 return 0;
1290 }
1291
1292 static const struct nl_policy mirred_policy[] = {
1293 [TCA_MIRRED_PARMS] = { .type = NL_A_UNSPEC,
1294 .min_len = sizeof(struct tc_mirred),
1295 .optional = false, },
1296 [TCA_MIRRED_TM] = { .type = NL_A_UNSPEC,
1297 .min_len = sizeof(struct tcf_t),
1298 .optional = false, },
1299 };
1300
1301 static int
1302 nl_parse_act_mirred(struct nlattr *options, struct tc_flower *flower)
1303 {
1304
1305 struct nlattr *mirred_attrs[ARRAY_SIZE(mirred_policy)];
1306 const struct tc_mirred *m;
1307 const struct nlattr *mirred_parms;
1308 const struct tcf_t *tm;
1309 struct nlattr *mirred_tm;
1310 struct tc_action *action;
1311
1312 if (!nl_parse_nested(options, mirred_policy, mirred_attrs,
1313 ARRAY_SIZE(mirred_policy))) {
1314 VLOG_ERR_RL(&error_rl, "failed to parse mirred action options");
1315 return EPROTO;
1316 }
1317
1318 mirred_parms = mirred_attrs[TCA_MIRRED_PARMS];
1319 m = nl_attr_get_unspec(mirred_parms, sizeof *m);
1320
1321 if (m->eaction != TCA_EGRESS_REDIR && m->eaction != TCA_EGRESS_MIRROR &&
1322 m->eaction != TCA_INGRESS_REDIR && m->eaction != TCA_INGRESS_MIRROR) {
1323 VLOG_ERR_RL(&error_rl, "unknown mirred action: %d, %d, %d",
1324 m->action, m->eaction, m->ifindex);
1325 return EINVAL;
1326 }
1327
1328 action = &flower->actions[flower->action_count++];
1329 action->out.ifindex_out = m->ifindex;
1330 if (m->eaction == TCA_INGRESS_REDIR || m->eaction == TCA_INGRESS_MIRROR) {
1331 action->out.ingress = true;
1332 } else {
1333 action->out.ingress = false;
1334 }
1335 action->type = TC_ACT_OUTPUT;
1336
1337 mirred_tm = mirred_attrs[TCA_MIRRED_TM];
1338 tm = nl_attr_get_unspec(mirred_tm, sizeof *tm);
1339 nl_parse_tcf(tm, flower);
1340
1341 return 0;
1342 }
1343
1344 static const struct nl_policy ct_policy[] = {
1345 [TCA_CT_PARMS] = { .type = NL_A_UNSPEC,
1346 .min_len = sizeof(struct tc_ct),
1347 .optional = false, },
1348 [TCA_CT_ACTION] = { .type = NL_A_U16,
1349 .optional = true, },
1350 [TCA_CT_ZONE] = { .type = NL_A_U16,
1351 .optional = true, },
1352 [TCA_CT_MARK] = { .type = NL_A_U32,
1353 .optional = true, },
1354 [TCA_CT_MARK_MASK] = { .type = NL_A_U32,
1355 .optional = true, },
1356 [TCA_CT_LABELS] = { .type = NL_A_UNSPEC,
1357 .optional = true, },
1358 [TCA_CT_LABELS_MASK] = { .type = NL_A_UNSPEC,
1359 .optional = true, },
1360 [TCA_CT_NAT_IPV4_MIN] = { .type = NL_A_U32,
1361 .optional = true, },
1362 [TCA_CT_NAT_IPV4_MAX] = { .type = NL_A_U32,
1363 .optional = true, },
1364 [TCA_CT_NAT_IPV6_MIN] = { .min_len = sizeof(struct in6_addr),
1365 .type = NL_A_UNSPEC,
1366 .optional = true },
1367 [TCA_CT_NAT_IPV6_MAX] = { .min_len = sizeof(struct in6_addr),
1368 .type = NL_A_UNSPEC,
1369 .optional = true },
1370 [TCA_CT_NAT_PORT_MIN] = { .type = NL_A_U16,
1371 .optional = true, },
1372 [TCA_CT_NAT_PORT_MAX] = { .type = NL_A_U16,
1373 .optional = true, },
1374 };
1375
1376 static int
1377 nl_parse_act_ct(struct nlattr *options, struct tc_flower *flower)
1378 {
1379 struct nlattr *ct_attrs[ARRAY_SIZE(ct_policy)];
1380 const struct nlattr *ct_parms;
1381 struct tc_action *action;
1382 const struct tc_ct *ct;
1383 uint16_t ct_action = 0;
1384
1385 if (!nl_parse_nested(options, ct_policy, ct_attrs,
1386 ARRAY_SIZE(ct_policy))) {
1387 VLOG_ERR_RL(&error_rl, "failed to parse ct action options");
1388 return EPROTO;
1389 }
1390
1391 ct_parms = ct_attrs[TCA_CT_PARMS];
1392 ct = nl_attr_get_unspec(ct_parms, sizeof *ct);
1393
1394 if (ct_attrs[TCA_CT_ACTION]) {
1395 ct_action = nl_attr_get_u16(ct_attrs[TCA_CT_ACTION]);
1396 }
1397
1398 action = &flower->actions[flower->action_count++];
1399 action->ct.clear = ct_action & TCA_CT_ACT_CLEAR;
1400 if (!action->ct.clear) {
1401 struct nlattr *zone = ct_attrs[TCA_CT_ZONE];
1402 struct nlattr *mark = ct_attrs[TCA_CT_MARK];
1403 struct nlattr *mark_mask = ct_attrs[TCA_CT_MARK_MASK];
1404 struct nlattr *label = ct_attrs[TCA_CT_LABELS];
1405 struct nlattr *label_mask = ct_attrs[TCA_CT_LABELS_MASK];
1406
1407 action->ct.commit = ct_action & TCA_CT_ACT_COMMIT;
1408 action->ct.force = ct_action & TCA_CT_ACT_FORCE;
1409
1410 action->ct.zone = zone ? nl_attr_get_u16(zone) : 0;
1411 action->ct.mark = mark ? nl_attr_get_u32(mark) : 0;
1412 action->ct.mark_mask = mark_mask ? nl_attr_get_u32(mark_mask) : 0;
1413 action->ct.label = label? nl_attr_get_u128(label) : OVS_U128_ZERO;
1414 action->ct.label_mask = label_mask ?
1415 nl_attr_get_u128(label_mask) : OVS_U128_ZERO;
1416
1417 if (ct_action & TCA_CT_ACT_NAT) {
1418 struct nlattr *ipv4_min = ct_attrs[TCA_CT_NAT_IPV4_MIN];
1419 struct nlattr *ipv4_max = ct_attrs[TCA_CT_NAT_IPV4_MAX];
1420 struct nlattr *ipv6_min = ct_attrs[TCA_CT_NAT_IPV6_MIN];
1421 struct nlattr *ipv6_max = ct_attrs[TCA_CT_NAT_IPV6_MAX];
1422 struct nlattr *port_min = ct_attrs[TCA_CT_NAT_PORT_MIN];
1423 struct nlattr *port_max = ct_attrs[TCA_CT_NAT_PORT_MAX];
1424
1425 action->ct.nat_type = TC_NAT_RESTORE;
1426 if (ct_action & TCA_CT_ACT_NAT_SRC) {
1427 action->ct.nat_type = TC_NAT_SRC;
1428 } else if (ct_action & TCA_CT_ACT_NAT_DST) {
1429 action->ct.nat_type = TC_NAT_DST;
1430 }
1431
1432 if (ipv4_min) {
1433 action->ct.range.ip_family = AF_INET;
1434 action->ct.range.ipv4.min = nl_attr_get_be32(ipv4_min);
1435 if (ipv4_max) {
1436 ovs_be32 addr = nl_attr_get_be32(ipv4_max);
1437
1438 action->ct.range.ipv4.max = addr;
1439 }
1440 } else if (ipv6_min) {
1441 action->ct.range.ip_family = AF_INET6;
1442 action->ct.range.ipv6.min
1443 = nl_attr_get_in6_addr(ipv6_min);
1444 if (ipv6_max) {
1445 struct in6_addr addr = nl_attr_get_in6_addr(ipv6_max);
1446
1447 action->ct.range.ipv6.max = addr;
1448 }
1449 }
1450
1451 if (port_min) {
1452 action->ct.range.port.min = nl_attr_get_be16(port_min);
1453 if (port_max) {
1454 action->ct.range.port.max = nl_attr_get_be16(port_max);
1455 }
1456 }
1457 }
1458 }
1459 action->type = TC_ACT_CT;
1460
1461 return 0;
1462 }
1463
1464 static const struct nl_policy vlan_policy[] = {
1465 [TCA_VLAN_PARMS] = { .type = NL_A_UNSPEC,
1466 .min_len = sizeof(struct tc_vlan),
1467 .optional = false, },
1468 [TCA_VLAN_PUSH_VLAN_ID] = { .type = NL_A_U16, .optional = true, },
1469 [TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NL_A_U16, .optional = true, },
1470 [TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NL_A_U8, .optional = true, },
1471 };
1472
1473 static int
1474 nl_parse_act_vlan(struct nlattr *options, struct tc_flower *flower)
1475 {
1476 struct nlattr *vlan_attrs[ARRAY_SIZE(vlan_policy)];
1477 const struct tc_vlan *v;
1478 const struct nlattr *vlan_parms;
1479 struct tc_action *action;
1480
1481 if (!nl_parse_nested(options, vlan_policy, vlan_attrs,
1482 ARRAY_SIZE(vlan_policy))) {
1483 VLOG_ERR_RL(&error_rl, "failed to parse vlan action options");
1484 return EPROTO;
1485 }
1486
1487 action = &flower->actions[flower->action_count++];
1488 vlan_parms = vlan_attrs[TCA_VLAN_PARMS];
1489 v = nl_attr_get_unspec(vlan_parms, sizeof *v);
1490 if (v->v_action == TCA_VLAN_ACT_PUSH) {
1491 struct nlattr *vlan_tpid = vlan_attrs[TCA_VLAN_PUSH_VLAN_PROTOCOL];
1492 struct nlattr *vlan_id = vlan_attrs[TCA_VLAN_PUSH_VLAN_ID];
1493 struct nlattr *vlan_prio = vlan_attrs[TCA_VLAN_PUSH_VLAN_PRIORITY];
1494
1495 action->vlan.vlan_push_tpid = nl_attr_get_be16(vlan_tpid);
1496 action->vlan.vlan_push_id = nl_attr_get_u16(vlan_id);
1497 action->vlan.vlan_push_prio = vlan_prio ? nl_attr_get_u8(vlan_prio) : 0;
1498 action->type = TC_ACT_VLAN_PUSH;
1499 } else if (v->v_action == TCA_VLAN_ACT_POP) {
1500 action->type = TC_ACT_VLAN_POP;
1501 } else {
1502 VLOG_ERR_RL(&error_rl, "unknown vlan action: %d, %d",
1503 v->action, v->v_action);
1504 return EINVAL;
1505 }
1506 return 0;
1507 }
1508
1509 static const struct nl_policy mpls_policy[] = {
1510 [TCA_MPLS_PARMS] = { .type = NL_A_UNSPEC,
1511 .min_len = sizeof(struct tc_mpls),
1512 .optional = false, },
1513 [TCA_MPLS_PROTO] = { .type = NL_A_U16, .optional = true, },
1514 [TCA_MPLS_LABEL] = { .type = NL_A_U32, .optional = true, },
1515 [TCA_MPLS_TC] = { .type = NL_A_U8, .optional = true, },
1516 [TCA_MPLS_TTL] = { .type = NL_A_U8, .optional = true, },
1517 [TCA_MPLS_BOS] = { .type = NL_A_U8, .optional = true, },
1518 };
1519
1520 static int
1521 nl_parse_act_mpls(struct nlattr *options, struct tc_flower *flower)
1522 {
1523 struct nlattr *mpls_attrs[ARRAY_SIZE(mpls_policy)];
1524 const struct nlattr *mpls_parms;
1525 struct nlattr *mpls_proto;
1526 struct nlattr *mpls_label;
1527 struct tc_action *action;
1528 const struct tc_mpls *m;
1529 struct nlattr *mpls_ttl;
1530 struct nlattr *mpls_bos;
1531 struct nlattr *mpls_tc;
1532
1533 if (!nl_parse_nested(options, mpls_policy, mpls_attrs,
1534 ARRAY_SIZE(mpls_policy))) {
1535 VLOG_ERR_RL(&error_rl, "failed to parse mpls action options");
1536 return EPROTO;
1537 }
1538
1539 action = &flower->actions[flower->action_count++];
1540 mpls_parms = mpls_attrs[TCA_MPLS_PARMS];
1541 m = nl_attr_get_unspec(mpls_parms, sizeof *m);
1542
1543 switch (m->m_action) {
1544 case TCA_MPLS_ACT_POP:
1545 mpls_proto = mpls_attrs[TCA_MPLS_PROTO];
1546 if (mpls_proto) {
1547 action->mpls.proto = nl_attr_get_be16(mpls_proto);
1548 }
1549 action->type = TC_ACT_MPLS_POP;
1550 break;
1551 case TCA_MPLS_ACT_PUSH:
1552 mpls_proto = mpls_attrs[TCA_MPLS_PROTO];
1553 if (mpls_proto) {
1554 action->mpls.proto = nl_attr_get_be16(mpls_proto);
1555 }
1556 mpls_label = mpls_attrs[TCA_MPLS_LABEL];
1557 if (mpls_label) {
1558 action->mpls.label = nl_attr_get_u32(mpls_label);
1559 }
1560 mpls_tc = mpls_attrs[TCA_MPLS_TC];
1561 if (mpls_tc) {
1562 action->mpls.tc = nl_attr_get_u8(mpls_tc);
1563 }
1564 mpls_ttl = mpls_attrs[TCA_MPLS_TTL];
1565 if (mpls_ttl) {
1566 action->mpls.ttl = nl_attr_get_u8(mpls_ttl);
1567 }
1568 mpls_bos = mpls_attrs[TCA_MPLS_BOS];
1569 if (mpls_bos) {
1570 action->mpls.bos = nl_attr_get_u8(mpls_bos);
1571 }
1572 action->type = TC_ACT_MPLS_PUSH;
1573 break;
1574 case TCA_MPLS_ACT_MODIFY:
1575 mpls_label = mpls_attrs[TCA_MPLS_LABEL];
1576 if (mpls_label) {
1577 action->mpls.label = nl_attr_get_u32(mpls_label);
1578 }
1579 mpls_tc = mpls_attrs[TCA_MPLS_TC];
1580 if (mpls_tc) {
1581 action->mpls.tc = nl_attr_get_u8(mpls_tc);
1582 }
1583 mpls_ttl = mpls_attrs[TCA_MPLS_TTL];
1584 if (mpls_ttl) {
1585 action->mpls.ttl = nl_attr_get_u8(mpls_ttl);
1586 }
1587 mpls_bos = mpls_attrs[TCA_MPLS_BOS];
1588 if (mpls_bos) {
1589 action->mpls.bos = nl_attr_get_u8(mpls_bos);
1590 }
1591 action->type = TC_ACT_MPLS_SET;
1592 break;
1593 default:
1594 VLOG_ERR_RL(&error_rl, "unknown mpls action: %d, %d",
1595 m->action, m->m_action);
1596 return EINVAL;
1597 }
1598
1599 return 0;
1600 }
1601
1602 static const struct nl_policy csum_policy[] = {
1603 [TCA_CSUM_PARMS] = { .type = NL_A_UNSPEC,
1604 .min_len = sizeof(struct tc_csum),
1605 .optional = false, },
1606 };
1607
1608 static int
1609 nl_parse_act_csum(struct nlattr *options, struct tc_flower *flower)
1610 {
1611 struct nlattr *csum_attrs[ARRAY_SIZE(csum_policy)];
1612 const struct tc_csum *c;
1613 const struct nlattr *csum_parms;
1614
1615 if (!nl_parse_nested(options, csum_policy, csum_attrs,
1616 ARRAY_SIZE(csum_policy))) {
1617 VLOG_ERR_RL(&error_rl, "failed to parse csum action options");
1618 return EPROTO;
1619 }
1620
1621 csum_parms = csum_attrs[TCA_CSUM_PARMS];
1622 c = nl_attr_get_unspec(csum_parms, sizeof *c);
1623
1624 /* sanity checks */
1625 if (c->update_flags != flower->csum_update_flags) {
1626 VLOG_WARN_RL(&error_rl,
1627 "expected different act csum flags: 0x%x != 0x%x",
1628 flower->csum_update_flags, c->update_flags);
1629 return EINVAL;
1630 }
1631 flower->csum_update_flags = 0; /* so we know csum was handled */
1632
1633 if (flower->needs_full_ip_proto_mask
1634 && flower->mask.ip_proto != UINT8_MAX) {
1635 VLOG_WARN_RL(&error_rl, "expected full matching on flower ip_proto");
1636 return EINVAL;
1637 }
1638
1639 return 0;
1640 }
1641
1642 static const struct nl_policy act_policy[] = {
1643 [TCA_ACT_KIND] = { .type = NL_A_STRING, .optional = false, },
1644 [TCA_ACT_COOKIE] = { .type = NL_A_UNSPEC, .optional = true, },
1645 [TCA_ACT_OPTIONS] = { .type = NL_A_NESTED, .optional = true, },
1646 [TCA_ACT_STATS] = { .type = NL_A_NESTED, .optional = false, },
1647 };
1648
1649 static const struct nl_policy stats_policy[] = {
1650 [TCA_STATS_BASIC] = { .type = NL_A_UNSPEC,
1651 .min_len = sizeof(struct gnet_stats_basic),
1652 .optional = false, },
1653 };
1654
1655 static int
1656 nl_parse_single_action(struct nlattr *action, struct tc_flower *flower,
1657 bool terse)
1658 {
1659 struct nlattr *act_options;
1660 struct nlattr *act_stats;
1661 struct nlattr *act_cookie;
1662 const char *act_kind;
1663 struct nlattr *action_attrs[ARRAY_SIZE(act_policy)];
1664 struct nlattr *stats_attrs[ARRAY_SIZE(stats_policy)];
1665 struct ovs_flow_stats *stats = &flower->stats;
1666 const struct gnet_stats_basic *bs;
1667 int err = 0;
1668
1669 if (!nl_parse_nested(action, act_policy, action_attrs,
1670 ARRAY_SIZE(act_policy)) ||
1671 (!terse && !action_attrs[TCA_ACT_OPTIONS])) {
1672 VLOG_ERR_RL(&error_rl, "failed to parse single action options");
1673 return EPROTO;
1674 }
1675
1676 act_kind = nl_attr_get_string(action_attrs[TCA_ACT_KIND]);
1677 act_options = action_attrs[TCA_ACT_OPTIONS];
1678 act_cookie = action_attrs[TCA_ACT_COOKIE];
1679
1680 if (terse) {
1681 /* Terse dump doesn't provide act options attribute. */
1682 } else if (!strcmp(act_kind, "gact")) {
1683 err = nl_parse_act_gact(act_options, flower);
1684 } else if (!strcmp(act_kind, "mirred")) {
1685 err = nl_parse_act_mirred(act_options, flower);
1686 } else if (!strcmp(act_kind, "vlan")) {
1687 err = nl_parse_act_vlan(act_options, flower);
1688 } else if (!strcmp(act_kind, "mpls")) {
1689 err = nl_parse_act_mpls(act_options, flower);
1690 } else if (!strcmp(act_kind, "tunnel_key")) {
1691 err = nl_parse_act_tunnel_key(act_options, flower);
1692 } else if (!strcmp(act_kind, "pedit")) {
1693 err = nl_parse_act_pedit(act_options, flower);
1694 } else if (!strcmp(act_kind, "csum")) {
1695 nl_parse_act_csum(act_options, flower);
1696 } else if (!strcmp(act_kind, "skbedit")) {
1697 /* Added for TC rule only (not in OvS rule) so ignore. */
1698 } else if (!strcmp(act_kind, "ct")) {
1699 nl_parse_act_ct(act_options, flower);
1700 } else {
1701 VLOG_ERR_RL(&error_rl, "unknown tc action kind: %s", act_kind);
1702 err = EINVAL;
1703 }
1704
1705 if (err) {
1706 return err;
1707 }
1708
1709 if (act_cookie) {
1710 flower->act_cookie.data = nl_attr_get(act_cookie);
1711 flower->act_cookie.len = nl_attr_get_size(act_cookie);
1712 }
1713
1714 act_stats = action_attrs[TCA_ACT_STATS];
1715
1716 if (!nl_parse_nested(act_stats, stats_policy, stats_attrs,
1717 ARRAY_SIZE(stats_policy))) {
1718 VLOG_ERR_RL(&error_rl, "failed to parse action stats policy");
1719 return EPROTO;
1720 }
1721
1722 bs = nl_attr_get_unspec(stats_attrs[TCA_STATS_BASIC], sizeof *bs);
1723 if (bs->packets) {
1724 put_32aligned_u64(&stats->n_packets, bs->packets);
1725 put_32aligned_u64(&stats->n_bytes, bs->bytes);
1726 }
1727
1728 return 0;
1729 }
1730
1731 #define TCA_ACT_MIN_PRIO 1
1732
1733 static int
1734 nl_parse_flower_actions(struct nlattr **attrs, struct tc_flower *flower,
1735 bool terse)
1736 {
1737 const struct nlattr *actions = attrs[TCA_FLOWER_ACT];
1738 static struct nl_policy actions_orders_policy[TCA_ACT_MAX_NUM + 1] = {};
1739 struct nlattr *actions_orders[ARRAY_SIZE(actions_orders_policy)];
1740 const int max_size = ARRAY_SIZE(actions_orders_policy);
1741
1742 for (int i = TCA_ACT_MIN_PRIO; i < max_size; i++) {
1743 actions_orders_policy[i].type = NL_A_NESTED;
1744 actions_orders_policy[i].optional = true;
1745 }
1746
1747 if (!nl_parse_nested(actions, actions_orders_policy, actions_orders,
1748 ARRAY_SIZE(actions_orders_policy))) {
1749 VLOG_ERR_RL(&error_rl, "failed to parse flower order of actions");
1750 return EPROTO;
1751 }
1752
1753 for (int i = TCA_ACT_MIN_PRIO; i < max_size; i++) {
1754 if (actions_orders[i]) {
1755 int err;
1756
1757 if (flower->action_count >= TCA_ACT_MAX_NUM) {
1758 VLOG_DBG_RL(&error_rl, "Can only support %d actions", TCA_ACT_MAX_NUM);
1759 return EOPNOTSUPP;
1760 }
1761 err = nl_parse_single_action(actions_orders[i], flower, terse);
1762
1763 if (err) {
1764 return err;
1765 }
1766 }
1767 }
1768
1769 if (flower->csum_update_flags) {
1770 VLOG_WARN_RL(&error_rl,
1771 "expected act csum with flags: 0x%x",
1772 flower->csum_update_flags);
1773 return EINVAL;
1774 }
1775
1776 return 0;
1777 }
1778
1779 static int
1780 nl_parse_flower_options(struct nlattr *nl_options, struct tc_flower *flower,
1781 bool terse)
1782 {
1783 struct nlattr *attrs[ARRAY_SIZE(tca_flower_policy)];
1784 int err;
1785
1786 if (terse) {
1787 if (!nl_parse_nested(nl_options, tca_flower_terse_policy,
1788 attrs, ARRAY_SIZE(tca_flower_terse_policy))) {
1789 VLOG_ERR_RL(&error_rl, "failed to parse flower classifier terse options");
1790 return EPROTO;
1791 }
1792 goto skip_flower_opts;
1793 }
1794
1795 if (!nl_parse_nested(nl_options, tca_flower_policy,
1796 attrs, ARRAY_SIZE(tca_flower_policy))) {
1797 VLOG_ERR_RL(&error_rl, "failed to parse flower classifier options");
1798 return EPROTO;
1799 }
1800
1801 nl_parse_flower_eth(attrs, flower);
1802 nl_parse_flower_arp(attrs, flower);
1803 nl_parse_flower_mpls(attrs, flower);
1804 nl_parse_flower_vlan(attrs, flower);
1805 nl_parse_flower_ip(attrs, flower);
1806 err = nl_parse_flower_tunnel(attrs, flower);
1807 if (err) {
1808 return err;
1809 }
1810
1811 skip_flower_opts:
1812 nl_parse_flower_flags(attrs, flower);
1813 return nl_parse_flower_actions(attrs, flower, terse);
1814 }
1815
1816 int
1817 parse_netlink_to_tc_flower(struct ofpbuf *reply, struct tcf_id *id,
1818 struct tc_flower *flower, bool terse)
1819 {
1820 struct tcmsg *tc;
1821 struct nlattr *ta[ARRAY_SIZE(tca_policy)];
1822 const char *kind;
1823
1824 if (NLMSG_HDRLEN + sizeof *tc > reply->size) {
1825 return EPROTO;
1826 }
1827
1828 memset(flower, 0, sizeof *flower);
1829
1830 tc = ofpbuf_at_assert(reply, NLMSG_HDRLEN, sizeof *tc);
1831
1832 flower->key.eth_type = (OVS_FORCE ovs_be16) tc_get_minor(tc->tcm_info);
1833 flower->mask.eth_type = OVS_BE16_MAX;
1834 id->prio = tc_get_major(tc->tcm_info);
1835 id->handle = tc->tcm_handle;
1836
1837 if (id->prio == TC_RESERVED_PRIORITY_POLICE) {
1838 return 0;
1839 }
1840
1841 if (!id->handle) {
1842 return EAGAIN;
1843 }
1844
1845 if (!nl_policy_parse(reply, NLMSG_HDRLEN + sizeof *tc,
1846 tca_policy, ta, ARRAY_SIZE(ta))) {
1847 VLOG_ERR_RL(&error_rl, "failed to parse tca policy");
1848 return EPROTO;
1849 }
1850
1851 if (ta[TCA_CHAIN]) {
1852 id->chain = nl_attr_get_u32(ta[TCA_CHAIN]);
1853 }
1854
1855 kind = nl_attr_get_string(ta[TCA_KIND]);
1856 if (strcmp(kind, "flower")) {
1857 VLOG_DBG_ONCE("Unsupported filter: %s", kind);
1858 return EPROTO;
1859 }
1860
1861 return nl_parse_flower_options(ta[TCA_OPTIONS], flower, terse);
1862 }
1863
1864 int
1865 tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump, bool terse)
1866 {
1867 struct ofpbuf request;
1868
1869 request_from_tcf_id(id, 0, RTM_GETTFILTER, NLM_F_DUMP, &request);
1870 if (terse) {
1871 struct nla_bitfield32 dump_flags = { TCA_DUMP_FLAGS_TERSE,
1872 TCA_DUMP_FLAGS_TERSE };
1873
1874 nl_msg_put_unspec(&request, TCA_DUMP_FLAGS, &dump_flags,
1875 sizeof dump_flags);
1876 }
1877 nl_dump_start(dump, NETLINK_ROUTE, &request);
1878 ofpbuf_uninit(&request);
1879
1880 return 0;
1881 }
1882
1883 int
1884 tc_del_filter(struct tcf_id *id)
1885 {
1886 struct ofpbuf request;
1887
1888 request_from_tcf_id(id, 0, RTM_DELTFILTER, NLM_F_ACK, &request);
1889 return tc_transact(&request, NULL);
1890 }
1891
1892 int
1893 tc_get_flower(struct tcf_id *id, struct tc_flower *flower)
1894 {
1895 struct ofpbuf request;
1896 struct ofpbuf *reply;
1897 int error;
1898
1899 request_from_tcf_id(id, 0, RTM_GETTFILTER, NLM_F_ECHO, &request);
1900 error = tc_transact(&request, &reply);
1901 if (error) {
1902 return error;
1903 }
1904
1905 error = parse_netlink_to_tc_flower(reply, id, flower, false);
1906 ofpbuf_delete(reply);
1907 return error;
1908 }
1909
1910 static int
1911 tc_get_tc_cls_policy(enum tc_offload_policy policy)
1912 {
1913 if (policy == TC_POLICY_SKIP_HW) {
1914 return TCA_CLS_FLAGS_SKIP_HW;
1915 } else if (policy == TC_POLICY_SKIP_SW) {
1916 return TCA_CLS_FLAGS_SKIP_SW;
1917 }
1918
1919 return 0;
1920 }
1921
1922 static void
1923 nl_msg_put_act_csum(struct ofpbuf *request, uint32_t flags)
1924 {
1925 size_t offset;
1926
1927 nl_msg_put_string(request, TCA_ACT_KIND, "csum");
1928 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
1929 {
1930 struct tc_csum parm = { .action = TC_ACT_PIPE,
1931 .update_flags = flags };
1932
1933 nl_msg_put_unspec(request, TCA_CSUM_PARMS, &parm, sizeof parm);
1934 }
1935 nl_msg_end_nested(request, offset);
1936 }
1937
1938 static void
1939 nl_msg_put_act_pedit(struct ofpbuf *request, struct tc_pedit *parm,
1940 struct tc_pedit_key_ex *ex)
1941 {
1942 size_t ksize = sizeof *parm + parm->nkeys * sizeof(struct tc_pedit_key);
1943 size_t offset, offset_keys_ex, offset_key;
1944 int i;
1945
1946 nl_msg_put_string(request, TCA_ACT_KIND, "pedit");
1947 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
1948 {
1949 parm->action = TC_ACT_PIPE;
1950
1951 nl_msg_put_unspec(request, TCA_PEDIT_PARMS_EX, parm, ksize);
1952 offset_keys_ex = nl_msg_start_nested(request, TCA_PEDIT_KEYS_EX);
1953 for (i = 0; i < parm->nkeys; i++, ex++) {
1954 offset_key = nl_msg_start_nested(request, TCA_PEDIT_KEY_EX);
1955 nl_msg_put_u16(request, TCA_PEDIT_KEY_EX_HTYPE, ex->htype);
1956 nl_msg_put_u16(request, TCA_PEDIT_KEY_EX_CMD, ex->cmd);
1957 nl_msg_end_nested(request, offset_key);
1958 }
1959 nl_msg_end_nested(request, offset_keys_ex);
1960 }
1961 nl_msg_end_nested(request, offset);
1962 }
1963
1964 static void
1965 nl_msg_put_act_push_vlan(struct ofpbuf *request, ovs_be16 tpid,
1966 uint16_t vid, uint8_t prio)
1967 {
1968 size_t offset;
1969
1970 nl_msg_put_string(request, TCA_ACT_KIND, "vlan");
1971 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
1972 {
1973 struct tc_vlan parm = { .action = TC_ACT_PIPE,
1974 .v_action = TCA_VLAN_ACT_PUSH };
1975
1976 nl_msg_put_unspec(request, TCA_VLAN_PARMS, &parm, sizeof parm);
1977 nl_msg_put_be16(request, TCA_VLAN_PUSH_VLAN_PROTOCOL, tpid);
1978 nl_msg_put_u16(request, TCA_VLAN_PUSH_VLAN_ID, vid);
1979 nl_msg_put_u8(request, TCA_VLAN_PUSH_VLAN_PRIORITY, prio);
1980 }
1981 nl_msg_end_nested(request, offset);
1982 }
1983
1984 static void
1985 nl_msg_put_act_pop_vlan(struct ofpbuf *request)
1986 {
1987 size_t offset;
1988
1989 nl_msg_put_string(request, TCA_ACT_KIND, "vlan");
1990 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
1991 {
1992 struct tc_vlan parm = { .action = TC_ACT_PIPE,
1993 .v_action = TCA_VLAN_ACT_POP };
1994
1995 nl_msg_put_unspec(request, TCA_VLAN_PARMS, &parm, sizeof parm);
1996 }
1997 nl_msg_end_nested(request, offset);
1998 }
1999
2000 static void
2001 nl_msg_put_act_pop_mpls(struct ofpbuf *request, ovs_be16 proto)
2002 {
2003 size_t offset;
2004
2005 nl_msg_put_string(request, TCA_ACT_KIND, "mpls");
2006 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS | NLA_F_NESTED);
2007 {
2008 struct tc_mpls parm = { .action = TC_ACT_PIPE,
2009 .m_action = TCA_MPLS_ACT_POP };
2010
2011 nl_msg_put_unspec(request, TCA_MPLS_PARMS, &parm, sizeof parm);
2012 nl_msg_put_be16(request, TCA_MPLS_PROTO, proto);
2013 }
2014 nl_msg_end_nested(request, offset);
2015 }
2016
2017 static void
2018 nl_msg_put_act_push_mpls(struct ofpbuf *request, ovs_be16 proto,
2019 uint32_t label, uint8_t tc, uint8_t ttl, uint8_t bos)
2020 {
2021 size_t offset;
2022
2023 nl_msg_put_string(request, TCA_ACT_KIND, "mpls");
2024 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS | NLA_F_NESTED);
2025 {
2026 struct tc_mpls parm = { .action = TC_ACT_PIPE,
2027 .m_action = TCA_MPLS_ACT_PUSH };
2028
2029 nl_msg_put_unspec(request, TCA_MPLS_PARMS, &parm, sizeof parm);
2030 nl_msg_put_be16(request, TCA_MPLS_PROTO, proto);
2031 nl_msg_put_u32(request, TCA_MPLS_LABEL, label);
2032 nl_msg_put_u8(request, TCA_MPLS_TC, tc);
2033 nl_msg_put_u8(request, TCA_MPLS_TTL, ttl);
2034 nl_msg_put_u8(request, TCA_MPLS_BOS, bos);
2035 }
2036 nl_msg_end_nested(request, offset);
2037 }
2038
2039 static void
2040 nl_msg_put_act_set_mpls(struct ofpbuf *request, uint32_t label, uint8_t tc,
2041 uint8_t ttl, uint8_t bos)
2042 {
2043 size_t offset;
2044
2045 nl_msg_put_string(request, TCA_ACT_KIND, "mpls");
2046 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS | NLA_F_NESTED);
2047 {
2048 struct tc_mpls parm = { .action = TC_ACT_PIPE,
2049 .m_action = TCA_MPLS_ACT_MODIFY };
2050
2051 nl_msg_put_unspec(request, TCA_MPLS_PARMS, &parm, sizeof parm);
2052 nl_msg_put_u32(request, TCA_MPLS_LABEL, label);
2053 nl_msg_put_u8(request, TCA_MPLS_TC, tc);
2054 nl_msg_put_u8(request, TCA_MPLS_TTL, ttl);
2055 nl_msg_put_u8(request, TCA_MPLS_BOS, bos);
2056 }
2057 nl_msg_end_nested(request, offset);
2058 }
2059
2060 static void
2061 nl_msg_put_act_tunnel_key_release(struct ofpbuf *request)
2062 {
2063 size_t offset;
2064
2065 nl_msg_put_string(request, TCA_ACT_KIND, "tunnel_key");
2066 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
2067 {
2068 struct tc_tunnel_key tun = { .action = TC_ACT_PIPE,
2069 .t_action = TCA_TUNNEL_KEY_ACT_RELEASE };
2070
2071 nl_msg_put_unspec(request, TCA_TUNNEL_KEY_PARMS, &tun, sizeof tun);
2072 }
2073 nl_msg_end_nested(request, offset);
2074 }
2075
2076 static void
2077 nl_msg_put_act_tunnel_geneve_option(struct ofpbuf *request,
2078 struct tun_metadata tun_metadata)
2079 {
2080 const struct geneve_opt *opt;
2081 size_t outer, inner;
2082 int len, cnt = 0;
2083
2084 len = tun_metadata.present.len;
2085 if (!len) {
2086 return;
2087 }
2088
2089 outer = nl_msg_start_nested(request, TCA_TUNNEL_KEY_ENC_OPTS);
2090
2091 while (len) {
2092 opt = &tun_metadata.opts.gnv[cnt];
2093 inner = nl_msg_start_nested(request, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE);
2094
2095 nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS,
2096 opt->opt_class);
2097 nl_msg_put_u8(request, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE, opt->type);
2098 nl_msg_put_unspec(request, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA, opt + 1,
2099 opt->length * 4);
2100
2101 cnt += sizeof(struct geneve_opt) / 4 + opt->length;
2102 len -= sizeof(struct geneve_opt) + opt->length * 4;
2103
2104 nl_msg_end_nested(request, inner);
2105 }
2106
2107 nl_msg_end_nested(request, outer);
2108 }
2109
2110 static void
2111 nl_msg_put_act_tunnel_key_set(struct ofpbuf *request, bool id_present,
2112 ovs_be64 id, ovs_be32 ipv4_src,
2113 ovs_be32 ipv4_dst, struct in6_addr *ipv6_src,
2114 struct in6_addr *ipv6_dst,
2115 ovs_be16 tp_dst, uint8_t tos, uint8_t ttl,
2116 struct tun_metadata tun_metadata,
2117 uint8_t no_csum)
2118 {
2119 size_t offset;
2120
2121 nl_msg_put_string(request, TCA_ACT_KIND, "tunnel_key");
2122 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
2123 {
2124 struct tc_tunnel_key tun = { .action = TC_ACT_PIPE,
2125 .t_action = TCA_TUNNEL_KEY_ACT_SET };
2126
2127 nl_msg_put_unspec(request, TCA_TUNNEL_KEY_PARMS, &tun, sizeof tun);
2128
2129 ovs_be32 id32 = be64_to_be32(id);
2130 if (id_present) {
2131 nl_msg_put_be32(request, TCA_TUNNEL_KEY_ENC_KEY_ID, id32);
2132 }
2133 if (ipv4_dst) {
2134 nl_msg_put_be32(request, TCA_TUNNEL_KEY_ENC_IPV4_SRC, ipv4_src);
2135 nl_msg_put_be32(request, TCA_TUNNEL_KEY_ENC_IPV4_DST, ipv4_dst);
2136 } else if (ipv6_addr_is_set(ipv6_dst)) {
2137 nl_msg_put_in6_addr(request, TCA_TUNNEL_KEY_ENC_IPV6_DST,
2138 ipv6_dst);
2139 nl_msg_put_in6_addr(request, TCA_TUNNEL_KEY_ENC_IPV6_SRC,
2140 ipv6_src);
2141 }
2142 if (tos) {
2143 nl_msg_put_u8(request, TCA_TUNNEL_KEY_ENC_TOS, tos);
2144 }
2145 if (ttl) {
2146 nl_msg_put_u8(request, TCA_TUNNEL_KEY_ENC_TTL, ttl);
2147 }
2148 if (tp_dst) {
2149 nl_msg_put_be16(request, TCA_TUNNEL_KEY_ENC_DST_PORT, tp_dst);
2150 }
2151 nl_msg_put_act_tunnel_geneve_option(request, tun_metadata);
2152 nl_msg_put_u8(request, TCA_TUNNEL_KEY_NO_CSUM, no_csum);
2153 }
2154 nl_msg_end_nested(request, offset);
2155 }
2156
2157 static void
2158 nl_msg_put_act_gact(struct ofpbuf *request, uint32_t chain)
2159 {
2160 size_t offset;
2161
2162 nl_msg_put_string(request, TCA_ACT_KIND, "gact");
2163 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
2164 {
2165 struct tc_gact p = { .action = TC_ACT_SHOT };
2166
2167 if (chain) {
2168 p.action = TC_ACT_GOTO_CHAIN | chain;
2169 }
2170
2171 nl_msg_put_unspec(request, TCA_GACT_PARMS, &p, sizeof p);
2172 }
2173 nl_msg_end_nested(request, offset);
2174 }
2175
2176 static void
2177 nl_msg_put_act_ct(struct ofpbuf *request, struct tc_action *action)
2178 {
2179 uint16_t ct_action = 0;
2180 size_t offset;
2181
2182 nl_msg_put_string(request, TCA_ACT_KIND, "ct");
2183 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS | NLA_F_NESTED);
2184 {
2185 struct tc_ct ct = {
2186 .action = TC_ACT_PIPE,
2187 };
2188
2189 if (!action->ct.clear) {
2190 if (action->ct.zone) {
2191 nl_msg_put_u16(request, TCA_CT_ZONE, action->ct.zone);
2192 }
2193
2194 if (!is_all_zeros(&action->ct.label_mask,
2195 sizeof action->ct.label_mask)) {
2196 nl_msg_put_u128(request, TCA_CT_LABELS,
2197 action->ct.label);
2198 nl_msg_put_u128(request, TCA_CT_LABELS_MASK,
2199 action->ct.label_mask);
2200 }
2201
2202 if (action->ct.mark_mask) {
2203 nl_msg_put_u32(request, TCA_CT_MARK,
2204 action->ct.mark);
2205 nl_msg_put_u32(request, TCA_CT_MARK_MASK,
2206 action->ct.mark_mask);
2207 }
2208
2209 if (action->ct.commit) {
2210 ct_action = TCA_CT_ACT_COMMIT;
2211 if (action->ct.force) {
2212 ct_action |= TCA_CT_ACT_FORCE;
2213 }
2214 }
2215
2216 if (action->ct.nat_type) {
2217 ct_action |= TCA_CT_ACT_NAT;
2218
2219 if (action->ct.nat_type == TC_NAT_SRC) {
2220 ct_action |= TCA_CT_ACT_NAT_SRC;
2221 } else if (action->ct.nat_type == TC_NAT_DST) {
2222 ct_action |= TCA_CT_ACT_NAT_DST;
2223 }
2224
2225 if (action->ct.range.ip_family == AF_INET) {
2226 nl_msg_put_be32(request, TCA_CT_NAT_IPV4_MIN,
2227 action->ct.range.ipv4.min);
2228 if (action->ct.range.ipv4.max) {
2229 nl_msg_put_be32(request, TCA_CT_NAT_IPV4_MAX,
2230 action->ct.range.ipv4.max);
2231 }
2232 } else if (action->ct.range.ip_family == AF_INET6) {
2233
2234 nl_msg_put_in6_addr(request, TCA_CT_NAT_IPV6_MIN,
2235 &action->ct.range.ipv6.min);
2236 if (ipv6_addr_is_set(&action->ct.range.ipv6.max)) {
2237 nl_msg_put_in6_addr(request, TCA_CT_NAT_IPV6_MAX,
2238 &action->ct.range.ipv6.max);
2239 }
2240 }
2241
2242 if (action->ct.range.port.min) {
2243 nl_msg_put_be16(request, TCA_CT_NAT_PORT_MIN,
2244 action->ct.range.port.min);
2245 if (action->ct.range.port.max) {
2246 nl_msg_put_be16(request, TCA_CT_NAT_PORT_MAX,
2247 action->ct.range.port.max);
2248 }
2249 }
2250 }
2251 } else {
2252 ct_action = TCA_CT_ACT_CLEAR;
2253 }
2254
2255 nl_msg_put_u16(request, TCA_CT_ACTION, ct_action);
2256 nl_msg_put_unspec(request, TCA_CT_PARMS, &ct, sizeof ct);
2257 }
2258 nl_msg_end_nested(request, offset);
2259 }
2260
2261 static void
2262 nl_msg_put_act_skbedit_to_host(struct ofpbuf *request)
2263 {
2264 size_t offset;
2265
2266 nl_msg_put_string(request, TCA_ACT_KIND, "skbedit");
2267 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
2268 {
2269 struct tc_skbedit s = { .action = TC_ACT_PIPE };
2270
2271 nl_msg_put_unspec(request, TCA_SKBEDIT_PARMS, &s, sizeof s);
2272 nl_msg_put_be16(request, TCA_SKBEDIT_PTYPE, PACKET_HOST);
2273 }
2274 nl_msg_end_nested(request, offset);
2275 }
2276
2277 static void
2278 nl_msg_put_act_mirred(struct ofpbuf *request, int ifindex, int action,
2279 int eaction)
2280 {
2281 size_t offset;
2282
2283 nl_msg_put_string(request, TCA_ACT_KIND, "mirred");
2284 offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
2285 {
2286 struct tc_mirred m = { .action = action,
2287 .eaction = eaction,
2288 .ifindex = ifindex };
2289
2290 nl_msg_put_unspec(request, TCA_MIRRED_PARMS, &m, sizeof m);
2291 }
2292 nl_msg_end_nested(request, offset);
2293 }
2294
2295 static inline void
2296 nl_msg_put_act_cookie(struct ofpbuf *request, struct tc_cookie *ck) {
2297 if (ck->len) {
2298 nl_msg_put_unspec(request, TCA_ACT_COOKIE, ck->data, ck->len);
2299 }
2300 }
2301
2302 static inline void
2303 nl_msg_put_act_flags(struct ofpbuf *request) {
2304 struct nla_bitfield32 act_flags = { TCA_ACT_FLAGS_NO_PERCPU_STATS,
2305 TCA_ACT_FLAGS_NO_PERCPU_STATS };
2306
2307 nl_msg_put_unspec(request, TCA_ACT_FLAGS, &act_flags, sizeof act_flags);
2308 }
2309
2310 /* Given flower, a key_to_pedit map entry, calculates the rest,
2311 * where:
2312 *
2313 * mask, data - pointers of where read the first word of flower->key/mask.
2314 * current_offset - which offset to use for the first pedit action.
2315 * cnt - max pedits actions to use.
2316 * first_word_mask/last_word_mask - the mask to use for the first/last read
2317 * (as we read entire words). */
2318 static void
2319 calc_offsets(struct tc_flower *flower, struct flower_key_to_pedit *m,
2320 int *cur_offset, int *cnt, ovs_be32 *last_word_mask,
2321 ovs_be32 *first_word_mask, ovs_be32 **mask, ovs_be32 **data)
2322 {
2323 int start_offset, max_offset, total_size;
2324 int diff, right_zero_bits, left_zero_bits;
2325 char *rewrite_key = (void *) &flower->rewrite.key;
2326 char *rewrite_mask = (void *) &flower->rewrite.mask;
2327
2328 max_offset = m->offset + m->size;
2329 start_offset = ROUND_DOWN(m->offset, 4);
2330 diff = m->offset - start_offset;
2331 total_size = max_offset - start_offset;
2332 right_zero_bits = 8 * (4 - ((max_offset % 4) ? : 4));
2333 left_zero_bits = 8 * (m->offset - start_offset);
2334
2335 *cur_offset = start_offset;
2336 *cnt = (total_size / 4) + (total_size % 4 ? 1 : 0);
2337 *last_word_mask = htonl(UINT32_MAX << right_zero_bits);
2338 *first_word_mask = htonl(UINT32_MAX >> left_zero_bits);
2339 *data = (void *) (rewrite_key + m->flower_offset - diff);
2340 *mask = (void *) (rewrite_mask + m->flower_offset - diff);
2341 }
2342
2343 static inline int
2344 csum_update_flag(struct tc_flower *flower,
2345 enum pedit_header_type htype) {
2346 /* Explictily specifiy the csum flags so HW can return EOPNOTSUPP
2347 * if it doesn't support a checksum recalculation of some headers.
2348 * And since OVS allows a flow such as
2349 * eth(dst=<mac>),eth_type(0x0800) actions=set(ipv4(src=<new_ip>))
2350 * we need to force a more specific flow as this can, for example,
2351 * need a recalculation of icmp checksum if the packet that passes
2352 * is ICMPv6 and tcp checksum if its tcp. */
2353
2354 switch (htype) {
2355 case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
2356 flower->csum_update_flags |= TCA_CSUM_UPDATE_FLAG_IPV4HDR;
2357 /* Fall through. */
2358 case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
2359 case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
2360 case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
2361 if (flower->key.ip_proto == IPPROTO_TCP) {
2362 flower->needs_full_ip_proto_mask = true;
2363 flower->csum_update_flags |= TCA_CSUM_UPDATE_FLAG_TCP;
2364 } else if (flower->key.ip_proto == IPPROTO_UDP) {
2365 flower->needs_full_ip_proto_mask = true;
2366 flower->csum_update_flags |= TCA_CSUM_UPDATE_FLAG_UDP;
2367 } else if (flower->key.ip_proto == IPPROTO_ICMP) {
2368 flower->needs_full_ip_proto_mask = true;
2369 } else if (flower->key.ip_proto == IPPROTO_ICMPV6) {
2370 flower->needs_full_ip_proto_mask = true;
2371 flower->csum_update_flags |= TCA_CSUM_UPDATE_FLAG_ICMP;
2372 } else {
2373 VLOG_WARN_RL(&error_rl,
2374 "can't offload rewrite of IP/IPV6 with ip_proto: %d",
2375 flower->key.ip_proto);
2376 break;
2377 }
2378 /* Fall through. */
2379 case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
2380 return 0; /* success */
2381
2382 case TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK:
2383 case __PEDIT_HDR_TYPE_MAX:
2384 default:
2385 break;
2386 }
2387
2388 return EOPNOTSUPP;
2389 }
2390
2391 static int
2392 nl_msg_put_flower_rewrite_pedits(struct ofpbuf *request,
2393 struct tc_flower *flower)
2394 {
2395 struct {
2396 struct tc_pedit sel;
2397 struct tc_pedit_key keys[MAX_PEDIT_OFFSETS];
2398 struct tc_pedit_key_ex keys_ex[MAX_PEDIT_OFFSETS];
2399 } sel = {
2400 .sel = {
2401 .nkeys = 0
2402 }
2403 };
2404 int i, j, err;
2405
2406 for (i = 0; i < ARRAY_SIZE(flower_pedit_map); i++) {
2407 struct flower_key_to_pedit *m = &flower_pedit_map[i];
2408 struct tc_pedit_key *pedit_key = NULL;
2409 struct tc_pedit_key_ex *pedit_key_ex = NULL;
2410 ovs_be32 *mask, *data, first_word_mask, last_word_mask;
2411 int cnt = 0, cur_offset = 0;
2412
2413 if (!m->size) {
2414 continue;
2415 }
2416
2417 calc_offsets(flower, m, &cur_offset, &cnt, &last_word_mask,
2418 &first_word_mask, &mask, &data);
2419
2420 for (j = 0; j < cnt; j++, mask++, data++, cur_offset += 4) {
2421 ovs_be32 mask_word = *mask;
2422 ovs_be32 data_word = *data;
2423
2424 if (j == 0) {
2425 mask_word &= first_word_mask;
2426 }
2427 if (j == cnt - 1) {
2428 mask_word &= last_word_mask;
2429 }
2430 if (!mask_word) {
2431 continue;
2432 }
2433 if (sel.sel.nkeys == MAX_PEDIT_OFFSETS) {
2434 VLOG_WARN_RL(&error_rl, "reached too many pedit offsets: %d",
2435 MAX_PEDIT_OFFSETS);
2436 return EOPNOTSUPP;
2437 }
2438
2439 pedit_key = &sel.keys[sel.sel.nkeys];
2440 pedit_key_ex = &sel.keys_ex[sel.sel.nkeys];
2441 pedit_key_ex->cmd = TCA_PEDIT_KEY_EX_CMD_SET;
2442 pedit_key_ex->htype = m->htype;
2443 pedit_key->off = cur_offset;
2444 mask_word = htonl(ntohl(mask_word) >> m->boundary_shift);
2445 data_word = htonl(ntohl(data_word) >> m->boundary_shift);
2446 pedit_key->mask = ~mask_word;
2447 pedit_key->val = data_word & mask_word;
2448 sel.sel.nkeys++;
2449
2450 err = csum_update_flag(flower, m->htype);
2451 if (err) {
2452 return err;
2453 }
2454
2455 if (flower->needs_full_ip_proto_mask) {
2456 flower->mask.ip_proto = UINT8_MAX;
2457 }
2458 }
2459 }
2460 nl_msg_put_act_pedit(request, &sel.sel, sel.keys_ex);
2461
2462 return 0;
2463 }
2464
2465 static int
2466 nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower)
2467 {
2468 bool ingress, released = false;
2469 size_t offset;
2470 size_t act_offset;
2471 uint16_t act_index = 1;
2472 struct tc_action *action;
2473 int i, ifindex = 0;
2474
2475 offset = nl_msg_start_nested(request, TCA_FLOWER_ACT);
2476 {
2477 int error;
2478
2479 action = flower->actions;
2480 for (i = 0; i < flower->action_count; i++, action++) {
2481 switch (action->type) {
2482 case TC_ACT_PEDIT: {
2483 act_offset = nl_msg_start_nested(request, act_index++);
2484 error = nl_msg_put_flower_rewrite_pedits(request, flower);
2485 if (error) {
2486 return error;
2487 }
2488 nl_msg_end_nested(request, act_offset);
2489
2490 if (flower->csum_update_flags) {
2491 act_offset = nl_msg_start_nested(request, act_index++);
2492 nl_msg_put_act_csum(request, flower->csum_update_flags);
2493 nl_msg_put_act_flags(request);
2494 nl_msg_end_nested(request, act_offset);
2495 }
2496 }
2497 break;
2498 case TC_ACT_ENCAP: {
2499 act_offset = nl_msg_start_nested(request, act_index++);
2500 nl_msg_put_act_tunnel_key_set(request, action->encap.id_present,
2501 action->encap.id,
2502 action->encap.ipv4.ipv4_src,
2503 action->encap.ipv4.ipv4_dst,
2504 &action->encap.ipv6.ipv6_src,
2505 &action->encap.ipv6.ipv6_dst,
2506 action->encap.tp_dst,
2507 action->encap.tos,
2508 action->encap.ttl,
2509 action->encap.data,
2510 action->encap.no_csum);
2511 nl_msg_put_act_flags(request);
2512 nl_msg_end_nested(request, act_offset);
2513 }
2514 break;
2515 case TC_ACT_VLAN_POP: {
2516 act_offset = nl_msg_start_nested(request, act_index++);
2517 nl_msg_put_act_pop_vlan(request);
2518 nl_msg_put_act_flags(request);
2519 nl_msg_end_nested(request, act_offset);
2520 }
2521 break;
2522 case TC_ACT_VLAN_PUSH: {
2523 act_offset = nl_msg_start_nested(request, act_index++);
2524 nl_msg_put_act_push_vlan(request,
2525 action->vlan.vlan_push_tpid,
2526 action->vlan.vlan_push_id,
2527 action->vlan.vlan_push_prio);
2528 nl_msg_put_act_flags(request);
2529 nl_msg_end_nested(request, act_offset);
2530 }
2531 break;
2532 case TC_ACT_MPLS_POP: {
2533 act_offset = nl_msg_start_nested(request, act_index++);
2534 nl_msg_put_act_pop_mpls(request, action->mpls.proto);
2535 nl_msg_end_nested(request, act_offset);
2536 }
2537 break;
2538 case TC_ACT_MPLS_PUSH: {
2539 act_offset = nl_msg_start_nested(request, act_index++);
2540 nl_msg_put_act_push_mpls(request, action->mpls.proto,
2541 action->mpls.label, action->mpls.tc,
2542 action->mpls.ttl, action->mpls.bos);
2543 nl_msg_end_nested(request, act_offset);
2544 }
2545 break;
2546 case TC_ACT_MPLS_SET: {
2547 act_offset = nl_msg_start_nested(request, act_index++);
2548 nl_msg_put_act_set_mpls(request, action->mpls.label,
2549 action->mpls.tc, action->mpls.ttl,
2550 action->mpls.bos);
2551 nl_msg_end_nested(request, act_offset);
2552 }
2553 break;
2554 case TC_ACT_OUTPUT: {
2555 if (!released && flower->tunnel) {
2556 act_offset = nl_msg_start_nested(request, act_index++);
2557 nl_msg_put_act_tunnel_key_release(request);
2558 nl_msg_end_nested(request, act_offset);
2559 released = true;
2560 }
2561
2562 ingress = action->out.ingress;
2563 ifindex = action->out.ifindex_out;
2564 if (ifindex < 1) {
2565 VLOG_ERR_RL(&error_rl, "%s: invalid ifindex: %d, type: %d",
2566 __func__, ifindex, action->type);
2567 return EINVAL;
2568 }
2569
2570 if (ingress) {
2571 /* If redirecting to ingress (internal port) ensure
2572 * pkt_type on skb is set to PACKET_HOST. */
2573 act_offset = nl_msg_start_nested(request, act_index++);
2574 nl_msg_put_act_skbedit_to_host(request);
2575 nl_msg_end_nested(request, act_offset);
2576 }
2577
2578 act_offset = nl_msg_start_nested(request, act_index++);
2579 if (i == flower->action_count - 1) {
2580 if (ingress) {
2581 nl_msg_put_act_mirred(request, ifindex, TC_ACT_STOLEN,
2582 TCA_INGRESS_REDIR);
2583 } else {
2584 nl_msg_put_act_mirred(request, ifindex, TC_ACT_STOLEN,
2585 TCA_EGRESS_REDIR);
2586 }
2587 } else {
2588 if (ingress) {
2589 nl_msg_put_act_mirred(request, ifindex, TC_ACT_PIPE,
2590 TCA_INGRESS_MIRROR);
2591 } else {
2592 nl_msg_put_act_mirred(request, ifindex, TC_ACT_PIPE,
2593 TCA_EGRESS_MIRROR);
2594 }
2595 }
2596 nl_msg_put_act_cookie(request, &flower->act_cookie);
2597 nl_msg_put_act_flags(request);
2598 nl_msg_end_nested(request, act_offset);
2599 }
2600 break;
2601 case TC_ACT_GOTO: {
2602 if (released) {
2603 /* We don't support tunnel release + output + goto
2604 * for now, as next chain by default will try and match
2605 * the tunnel metadata that was released/unset.
2606 *
2607 * This will happen with tunnel + mirror ports.
2608 */
2609 return -EOPNOTSUPP;
2610 }
2611
2612 act_offset = nl_msg_start_nested(request, act_index++);
2613 nl_msg_put_act_gact(request, action->chain);
2614 nl_msg_put_act_cookie(request, &flower->act_cookie);
2615 nl_msg_end_nested(request, act_offset);
2616 }
2617 break;
2618 case TC_ACT_CT: {
2619 act_offset = nl_msg_start_nested(request, act_index++);
2620 nl_msg_put_act_ct(request, action);
2621 nl_msg_put_act_cookie(request, &flower->act_cookie);
2622 nl_msg_end_nested(request, act_offset);
2623 }
2624 break;
2625 }
2626 }
2627 }
2628
2629 if (!flower->action_count) {
2630 act_offset = nl_msg_start_nested(request, act_index++);
2631 nl_msg_put_act_gact(request, 0);
2632 nl_msg_put_act_cookie(request, &flower->act_cookie);
2633 nl_msg_put_act_flags(request);
2634 nl_msg_end_nested(request, act_offset);
2635 }
2636 nl_msg_end_nested(request, offset);
2637
2638 return 0;
2639 }
2640
2641 static void
2642 nl_msg_put_masked_value(struct ofpbuf *request, uint16_t type,
2643 uint16_t mask_type, const void *data,
2644 const void *mask_data, size_t len)
2645 {
2646 if (mask_type != TCA_FLOWER_UNSPEC) {
2647 if (is_all_zeros(mask_data, len)) {
2648 return;
2649 }
2650 nl_msg_put_unspec(request, mask_type, mask_data, len);
2651 }
2652 nl_msg_put_unspec(request, type, data, len);
2653 }
2654
2655 static void
2656 nl_msg_put_flower_tunnel_opts(struct ofpbuf *request, uint16_t type,
2657 struct tun_metadata metadata)
2658 {
2659 struct geneve_opt *opt;
2660 size_t outer, inner;
2661 int len, cnt = 0;
2662
2663 len = metadata.present.len;
2664 if (!len) {
2665 return;
2666 }
2667
2668 outer = nl_msg_start_nested(request, type);
2669 while (len) {
2670 opt = &metadata.opts.gnv[cnt];
2671 inner = nl_msg_start_nested(request, TCA_FLOWER_KEY_ENC_OPTS_GENEVE);
2672
2673 nl_msg_put_be16(request, TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS,
2674 opt->opt_class);
2675 nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE, opt->type);
2676 nl_msg_put_unspec(request, TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA, opt + 1,
2677 opt->length * 4);
2678
2679 cnt += sizeof(struct geneve_opt) / 4 + opt->length;
2680 len -= sizeof(struct geneve_opt) + opt->length * 4;
2681
2682 nl_msg_end_nested(request, inner);
2683 }
2684 nl_msg_end_nested(request, outer);
2685 }
2686
2687 static void
2688 nl_msg_put_flower_tunnel(struct ofpbuf *request, struct tc_flower *flower)
2689 {
2690 ovs_be32 ipv4_src_mask = flower->mask.tunnel.ipv4.ipv4_src;
2691 ovs_be32 ipv4_dst_mask = flower->mask.tunnel.ipv4.ipv4_dst;
2692 ovs_be32 ipv4_src = flower->key.tunnel.ipv4.ipv4_src;
2693 ovs_be32 ipv4_dst = flower->key.tunnel.ipv4.ipv4_dst;
2694 struct in6_addr *ipv6_src_mask = &flower->mask.tunnel.ipv6.ipv6_src;
2695 struct in6_addr *ipv6_dst_mask = &flower->mask.tunnel.ipv6.ipv6_dst;
2696 struct in6_addr *ipv6_src = &flower->key.tunnel.ipv6.ipv6_src;
2697 struct in6_addr *ipv6_dst = &flower->key.tunnel.ipv6.ipv6_dst;
2698 ovs_be16 tp_dst = flower->key.tunnel.tp_dst;
2699 ovs_be32 id = be64_to_be32(flower->key.tunnel.id);
2700 uint8_t tos = flower->key.tunnel.tos;
2701 uint8_t ttl = flower->key.tunnel.ttl;
2702 uint8_t tos_mask = flower->mask.tunnel.tos;
2703 uint8_t ttl_mask = flower->mask.tunnel.ttl;
2704 ovs_be64 id_mask = flower->mask.tunnel.id;
2705
2706 if (ipv4_dst_mask || ipv4_src_mask) {
2707 nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
2708 ipv4_dst_mask);
2709 nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,
2710 ipv4_src_mask);
2711 nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_IPV4_DST, ipv4_dst);
2712 nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_IPV4_SRC, ipv4_src);
2713 } else if (ipv6_addr_is_set(ipv6_dst_mask) ||
2714 ipv6_addr_is_set(ipv6_src_mask)) {
2715 nl_msg_put_in6_addr(request, TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,
2716 ipv6_dst_mask);
2717 nl_msg_put_in6_addr(request, TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,
2718 ipv6_src_mask);
2719 nl_msg_put_in6_addr(request, TCA_FLOWER_KEY_ENC_IPV6_DST, ipv6_dst);
2720 nl_msg_put_in6_addr(request, TCA_FLOWER_KEY_ENC_IPV6_SRC, ipv6_src);
2721 }
2722 if (tos_mask) {
2723 nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TOS, tos);
2724 nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TOS_MASK, tos_mask);
2725 }
2726 if (ttl_mask) {
2727 nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TTL, ttl);
2728 nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TTL_MASK, ttl_mask);
2729 }
2730 if (tp_dst) {
2731 nl_msg_put_be16(request, TCA_FLOWER_KEY_ENC_UDP_DST_PORT, tp_dst);
2732 }
2733 if (id_mask) {
2734 nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_KEY_ID, id);
2735 }
2736 nl_msg_put_flower_tunnel_opts(request, TCA_FLOWER_KEY_ENC_OPTS,
2737 flower->key.tunnel.metadata);
2738 nl_msg_put_flower_tunnel_opts(request, TCA_FLOWER_KEY_ENC_OPTS_MASK,
2739 flower->mask.tunnel.metadata);
2740 }
2741
2742 #define FLOWER_PUT_MASKED_VALUE(member, type) \
2743 nl_msg_put_masked_value(request, type, type##_MASK, &flower->key.member, \
2744 &flower->mask.member, sizeof flower->key.member)
2745
2746 static int
2747 nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
2748 {
2749
2750 uint16_t host_eth_type = ntohs(flower->key.eth_type);
2751 bool is_vlan = eth_type_vlan(flower->key.eth_type);
2752 bool is_qinq = is_vlan && eth_type_vlan(flower->key.encap_eth_type[0]);
2753 bool is_mpls = eth_type_mpls(flower->key.eth_type);
2754 enum tc_offload_policy policy = flower->tc_policy;
2755 int err;
2756
2757 /* need to parse acts first as some acts require changing the matching
2758 * see csum_update_flag() */
2759 err = nl_msg_put_flower_acts(request, flower);
2760 if (err) {
2761 return err;
2762 }
2763
2764 if (is_vlan) {
2765 if (is_qinq) {
2766 host_eth_type = ntohs(flower->key.encap_eth_type[1]);
2767 } else {
2768 host_eth_type = ntohs(flower->key.encap_eth_type[0]);
2769 }
2770 }
2771
2772 if (is_mpls) {
2773 host_eth_type = ntohs(flower->key.encap_eth_type[0]);
2774 }
2775
2776 FLOWER_PUT_MASKED_VALUE(dst_mac, TCA_FLOWER_KEY_ETH_DST);
2777 FLOWER_PUT_MASKED_VALUE(src_mac, TCA_FLOWER_KEY_ETH_SRC);
2778
2779 if (host_eth_type == ETH_P_ARP) {
2780 FLOWER_PUT_MASKED_VALUE(arp.spa, TCA_FLOWER_KEY_ARP_SIP);
2781 FLOWER_PUT_MASKED_VALUE(arp.tpa, TCA_FLOWER_KEY_ARP_TIP);
2782 FLOWER_PUT_MASKED_VALUE(arp.sha, TCA_FLOWER_KEY_ARP_SHA);
2783 FLOWER_PUT_MASKED_VALUE(arp.tha, TCA_FLOWER_KEY_ARP_THA);
2784 FLOWER_PUT_MASKED_VALUE(arp.opcode, TCA_FLOWER_KEY_ARP_OP);
2785 }
2786
2787 if (host_eth_type == ETH_P_IP || host_eth_type == ETH_P_IPV6) {
2788 FLOWER_PUT_MASKED_VALUE(ip_ttl, TCA_FLOWER_KEY_IP_TTL);
2789 FLOWER_PUT_MASKED_VALUE(ip_tos, TCA_FLOWER_KEY_IP_TOS);
2790
2791 if (flower->mask.ip_proto && flower->key.ip_proto) {
2792 nl_msg_put_u8(request, TCA_FLOWER_KEY_IP_PROTO,
2793 flower->key.ip_proto);
2794 }
2795
2796 if (flower->mask.flags) {
2797 nl_msg_put_be32(request, TCA_FLOWER_KEY_FLAGS,
2798 htonl(flower->key.flags));
2799 nl_msg_put_be32(request, TCA_FLOWER_KEY_FLAGS_MASK,
2800 htonl(flower->mask.flags));
2801 }
2802
2803 if (flower->key.ip_proto == IPPROTO_UDP) {
2804 FLOWER_PUT_MASKED_VALUE(udp_src, TCA_FLOWER_KEY_UDP_SRC);
2805 FLOWER_PUT_MASKED_VALUE(udp_dst, TCA_FLOWER_KEY_UDP_DST);
2806 } else if (flower->key.ip_proto == IPPROTO_TCP) {
2807 FLOWER_PUT_MASKED_VALUE(tcp_src, TCA_FLOWER_KEY_TCP_SRC);
2808 FLOWER_PUT_MASKED_VALUE(tcp_dst, TCA_FLOWER_KEY_TCP_DST);
2809 FLOWER_PUT_MASKED_VALUE(tcp_flags, TCA_FLOWER_KEY_TCP_FLAGS);
2810 } else if (flower->key.ip_proto == IPPROTO_SCTP) {
2811 FLOWER_PUT_MASKED_VALUE(sctp_src, TCA_FLOWER_KEY_SCTP_SRC);
2812 FLOWER_PUT_MASKED_VALUE(sctp_dst, TCA_FLOWER_KEY_SCTP_DST);
2813 }
2814
2815 FLOWER_PUT_MASKED_VALUE(ct_state, TCA_FLOWER_KEY_CT_STATE);
2816 FLOWER_PUT_MASKED_VALUE(ct_zone, TCA_FLOWER_KEY_CT_ZONE);
2817 FLOWER_PUT_MASKED_VALUE(ct_mark, TCA_FLOWER_KEY_CT_MARK);
2818 FLOWER_PUT_MASKED_VALUE(ct_label, TCA_FLOWER_KEY_CT_LABELS);
2819 }
2820
2821 if (host_eth_type == ETH_P_IP) {
2822 FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_src, TCA_FLOWER_KEY_IPV4_SRC);
2823 FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_dst, TCA_FLOWER_KEY_IPV4_DST);
2824 } else if (host_eth_type == ETH_P_IPV6) {
2825 FLOWER_PUT_MASKED_VALUE(ipv6.ipv6_src, TCA_FLOWER_KEY_IPV6_SRC);
2826 FLOWER_PUT_MASKED_VALUE(ipv6.ipv6_dst, TCA_FLOWER_KEY_IPV6_DST);
2827 }
2828
2829 nl_msg_put_be16(request, TCA_FLOWER_KEY_ETH_TYPE, flower->key.eth_type);
2830
2831 if (is_mpls) {
2832 if (mpls_lse_to_ttl(flower->mask.mpls_lse)) {
2833 nl_msg_put_u8(request, TCA_FLOWER_KEY_MPLS_TTL,
2834 mpls_lse_to_ttl(flower->key.mpls_lse));
2835 }
2836 if (mpls_lse_to_tc(flower->mask.mpls_lse)) {
2837 nl_msg_put_u8(request, TCA_FLOWER_KEY_MPLS_TC,
2838 mpls_lse_to_tc(flower->key.mpls_lse));
2839 }
2840 if (mpls_lse_to_bos(flower->mask.mpls_lse)) {
2841 nl_msg_put_u8(request, TCA_FLOWER_KEY_MPLS_BOS,
2842 mpls_lse_to_bos(flower->key.mpls_lse));
2843 }
2844 if (mpls_lse_to_label(flower->mask.mpls_lse)) {
2845 nl_msg_put_u32(request, TCA_FLOWER_KEY_MPLS_LABEL,
2846 mpls_lse_to_label(flower->key.mpls_lse));
2847 }
2848 }
2849
2850 if (is_vlan) {
2851 if (flower->mask.vlan_id[0]) {
2852 nl_msg_put_u16(request, TCA_FLOWER_KEY_VLAN_ID,
2853 flower->key.vlan_id[0]);
2854 }
2855 if (flower->mask.vlan_prio[0]) {
2856 nl_msg_put_u8(request, TCA_FLOWER_KEY_VLAN_PRIO,
2857 flower->key.vlan_prio[0]);
2858 }
2859 if (flower->key.encap_eth_type[0]) {
2860 nl_msg_put_be16(request, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
2861 flower->key.encap_eth_type[0]);
2862 }
2863
2864 if (is_qinq) {
2865 if (flower->mask.vlan_id[1]) {
2866 nl_msg_put_u16(request, TCA_FLOWER_KEY_CVLAN_ID,
2867 flower->key.vlan_id[1]);
2868 }
2869 if (flower->mask.vlan_prio[1]) {
2870 nl_msg_put_u8(request, TCA_FLOWER_KEY_CVLAN_PRIO,
2871 flower->key.vlan_prio[1]);
2872 }
2873 if (flower->key.encap_eth_type[1]) {
2874 nl_msg_put_be16(request, TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
2875 flower->key.encap_eth_type[1]);
2876 }
2877 }
2878 }
2879
2880 if (policy == TC_POLICY_NONE) {
2881 policy = tc_policy;
2882 }
2883
2884 nl_msg_put_u32(request, TCA_FLOWER_FLAGS, tc_get_tc_cls_policy(policy));
2885
2886 if (flower->tunnel) {
2887 nl_msg_put_flower_tunnel(request, flower);
2888 }
2889
2890 return 0;
2891 }
2892
2893 int
2894 tc_replace_flower(struct tcf_id *id, struct tc_flower *flower)
2895 {
2896 struct ofpbuf request;
2897 struct ofpbuf *reply;
2898 int error = 0;
2899 size_t basic_offset;
2900 uint16_t eth_type = (OVS_FORCE uint16_t) flower->key.eth_type;
2901
2902 request_from_tcf_id(id, eth_type, RTM_NEWTFILTER,
2903 NLM_F_CREATE | NLM_F_ECHO, &request);
2904
2905 nl_msg_put_string(&request, TCA_KIND, "flower");
2906 basic_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
2907 {
2908 error = nl_msg_put_flower_options(&request, flower);
2909
2910 if (error) {
2911 ofpbuf_uninit(&request);
2912 return error;
2913 }
2914 }
2915 nl_msg_end_nested(&request, basic_offset);
2916
2917 error = tc_transact(&request, &reply);
2918 if (!error) {
2919 struct tcmsg *tc =
2920 ofpbuf_at_assert(reply, NLMSG_HDRLEN, sizeof *tc);
2921
2922 id->prio = tc_get_major(tc->tcm_info);
2923 id->handle = tc->tcm_handle;
2924 ofpbuf_delete(reply);
2925 }
2926
2927 return error;
2928 }
2929
2930 void
2931 tc_set_policy(const char *policy)
2932 {
2933 if (!policy) {
2934 return;
2935 }
2936
2937 if (!strcmp(policy, "skip_sw")) {
2938 tc_policy = TC_POLICY_SKIP_SW;
2939 } else if (!strcmp(policy, "skip_hw")) {
2940 tc_policy = TC_POLICY_SKIP_HW;
2941 } else if (!strcmp(policy, "none")) {
2942 tc_policy = TC_POLICY_NONE;
2943 } else {
2944 VLOG_WARN("tc: Invalid policy '%s'", policy);
2945 return;
2946 }
2947
2948 VLOG_INFO("tc: Using policy '%s'", policy);
2949 }