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