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