1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2017 6WIND S.A.
3 * Copyright 2017 Mellanox.
10 #include <sys/resource.h>
12 #include <rte_byteorder.h>
13 #include <rte_jhash.h>
14 #include <rte_malloc.h>
15 #include <rte_eth_tap.h>
17 #include <tap_autoconf.h>
18 #include <tap_tcmsgs.h>
21 #ifndef HAVE_TC_FLOWER
23 * For kernels < 4.2, this enum is not defined. Runtime checks will be made to
24 * avoid sending TC messages the kernel cannot understand.
31 TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */
32 TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */
33 TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */
34 TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */
35 TCA_FLOWER_KEY_ETH_TYPE, /* be16 */
36 TCA_FLOWER_KEY_IP_PROTO, /* u8 */
37 TCA_FLOWER_KEY_IPV4_SRC, /* be32 */
38 TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */
39 TCA_FLOWER_KEY_IPV4_DST, /* be32 */
40 TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */
41 TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */
42 TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */
43 TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */
44 TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */
45 TCA_FLOWER_KEY_TCP_SRC, /* be16 */
46 TCA_FLOWER_KEY_TCP_DST, /* be16 */
47 TCA_FLOWER_KEY_UDP_SRC, /* be16 */
48 TCA_FLOWER_KEY_UDP_DST, /* be16 */
51 #ifndef HAVE_TC_VLAN_ID
53 /* TCA_FLOWER_FLAGS, */
54 TCA_FLOWER_KEY_VLAN_ID = TCA_FLOWER_KEY_UDP_DST + 2, /* be16 */
55 TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */
56 TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */
60 * For kernels < 4.2 BPF related enums may not be defined.
61 * Runtime checks will be carried out to gracefully report on TC messages that
62 * are rejected by the kernel. Rejection reasons may be due to:
63 * 1. enum is not defined
64 * 2. enum is defined but kernel is not configured to support BPF system calls,
65 * BPF classifications or BPF actions.
77 #ifndef HAVE_TC_BPF_FD
79 TCA_BPF_FD = TCA_BPF_OPS + 1,
83 #ifndef HAVE_TC_ACT_BPF
104 #ifndef HAVE_TC_ACT_BPF_FD
106 TCA_ACT_BPF_FD = TCA_ACT_BPF_OPS + 1,
111 /* RSS key management */
125 #define ISOLATE_HANDLE 1
126 #define REMOTE_PROMISCUOUS_HANDLE 2
129 LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */
130 struct rte_flow *remote_flow; /* associated remote flow */
131 int bpf_fd[SEC_MAX]; /* list of bfs fds per ELF section */
132 uint32_t key_idx; /* RSS rule key index into BPF map */
136 struct convert_data {
140 struct rte_flow *flow;
144 struct rte_flow_attr attr;
145 struct rte_flow_item items[2];
146 struct rte_flow_action actions[2];
155 struct tc_mirred mirred;
157 struct tc_skbedit skbedit;
161 struct tc_act_bpf bpf;
163 const char *annotation;
168 static int tap_flow_create_eth(const struct rte_flow_item *item, void *data);
169 static int tap_flow_create_vlan(const struct rte_flow_item *item, void *data);
170 static int tap_flow_create_ipv4(const struct rte_flow_item *item, void *data);
171 static int tap_flow_create_ipv6(const struct rte_flow_item *item, void *data);
172 static int tap_flow_create_udp(const struct rte_flow_item *item, void *data);
173 static int tap_flow_create_tcp(const struct rte_flow_item *item, void *data);
175 tap_flow_validate(struct rte_eth_dev *dev,
176 const struct rte_flow_attr *attr,
177 const struct rte_flow_item items[],
178 const struct rte_flow_action actions[],
179 struct rte_flow_error *error);
181 static struct rte_flow *
182 tap_flow_create(struct rte_eth_dev *dev,
183 const struct rte_flow_attr *attr,
184 const struct rte_flow_item items[],
185 const struct rte_flow_action actions[],
186 struct rte_flow_error *error);
189 tap_flow_free(struct pmd_internals *pmd,
190 struct rte_flow *flow);
193 tap_flow_destroy(struct rte_eth_dev *dev,
194 struct rte_flow *flow,
195 struct rte_flow_error *error);
198 tap_flow_isolate(struct rte_eth_dev *dev,
200 struct rte_flow_error *error);
202 static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx);
203 static int rss_enable(struct pmd_internals *pmd,
204 const struct rte_flow_attr *attr,
205 struct rte_flow_error *error);
206 static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,
207 const struct rte_flow_action_rss *rss,
208 struct rte_flow_error *error);
210 static const struct rte_flow_ops tap_flow_ops = {
211 .validate = tap_flow_validate,
212 .create = tap_flow_create,
213 .destroy = tap_flow_destroy,
214 .flush = tap_flow_flush,
215 .isolate = tap_flow_isolate,
218 /* Static initializer for items. */
220 (const enum rte_flow_item_type []){ \
221 __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
224 /* Structure to generate a simple graph of layers supported by the NIC. */
225 struct tap_flow_items {
226 /* Bit-mask corresponding to what is supported for this item. */
228 const unsigned int mask_sz; /* Bit-mask size in bytes. */
230 * Bit-mask corresponding to the default mask, if none is provided
231 * along with the item.
233 const void *default_mask;
235 * Conversion function from rte_flow to netlink attributes.
238 * rte_flow item to convert.
240 * Internal structure to store the conversion.
243 * 0 on success, negative value otherwise.
245 int (*convert)(const struct rte_flow_item *item, void *data);
246 /** List of possible following items. */
247 const enum rte_flow_item_type *const items;
250 /* Graph of supported items and associated actions. */
251 static const struct tap_flow_items tap_flow_items[] = {
252 [RTE_FLOW_ITEM_TYPE_END] = {
253 .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH),
255 [RTE_FLOW_ITEM_TYPE_ETH] = {
257 RTE_FLOW_ITEM_TYPE_VLAN,
258 RTE_FLOW_ITEM_TYPE_IPV4,
259 RTE_FLOW_ITEM_TYPE_IPV6),
260 .mask = &(const struct rte_flow_item_eth){
261 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
262 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
265 .mask_sz = sizeof(struct rte_flow_item_eth),
266 .default_mask = &rte_flow_item_eth_mask,
267 .convert = tap_flow_create_eth,
269 [RTE_FLOW_ITEM_TYPE_VLAN] = {
270 .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4,
271 RTE_FLOW_ITEM_TYPE_IPV6),
272 .mask = &(const struct rte_flow_item_vlan){
274 /* DEI matching is not supported */
275 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
281 .mask_sz = sizeof(struct rte_flow_item_vlan),
282 .default_mask = &rte_flow_item_vlan_mask,
283 .convert = tap_flow_create_vlan,
285 [RTE_FLOW_ITEM_TYPE_IPV4] = {
286 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
287 RTE_FLOW_ITEM_TYPE_TCP),
288 .mask = &(const struct rte_flow_item_ipv4){
295 .mask_sz = sizeof(struct rte_flow_item_ipv4),
296 .default_mask = &rte_flow_item_ipv4_mask,
297 .convert = tap_flow_create_ipv4,
299 [RTE_FLOW_ITEM_TYPE_IPV6] = {
300 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
301 RTE_FLOW_ITEM_TYPE_TCP),
302 .mask = &(const struct rte_flow_item_ipv6){
305 "\xff\xff\xff\xff\xff\xff\xff\xff"
306 "\xff\xff\xff\xff\xff\xff\xff\xff",
309 "\xff\xff\xff\xff\xff\xff\xff\xff"
310 "\xff\xff\xff\xff\xff\xff\xff\xff",
315 .mask_sz = sizeof(struct rte_flow_item_ipv6),
316 .default_mask = &rte_flow_item_ipv6_mask,
317 .convert = tap_flow_create_ipv6,
319 [RTE_FLOW_ITEM_TYPE_UDP] = {
320 .mask = &(const struct rte_flow_item_udp){
326 .mask_sz = sizeof(struct rte_flow_item_udp),
327 .default_mask = &rte_flow_item_udp_mask,
328 .convert = tap_flow_create_udp,
330 [RTE_FLOW_ITEM_TYPE_TCP] = {
331 .mask = &(const struct rte_flow_item_tcp){
337 .mask_sz = sizeof(struct rte_flow_item_tcp),
338 .default_mask = &rte_flow_item_tcp_mask,
339 .convert = tap_flow_create_tcp,
344 * TC rules, by growing priority
346 * Remote netdevice Tap netdevice
347 * +-------------+-------------+ +-------------+-------------+
348 * | Ingress | Egress | | Ingress | Egress |
349 * |-------------|-------------| |-------------|-------------|
350 * | | \ / | | | REMOTE TX | prio 1
351 * | | \ / | | | \ / | prio 2
352 * | EXPLICIT | \ / | | EXPLICIT | \ / | .
353 * | | \ / | | | \ / | .
354 * | RULES | X | | RULES | X | .
355 * | . | / \ | | . | / \ | .
356 * | . | / \ | | . | / \ | .
357 * | . | / \ | | . | / \ | .
358 * | . | / \ | | . | / \ | .
360 * .... .... .... ....
362 * | . | \ / | | . | \ / | .
363 * | . | \ / | | . | \ / | .
364 * | | \ / | | | \ / |
365 * | LOCAL_MAC | \ / | | \ / | \ / | last prio - 5
366 * | PROMISC | X | | \ / | X | last prio - 4
367 * | ALLMULTI | / \ | | X | / \ | last prio - 3
368 * | BROADCAST | / \ | | / \ | / \ | last prio - 2
369 * | BROADCASTV6 | / \ | | / \ | / \ | last prio - 1
370 * | xx | / \ | | ISOLATE | / \ | last prio
371 * +-------------+-------------+ +-------------+-------------+
373 * The implicit flow rules are stored in a list in with mandatorily the last two
374 * being the ISOLATE and REMOTE_TX rules. e.g.:
376 * LOCAL_MAC -> BROADCAST -> BROADCASTV6 -> REMOTE_TX -> ISOLATE -> NULL
378 * That enables tap_flow_isolate() to remove implicit rules by popping the list
379 * head and remove it as long as it applies on the remote netdevice. The
380 * implicit rule for TX redirection is not removed, as isolate concerns only
384 static struct remote_rule implicit_rte_flows[TAP_REMOTE_MAX_IDX] = {
385 [TAP_REMOTE_LOCAL_MAC] = {
388 .priority = PRIORITY_MASK - TAP_REMOTE_LOCAL_MAC,
392 .type = RTE_FLOW_ITEM_TYPE_ETH,
393 .mask = &(const struct rte_flow_item_eth){
394 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
398 .type = RTE_FLOW_ITEM_TYPE_END,
400 .mirred = TCA_EGRESS_REDIR,
402 [TAP_REMOTE_BROADCAST] = {
405 .priority = PRIORITY_MASK - TAP_REMOTE_BROADCAST,
409 .type = RTE_FLOW_ITEM_TYPE_ETH,
410 .mask = &(const struct rte_flow_item_eth){
411 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
413 .spec = &(const struct rte_flow_item_eth){
414 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
418 .type = RTE_FLOW_ITEM_TYPE_END,
420 .mirred = TCA_EGRESS_MIRROR,
422 [TAP_REMOTE_BROADCASTV6] = {
425 .priority = PRIORITY_MASK - TAP_REMOTE_BROADCASTV6,
429 .type = RTE_FLOW_ITEM_TYPE_ETH,
430 .mask = &(const struct rte_flow_item_eth){
431 .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
433 .spec = &(const struct rte_flow_item_eth){
434 .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
438 .type = RTE_FLOW_ITEM_TYPE_END,
440 .mirred = TCA_EGRESS_MIRROR,
442 [TAP_REMOTE_PROMISC] = {
445 .priority = PRIORITY_MASK - TAP_REMOTE_PROMISC,
449 .type = RTE_FLOW_ITEM_TYPE_VOID,
452 .type = RTE_FLOW_ITEM_TYPE_END,
454 .mirred = TCA_EGRESS_MIRROR,
456 [TAP_REMOTE_ALLMULTI] = {
459 .priority = PRIORITY_MASK - TAP_REMOTE_ALLMULTI,
463 .type = RTE_FLOW_ITEM_TYPE_ETH,
464 .mask = &(const struct rte_flow_item_eth){
465 .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
467 .spec = &(const struct rte_flow_item_eth){
468 .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
472 .type = RTE_FLOW_ITEM_TYPE_END,
474 .mirred = TCA_EGRESS_MIRROR,
479 .priority = TAP_REMOTE_TX,
483 .type = RTE_FLOW_ITEM_TYPE_VOID,
486 .type = RTE_FLOW_ITEM_TYPE_END,
488 .mirred = TCA_EGRESS_MIRROR,
493 .priority = PRIORITY_MASK - TAP_ISOLATE,
497 .type = RTE_FLOW_ITEM_TYPE_VOID,
500 .type = RTE_FLOW_ITEM_TYPE_END,
506 * Make as much checks as possible on an Ethernet item, and if a flow is
507 * provided, fill it appropriately with Ethernet info.
510 * Item specification.
511 * @param[in, out] data
512 * Additional data structure to tell next layers we've been here.
515 * 0 if checks are alright, -1 otherwise.
518 tap_flow_create_eth(const struct rte_flow_item *item, void *data)
520 struct convert_data *info = (struct convert_data *)data;
521 const struct rte_flow_item_eth *spec = item->spec;
522 const struct rte_flow_item_eth *mask = item->mask;
523 struct rte_flow *flow = info->flow;
526 /* use default mask if none provided */
528 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_ETH].default_mask;
529 /* TC does not support eth_type masking. Only accept if exact match. */
530 if (mask->type && mask->type != 0xffff)
534 /* store eth_type for consistency if ipv4/6 pattern item comes next */
535 if (spec->type & mask->type)
536 info->eth_type = spec->type;
540 if (!is_zero_ether_addr(&spec->dst)) {
541 tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_ETH_DST, ETHER_ADDR_LEN,
542 &spec->dst.addr_bytes);
543 tap_nlattr_add(&msg->nh,
544 TCA_FLOWER_KEY_ETH_DST_MASK, ETHER_ADDR_LEN,
545 &mask->dst.addr_bytes);
547 if (!is_zero_ether_addr(&mask->src)) {
548 tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_ETH_SRC, ETHER_ADDR_LEN,
549 &spec->src.addr_bytes);
550 tap_nlattr_add(&msg->nh,
551 TCA_FLOWER_KEY_ETH_SRC_MASK, ETHER_ADDR_LEN,
552 &mask->src.addr_bytes);
558 * Make as much checks as possible on a VLAN item, and if a flow is provided,
559 * fill it appropriately with VLAN info.
562 * Item specification.
563 * @param[in, out] data
564 * Additional data structure to tell next layers we've been here.
567 * 0 if checks are alright, -1 otherwise.
570 tap_flow_create_vlan(const struct rte_flow_item *item, void *data)
572 struct convert_data *info = (struct convert_data *)data;
573 const struct rte_flow_item_vlan *spec = item->spec;
574 const struct rte_flow_item_vlan *mask = item->mask;
575 struct rte_flow *flow = info->flow;
578 /* use default mask if none provided */
580 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_VLAN].default_mask;
581 /* TC does not support tpid masking. Only accept if exact match. */
582 if (mask->tpid && mask->tpid != 0xffff)
584 /* Double-tagging not supported. */
585 if (spec && mask->tpid && spec->tpid != htons(ETH_P_8021Q))
591 msg->t.tcm_info = TC_H_MAKE(msg->t.tcm_info, htons(ETH_P_8021Q));
592 #define VLAN_PRIO(tci) ((tci) >> 13)
593 #define VLAN_ID(tci) ((tci) & 0xfff)
597 uint16_t tci = ntohs(spec->tci) & mask->tci;
598 uint16_t prio = VLAN_PRIO(tci);
599 uint8_t vid = VLAN_ID(tci);
602 tap_nlattr_add8(&msg->nh,
603 TCA_FLOWER_KEY_VLAN_PRIO, prio);
605 tap_nlattr_add16(&msg->nh,
606 TCA_FLOWER_KEY_VLAN_ID, vid);
612 * Make as much checks as possible on an IPv4 item, and if a flow is provided,
613 * fill it appropriately with IPv4 info.
616 * Item specification.
617 * @param[in, out] data
618 * Additional data structure to tell next layers we've been here.
621 * 0 if checks are alright, -1 otherwise.
624 tap_flow_create_ipv4(const struct rte_flow_item *item, void *data)
626 struct convert_data *info = (struct convert_data *)data;
627 const struct rte_flow_item_ipv4 *spec = item->spec;
628 const struct rte_flow_item_ipv4 *mask = item->mask;
629 struct rte_flow *flow = info->flow;
632 /* use default mask if none provided */
634 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_IPV4].default_mask;
635 /* check that previous eth type is compatible with ipv4 */
636 if (info->eth_type && info->eth_type != htons(ETH_P_IP))
638 /* store ip_proto for consistency if udp/tcp pattern item comes next */
640 info->ip_proto = spec->hdr.next_proto_id;
645 info->eth_type = htons(ETH_P_IP);
648 if (spec->hdr.dst_addr) {
649 tap_nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_DST,
651 tap_nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_DST_MASK,
654 if (spec->hdr.src_addr) {
655 tap_nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_SRC,
657 tap_nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_SRC_MASK,
660 if (spec->hdr.next_proto_id)
661 tap_nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO,
662 spec->hdr.next_proto_id);
667 * Make as much checks as possible on an IPv6 item, and if a flow is provided,
668 * fill it appropriately with IPv6 info.
671 * Item specification.
672 * @param[in, out] data
673 * Additional data structure to tell next layers we've been here.
676 * 0 if checks are alright, -1 otherwise.
679 tap_flow_create_ipv6(const struct rte_flow_item *item, void *data)
681 struct convert_data *info = (struct convert_data *)data;
682 const struct rte_flow_item_ipv6 *spec = item->spec;
683 const struct rte_flow_item_ipv6 *mask = item->mask;
684 struct rte_flow *flow = info->flow;
685 uint8_t empty_addr[16] = { 0 };
688 /* use default mask if none provided */
690 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_IPV6].default_mask;
691 /* check that previous eth type is compatible with ipv6 */
692 if (info->eth_type && info->eth_type != htons(ETH_P_IPV6))
694 /* store ip_proto for consistency if udp/tcp pattern item comes next */
696 info->ip_proto = spec->hdr.proto;
701 info->eth_type = htons(ETH_P_IPV6);
704 if (memcmp(spec->hdr.dst_addr, empty_addr, 16)) {
705 tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST,
706 sizeof(spec->hdr.dst_addr), &spec->hdr.dst_addr);
707 tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST_MASK,
708 sizeof(mask->hdr.dst_addr), &mask->hdr.dst_addr);
710 if (memcmp(spec->hdr.src_addr, empty_addr, 16)) {
711 tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC,
712 sizeof(spec->hdr.src_addr), &spec->hdr.src_addr);
713 tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC_MASK,
714 sizeof(mask->hdr.src_addr), &mask->hdr.src_addr);
717 tap_nlattr_add8(&msg->nh,
718 TCA_FLOWER_KEY_IP_PROTO, spec->hdr.proto);
723 * Make as much checks as possible on a UDP item, and if a flow is provided,
724 * fill it appropriately with UDP info.
727 * Item specification.
728 * @param[in, out] data
729 * Additional data structure to tell next layers we've been here.
732 * 0 if checks are alright, -1 otherwise.
735 tap_flow_create_udp(const struct rte_flow_item *item, void *data)
737 struct convert_data *info = (struct convert_data *)data;
738 const struct rte_flow_item_udp *spec = item->spec;
739 const struct rte_flow_item_udp *mask = item->mask;
740 struct rte_flow *flow = info->flow;
743 /* use default mask if none provided */
745 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_UDP].default_mask;
746 /* check that previous ip_proto is compatible with udp */
747 if (info->ip_proto && info->ip_proto != IPPROTO_UDP)
749 /* TC does not support UDP port masking. Only accept if exact match. */
750 if ((mask->hdr.src_port && mask->hdr.src_port != 0xffff) ||
751 (mask->hdr.dst_port && mask->hdr.dst_port != 0xffff))
756 tap_nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, IPPROTO_UDP);
759 if (spec->hdr.dst_port & mask->hdr.dst_port)
760 tap_nlattr_add16(&msg->nh, TCA_FLOWER_KEY_UDP_DST,
762 if (spec->hdr.src_port & mask->hdr.src_port)
763 tap_nlattr_add16(&msg->nh, TCA_FLOWER_KEY_UDP_SRC,
769 * Make as much checks as possible on a TCP item, and if a flow is provided,
770 * fill it appropriately with TCP info.
773 * Item specification.
774 * @param[in, out] data
775 * Additional data structure to tell next layers we've been here.
778 * 0 if checks are alright, -1 otherwise.
781 tap_flow_create_tcp(const struct rte_flow_item *item, void *data)
783 struct convert_data *info = (struct convert_data *)data;
784 const struct rte_flow_item_tcp *spec = item->spec;
785 const struct rte_flow_item_tcp *mask = item->mask;
786 struct rte_flow *flow = info->flow;
789 /* use default mask if none provided */
791 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_TCP].default_mask;
792 /* check that previous ip_proto is compatible with tcp */
793 if (info->ip_proto && info->ip_proto != IPPROTO_TCP)
795 /* TC does not support TCP port masking. Only accept if exact match. */
796 if ((mask->hdr.src_port && mask->hdr.src_port != 0xffff) ||
797 (mask->hdr.dst_port && mask->hdr.dst_port != 0xffff))
802 tap_nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, IPPROTO_TCP);
805 if (spec->hdr.dst_port & mask->hdr.dst_port)
806 tap_nlattr_add16(&msg->nh, TCA_FLOWER_KEY_TCP_DST,
808 if (spec->hdr.src_port & mask->hdr.src_port)
809 tap_nlattr_add16(&msg->nh, TCA_FLOWER_KEY_TCP_SRC,
815 * Check support for a given item.
818 * Item specification.
820 * Bit-Mask size in bytes.
821 * @param[in] supported_mask
822 * Bit-mask covering supported fields to compare with spec, last and mask in
824 * @param[in] default_mask
825 * Bit-mask default mask if none is provided in \item.
831 tap_flow_item_validate(const struct rte_flow_item *item,
833 const uint8_t *supported_mask,
834 const uint8_t *default_mask)
838 /* An empty layer is allowed, as long as all fields are NULL */
839 if (!item->spec && (item->mask || item->last))
841 /* Is the item spec compatible with what the NIC supports? */
842 if (item->spec && !item->mask) {
844 const uint8_t *spec = item->spec;
846 for (i = 0; i < size; ++i)
847 if ((spec[i] | supported_mask[i]) != supported_mask[i])
849 /* Is the default mask compatible with what the NIC supports? */
850 for (i = 0; i < size; i++)
851 if ((default_mask[i] | supported_mask[i]) !=
855 /* Is the item last compatible with what the NIC supports? */
856 if (item->last && !item->mask) {
858 const uint8_t *spec = item->last;
860 for (i = 0; i < size; ++i)
861 if ((spec[i] | supported_mask[i]) != supported_mask[i])
864 /* Is the item mask compatible with what the NIC supports? */
867 const uint8_t *spec = item->mask;
869 for (i = 0; i < size; ++i)
870 if ((spec[i] | supported_mask[i]) != supported_mask[i])
874 * Once masked, Are item spec and item last equal?
875 * TC does not support range so anything else is invalid.
877 if (item->spec && item->last) {
880 const uint8_t *apply = default_mask;
885 for (i = 0; i < size; ++i) {
886 spec[i] = ((const uint8_t *)item->spec)[i] & apply[i];
887 last[i] = ((const uint8_t *)item->last)[i] & apply[i];
889 ret = memcmp(spec, last, size);
895 * Configure the kernel with a TC action and its configured parameters
896 * Handled actions: "gact", "mirred", "skbedit", "bpf"
899 * Pointer to rte flow containing the netlink message
901 * @param[in, out] act_index
902 * Pointer to action sequence number in the TC command
905 * Pointer to struct holding the action parameters
908 * -1 on failure, 0 on success
911 add_action(struct rte_flow *flow, size_t *act_index, struct action_data *adata)
913 struct nlmsg *msg = &flow->msg;
915 if (tap_nlattr_nested_start(msg, (*act_index)++) < 0)
918 tap_nlattr_add(&msg->nh, TCA_ACT_KIND,
919 strlen(adata->id) + 1, adata->id);
920 if (tap_nlattr_nested_start(msg, TCA_ACT_OPTIONS) < 0)
922 if (strcmp("gact", adata->id) == 0) {
923 tap_nlattr_add(&msg->nh, TCA_GACT_PARMS, sizeof(adata->gact),
925 } else if (strcmp("mirred", adata->id) == 0) {
926 if (adata->mirred.eaction == TCA_EGRESS_MIRROR)
927 adata->mirred.action = TC_ACT_PIPE;
929 adata->mirred.action = TC_ACT_STOLEN;
930 tap_nlattr_add(&msg->nh, TCA_MIRRED_PARMS,
931 sizeof(adata->mirred),
933 } else if (strcmp("skbedit", adata->id) == 0) {
934 tap_nlattr_add(&msg->nh, TCA_SKBEDIT_PARMS,
935 sizeof(adata->skbedit.skbedit),
936 &adata->skbedit.skbedit);
937 tap_nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING,
938 adata->skbedit.queue);
939 } else if (strcmp("bpf", adata->id) == 0) {
940 tap_nlattr_add32(&msg->nh, TCA_ACT_BPF_FD, adata->bpf.bpf_fd);
941 tap_nlattr_add(&msg->nh, TCA_ACT_BPF_NAME,
942 strlen(adata->bpf.annotation) + 1,
943 adata->bpf.annotation);
944 tap_nlattr_add(&msg->nh, TCA_ACT_BPF_PARMS,
945 sizeof(adata->bpf.bpf),
950 tap_nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
951 tap_nlattr_nested_finish(msg); /* nested act_index */
956 * Helper function to send a serie of TC actions to the kernel
959 * Pointer to rte flow containing the netlink message
961 * @param[in] nb_actions
962 * Number of actions in an array of action structs
965 * Pointer to an array of action structs
967 * @param[in] classifier_actions
968 * The classifier on behave of which the actions are configured
971 * -1 on failure, 0 on success
974 add_actions(struct rte_flow *flow, int nb_actions, struct action_data *data,
975 int classifier_action)
977 struct nlmsg *msg = &flow->msg;
978 size_t act_index = 1;
981 if (tap_nlattr_nested_start(msg, classifier_action) < 0)
983 for (i = 0; i < nb_actions; i++)
984 if (add_action(flow, &act_index, data + i) < 0)
986 tap_nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
991 * Validate a flow supported by TC.
992 * If flow param is not NULL, then also fill the netlink message inside.
995 * Pointer to private structure.
997 * Flow rule attributes.
999 * Pattern specification (list terminated by the END pattern item).
1000 * @param[in] actions
1001 * Associated actions (list terminated by the END action).
1003 * Perform verbose error reporting if not NULL.
1004 * @param[in, out] flow
1005 * Flow structure to update.
1007 * If set to TCA_EGRESS_REDIR, provided actions will be replaced with a
1008 * redirection to the tap netdevice, and the TC rule will be configured
1009 * on the remote netdevice in pmd.
1010 * If set to TCA_EGRESS_MIRROR, provided actions will be replaced with a
1011 * mirroring to the tap netdevice, and the TC rule will be configured
1012 * on the remote netdevice in pmd. Matching packets will thus be duplicated.
1013 * If set to 0, the standard behavior is to be used: set correct actions for
1014 * the TC rule, and apply it on the tap netdevice.
1017 * 0 on success, a negative errno value otherwise and rte_errno is set.
1020 priv_flow_process(struct pmd_internals *pmd,
1021 const struct rte_flow_attr *attr,
1022 const struct rte_flow_item items[],
1023 const struct rte_flow_action actions[],
1024 struct rte_flow_error *error,
1025 struct rte_flow *flow,
1028 const struct tap_flow_items *cur_item = tap_flow_items;
1029 struct convert_data data = {
1034 int action = 0; /* Only one action authorized for now */
1036 if (attr->group > MAX_GROUP) {
1038 error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
1039 NULL, "group value too big: cannot exceed 15");
1042 if (attr->priority > MAX_PRIORITY) {
1044 error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1045 NULL, "priority value too big");
1048 uint16_t group = attr->group << GROUP_SHIFT;
1049 uint16_t prio = group | (attr->priority +
1050 RSS_PRIORITY_OFFSET + PRIORITY_OFFSET);
1051 flow->msg.t.tcm_info = TC_H_MAKE(prio << 16,
1052 flow->msg.t.tcm_info);
1057 * If attr->ingress, the rule applies on remote ingress
1058 * to match incoming packets
1059 * If attr->egress, the rule applies on tap ingress (as
1060 * seen from the kernel) to deal with packets going out
1061 * from the DPDK app.
1063 flow->msg.t.tcm_parent = TC_H_MAKE(TC_H_INGRESS, 0);
1065 /* Standard rule on tap egress (kernel standpoint). */
1066 flow->msg.t.tcm_parent =
1067 TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);
1069 /* use flower filter type */
1070 tap_nlattr_add(&flow->msg.nh, TCA_KIND, sizeof("flower"), "flower");
1071 if (tap_nlattr_nested_start(&flow->msg, TCA_OPTIONS) < 0)
1072 goto exit_item_not_supported;
1074 for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) {
1075 const struct tap_flow_items *token = NULL;
1079 if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
1083 cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END;
1085 if (cur_item->items[i] == items->type) {
1086 token = &tap_flow_items[items->type];
1091 goto exit_item_not_supported;
1093 err = tap_flow_item_validate(
1094 items, cur_item->mask_sz,
1095 (const uint8_t *)cur_item->mask,
1096 (const uint8_t *)cur_item->default_mask);
1098 goto exit_item_not_supported;
1099 if (flow && cur_item->convert) {
1100 err = cur_item->convert(items, &data);
1102 goto exit_item_not_supported;
1107 tap_nlattr_add16(&flow->msg.nh, TCA_FLOWER_KEY_ETH_TYPE,
1108 htons(ETH_P_8021Q));
1109 tap_nlattr_add16(&flow->msg.nh,
1110 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
1112 data.eth_type : htons(ETH_P_ALL));
1113 } else if (data.eth_type) {
1114 tap_nlattr_add16(&flow->msg.nh, TCA_FLOWER_KEY_ETH_TYPE,
1118 if (mirred && flow) {
1119 struct action_data adata = {
1127 * If attr->egress && mirred, then this is a special
1128 * case where the rule must be applied on the tap, to
1129 * redirect packets coming from the DPDK App, out
1130 * through the remote netdevice.
1132 adata.mirred.ifindex = attr->ingress ? pmd->if_index :
1133 pmd->remote_if_index;
1134 if (mirred == TCA_EGRESS_MIRROR)
1135 adata.mirred.action = TC_ACT_PIPE;
1137 adata.mirred.action = TC_ACT_STOLEN;
1138 if (add_actions(flow, 1, &adata, TCA_FLOWER_ACT) < 0)
1139 goto exit_action_not_supported;
1143 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
1146 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
1148 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
1150 goto exit_action_not_supported;
1153 struct action_data adata = {
1156 .action = TC_ACT_SHOT,
1160 err = add_actions(flow, 1, &adata,
1163 } else if (actions->type == RTE_FLOW_ACTION_TYPE_PASSTHRU) {
1165 goto exit_action_not_supported;
1168 struct action_data adata = {
1172 .action = TC_ACT_UNSPEC,
1176 err = add_actions(flow, 1, &adata,
1179 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
1180 const struct rte_flow_action_queue *queue =
1181 (const struct rte_flow_action_queue *)
1185 goto exit_action_not_supported;
1188 (queue->index > pmd->dev->data->nb_rx_queues - 1))
1189 goto exit_action_not_supported;
1191 struct action_data adata = {
1195 .action = TC_ACT_PIPE,
1197 .queue = queue->index,
1201 err = add_actions(flow, 1, &adata,
1204 } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) {
1205 const struct rte_flow_action_rss *rss =
1206 (const struct rte_flow_action_rss *)
1210 goto exit_action_not_supported;
1212 if (!pmd->rss_enabled) {
1213 err = rss_enable(pmd, attr, error);
1215 goto exit_action_not_supported;
1218 err = rss_add_actions(flow, pmd, rss, error);
1220 goto exit_action_not_supported;
1223 goto exit_action_not_supported;
1227 tap_nlattr_nested_finish(&flow->msg); /* nested TCA_OPTIONS */
1229 exit_item_not_supported:
1230 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
1231 items, "item not supported");
1233 exit_action_not_supported:
1234 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
1235 actions, "action not supported");
1244 * @see rte_flow_validate()
1248 tap_flow_validate(struct rte_eth_dev *dev,
1249 const struct rte_flow_attr *attr,
1250 const struct rte_flow_item items[],
1251 const struct rte_flow_action actions[],
1252 struct rte_flow_error *error)
1254 struct pmd_internals *pmd = dev->data->dev_private;
1256 return priv_flow_process(pmd, attr, items, actions, error, NULL, 0);
1260 * Set a unique handle in a flow.
1262 * The kernel supports TC rules with equal priority, as long as they use the
1263 * same matching fields (e.g.: dst mac and ipv4) with different values (and
1264 * full mask to ensure no collision is possible).
1265 * In those rules, the handle (uint32_t) is the part that would identify
1266 * specifically each rule.
1268 * On 32-bit architectures, the handle can simply be the flow's pointer address.
1269 * On 64-bit architectures, we rely on jhash(flow) to find a (sufficiently)
1272 * @param[in, out] flow
1273 * The flow that needs its handle set.
1276 tap_flow_set_handle(struct rte_flow *flow)
1278 uint32_t handle = 0;
1280 if (sizeof(flow) > 4)
1281 handle = rte_jhash(&flow, sizeof(flow), 1);
1283 handle = (uintptr_t)flow;
1284 /* must be at least 1 to avoid letting the kernel choose one for us */
1287 flow->msg.t.tcm_handle = handle;
1291 * Free the flow opened file descriptors and allocated memory
1294 * Pointer to the flow to free
1298 tap_flow_free(struct pmd_internals *pmd, struct rte_flow *flow)
1305 if (pmd->rss_enabled) {
1306 /* Close flow BPF file descriptors */
1307 for (i = 0; i < SEC_MAX; i++)
1308 if (flow->bpf_fd[i] != 0) {
1309 close(flow->bpf_fd[i]);
1310 flow->bpf_fd[i] = 0;
1313 /* Release the map key for this RSS rule */
1314 bpf_rss_key(KEY_CMD_RELEASE, &flow->key_idx);
1318 /* Free flow allocated memory */
1325 * @see rte_flow_create()
1328 static struct rte_flow *
1329 tap_flow_create(struct rte_eth_dev *dev,
1330 const struct rte_flow_attr *attr,
1331 const struct rte_flow_item items[],
1332 const struct rte_flow_action actions[],
1333 struct rte_flow_error *error)
1335 struct pmd_internals *pmd = dev->data->dev_private;
1336 struct rte_flow *remote_flow = NULL;
1337 struct rte_flow *flow = NULL;
1338 struct nlmsg *msg = NULL;
1341 if (!pmd->if_index) {
1342 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1344 "can't create rule, ifindex not found");
1348 * No rules configured through standard rte_flow should be set on the
1349 * priorities used by implicit rules.
1351 if ((attr->group == MAX_GROUP) &&
1352 attr->priority > (MAX_PRIORITY - TAP_REMOTE_MAX_IDX)) {
1354 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1355 NULL, "priority value too big");
1358 flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1360 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1361 NULL, "cannot allocate memory for rte_flow");
1365 tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER,
1366 NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
1367 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1368 tap_flow_set_handle(flow);
1369 if (priv_flow_process(pmd, attr, items, actions, error, flow, 0))
1371 err = tap_nl_send(pmd->nlsk_fd, &msg->nh);
1373 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1374 NULL, "couldn't send request to kernel");
1377 err = tap_nl_recv_ack(pmd->nlsk_fd);
1380 "Kernel refused TC filter rule creation (%d): %s\n",
1381 errno, strerror(errno));
1382 rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_HANDLE,
1384 "overlapping rules or Kernel too old for flower support");
1387 LIST_INSERT_HEAD(&pmd->flows, flow, next);
1389 * If a remote device is configured, a TC rule with identical items for
1390 * matching must be set on that device, with a single action: redirect
1391 * to the local pmd->if_index.
1393 if (pmd->remote_if_index) {
1394 remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1397 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1398 "cannot allocate memory for rte_flow");
1401 msg = &remote_flow->msg;
1402 /* set the rule if_index for the remote netdevice */
1404 msg, pmd->remote_if_index, RTM_NEWTFILTER,
1405 NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
1406 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1407 tap_flow_set_handle(remote_flow);
1408 if (priv_flow_process(pmd, attr, items, NULL,
1409 error, remote_flow, TCA_EGRESS_REDIR)) {
1411 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1412 NULL, "rte flow rule validation failed");
1415 err = tap_nl_send(pmd->nlsk_fd, &msg->nh);
1418 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1419 NULL, "Failure sending nl request");
1422 err = tap_nl_recv_ack(pmd->nlsk_fd);
1425 "Kernel refused TC filter rule creation (%d): %s\n",
1426 errno, strerror(errno));
1428 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1430 "overlapping rules or Kernel too old for flower support");
1433 flow->remote_flow = remote_flow;
1438 rte_free(remote_flow);
1440 tap_flow_free(pmd, flow);
1445 * Destroy a flow using pointer to pmd_internal.
1447 * @param[in, out] pmd
1448 * Pointer to private structure.
1450 * Pointer to the flow to destroy.
1451 * @param[in, out] error
1452 * Pointer to the flow error handler
1454 * @return 0 if the flow could be destroyed, -1 otherwise.
1457 tap_flow_destroy_pmd(struct pmd_internals *pmd,
1458 struct rte_flow *flow,
1459 struct rte_flow_error *error)
1461 struct rte_flow *remote_flow = flow->remote_flow;
1464 LIST_REMOVE(flow, next);
1465 flow->msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1466 flow->msg.nh.nlmsg_type = RTM_DELTFILTER;
1468 ret = tap_nl_send(pmd->nlsk_fd, &flow->msg.nh);
1470 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1471 NULL, "couldn't send request to kernel");
1474 ret = tap_nl_recv_ack(pmd->nlsk_fd);
1475 /* If errno is ENOENT, the rule is already no longer in the kernel. */
1476 if (ret < 0 && errno == ENOENT)
1480 "Kernel refused TC filter rule deletion (%d): %s\n",
1481 errno, strerror(errno));
1483 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1484 "couldn't receive kernel ack to our request");
1489 remote_flow->msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1490 remote_flow->msg.nh.nlmsg_type = RTM_DELTFILTER;
1492 ret = tap_nl_send(pmd->nlsk_fd, &remote_flow->msg.nh);
1495 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1496 NULL, "Failure sending nl request");
1499 ret = tap_nl_recv_ack(pmd->nlsk_fd);
1500 if (ret < 0 && errno == ENOENT)
1504 "Kernel refused TC filter rule deletion (%d): %s\n",
1505 errno, strerror(errno));
1507 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1508 NULL, "Failure trying to receive nl ack");
1514 rte_free(remote_flow);
1515 tap_flow_free(pmd, flow);
1522 * @see rte_flow_destroy()
1526 tap_flow_destroy(struct rte_eth_dev *dev,
1527 struct rte_flow *flow,
1528 struct rte_flow_error *error)
1530 struct pmd_internals *pmd = dev->data->dev_private;
1532 return tap_flow_destroy_pmd(pmd, flow, error);
1536 * Enable/disable flow isolation.
1538 * @see rte_flow_isolate()
1542 tap_flow_isolate(struct rte_eth_dev *dev,
1544 struct rte_flow_error *error __rte_unused)
1546 struct pmd_internals *pmd = dev->data->dev_private;
1549 pmd->flow_isolate = 1;
1551 pmd->flow_isolate = 0;
1553 * If netdevice is there, setup appropriate flow rules immediately.
1554 * Otherwise it will be set when bringing up the netdevice (tun_alloc).
1556 if (!pmd->rxq[0].fd)
1559 struct rte_flow *flow;
1562 flow = LIST_FIRST(&pmd->implicit_flows);
1566 * Remove all implicit rules on the remote.
1567 * Keep the local rule to redirect packets on TX.
1568 * Keep also the last implicit local rule: ISOLATE.
1570 if (flow->msg.t.tcm_ifindex == pmd->if_index)
1572 if (tap_flow_destroy_pmd(pmd, flow, NULL) < 0)
1575 /* Switch the TC rule according to pmd->flow_isolate */
1576 if (tap_flow_implicit_create(pmd, TAP_ISOLATE) == -1)
1579 /* Switch the TC rule according to pmd->flow_isolate */
1580 if (tap_flow_implicit_create(pmd, TAP_ISOLATE) == -1)
1582 if (!pmd->remote_if_index)
1584 if (tap_flow_implicit_create(pmd, TAP_REMOTE_TX) < 0)
1586 if (tap_flow_implicit_create(pmd, TAP_REMOTE_LOCAL_MAC) < 0)
1588 if (tap_flow_implicit_create(pmd, TAP_REMOTE_BROADCAST) < 0)
1590 if (tap_flow_implicit_create(pmd, TAP_REMOTE_BROADCASTV6) < 0)
1592 if (dev->data->promiscuous &&
1593 tap_flow_implicit_create(pmd, TAP_REMOTE_PROMISC) < 0)
1595 if (dev->data->all_multicast &&
1596 tap_flow_implicit_create(pmd, TAP_REMOTE_ALLMULTI) < 0)
1601 pmd->flow_isolate = 0;
1602 return rte_flow_error_set(
1603 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1604 "TC rule creation failed");
1608 * Destroy all flows.
1610 * @see rte_flow_flush()
1614 tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1616 struct pmd_internals *pmd = dev->data->dev_private;
1617 struct rte_flow *flow;
1619 while (!LIST_EMPTY(&pmd->flows)) {
1620 flow = LIST_FIRST(&pmd->flows);
1621 if (tap_flow_destroy(dev, flow, error) < 0)
1628 * Add an implicit flow rule on the remote device to make sure traffic gets to
1629 * the tap netdevice from there.
1632 * Pointer to private structure.
1634 * The idx in the implicit_rte_flows array specifying which rule to apply.
1636 * @return -1 if the rule couldn't be applied, 0 otherwise.
1638 int tap_flow_implicit_create(struct pmd_internals *pmd,
1639 enum implicit_rule_index idx)
1641 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
1642 struct rte_flow_action *actions = implicit_rte_flows[idx].actions;
1643 struct rte_flow_action isolate_actions[2] = {
1645 .type = RTE_FLOW_ACTION_TYPE_END,
1648 struct rte_flow_item *items = implicit_rte_flows[idx].items;
1649 struct rte_flow_attr *attr = &implicit_rte_flows[idx].attr;
1650 struct rte_flow_item_eth eth_local = { .type = 0 };
1651 uint16_t if_index = pmd->remote_if_index;
1652 struct rte_flow *remote_flow = NULL;
1653 struct nlmsg *msg = NULL;
1655 struct rte_flow_item items_local[2] = {
1657 .type = items[0].type,
1659 .mask = items[0].mask,
1662 .type = items[1].type,
1666 remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1668 RTE_LOG(ERR, PMD, "Cannot allocate memory for rte_flow\n");
1671 msg = &remote_flow->msg;
1672 if (idx == TAP_REMOTE_TX) {
1673 if_index = pmd->if_index;
1674 } else if (idx == TAP_ISOLATE) {
1675 if_index = pmd->if_index;
1676 /* Don't be exclusive for this rule, it can be changed later. */
1677 flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE;
1678 isolate_actions[0].type = pmd->flow_isolate ?
1679 RTE_FLOW_ACTION_TYPE_DROP :
1680 RTE_FLOW_ACTION_TYPE_PASSTHRU;
1681 actions = isolate_actions;
1682 } else if (idx == TAP_REMOTE_LOCAL_MAC) {
1684 * eth addr couldn't be set in implicit_rte_flows[] as it is not
1685 * known at compile time.
1687 memcpy(ð_local.dst, &pmd->eth_addr, sizeof(pmd->eth_addr));
1688 items = items_local;
1690 tc_init_msg(msg, if_index, RTM_NEWTFILTER, flags);
1691 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1693 * The ISOLATE rule is always present and must have a static handle, as
1694 * the action is changed whether the feature is enabled (DROP) or
1695 * disabled (PASSTHRU).
1696 * There is just one REMOTE_PROMISCUOUS rule in all cases. It should
1697 * have a static handle such that adding it twice will fail with EEXIST
1698 * with any kernel version. Remark: old kernels may falsely accept the
1699 * same REMOTE_PROMISCUOUS rules if they had different handles.
1701 if (idx == TAP_ISOLATE)
1702 remote_flow->msg.t.tcm_handle = ISOLATE_HANDLE;
1703 else if (idx == TAP_REMOTE_PROMISC)
1704 remote_flow->msg.t.tcm_handle = REMOTE_PROMISCUOUS_HANDLE;
1706 tap_flow_set_handle(remote_flow);
1707 if (priv_flow_process(pmd, attr, items, actions, NULL,
1708 remote_flow, implicit_rte_flows[idx].mirred)) {
1709 RTE_LOG(ERR, PMD, "rte flow rule validation failed\n");
1712 err = tap_nl_send(pmd->nlsk_fd, &msg->nh);
1714 RTE_LOG(ERR, PMD, "Failure sending nl request\n");
1717 err = tap_nl_recv_ack(pmd->nlsk_fd);
1719 /* Silently ignore re-entering remote promiscuous rule */
1720 if (errno == EEXIST && idx == TAP_REMOTE_PROMISC)
1723 "Kernel refused TC filter rule creation (%d): %s\n",
1724 errno, strerror(errno));
1727 LIST_INSERT_HEAD(&pmd->implicit_flows, remote_flow, next);
1732 rte_free(remote_flow);
1737 * Remove specific implicit flow rule on the remote device.
1739 * @param[in, out] pmd
1740 * Pointer to private structure.
1742 * The idx in the implicit_rte_flows array specifying which rule to remove.
1744 * @return -1 if one of the implicit rules couldn't be created, 0 otherwise.
1746 int tap_flow_implicit_destroy(struct pmd_internals *pmd,
1747 enum implicit_rule_index idx)
1749 struct rte_flow *remote_flow;
1751 int idx_prio = implicit_rte_flows[idx].attr.priority + PRIORITY_OFFSET;
1753 for (remote_flow = LIST_FIRST(&pmd->implicit_flows);
1755 remote_flow = LIST_NEXT(remote_flow, next)) {
1756 cur_prio = (remote_flow->msg.t.tcm_info >> 16) & PRIORITY_MASK;
1757 if (cur_prio != idx_prio)
1759 return tap_flow_destroy_pmd(pmd, remote_flow, NULL);
1765 * Destroy all implicit flows.
1767 * @see rte_flow_flush()
1770 tap_flow_implicit_flush(struct pmd_internals *pmd, struct rte_flow_error *error)
1772 struct rte_flow *remote_flow;
1774 while (!LIST_EMPTY(&pmd->implicit_flows)) {
1775 remote_flow = LIST_FIRST(&pmd->implicit_flows);
1776 if (tap_flow_destroy_pmd(pmd, remote_flow, error) < 0)
1782 #define MAX_RSS_KEYS 256
1783 #define KEY_IDX_OFFSET (3 * MAX_RSS_KEYS)
1784 #define SEC_NAME_CLS_Q "cls_q"
1786 const char *sec_name[SEC_MAX] = {
1787 [SEC_L3_L4] = "l3_l4",
1791 * Enable RSS on tap: create TC rules for queuing.
1793 * @param[in, out] pmd
1794 * Pointer to private structure.
1797 * Pointer to rte_flow to get flow group
1800 * Pointer to error reporting if not NULL.
1802 * @return 0 on success, negative value on failure.
1804 static int rss_enable(struct pmd_internals *pmd,
1805 const struct rte_flow_attr *attr,
1806 struct rte_flow_error *error)
1808 struct rte_flow *rss_flow = NULL;
1809 struct nlmsg *msg = NULL;
1810 /* 4096 is the maximum number of instructions for a BPF program */
1811 char annotation[64];
1815 /* unlimit locked memory */
1816 struct rlimit memlock_limit = {
1817 .rlim_cur = RLIM_INFINITY,
1818 .rlim_max = RLIM_INFINITY,
1820 setrlimit(RLIMIT_MEMLOCK, &memlock_limit);
1822 /* Get a new map key for a new RSS rule */
1823 err = bpf_rss_key(KEY_CMD_INIT, NULL);
1826 error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1827 "Failed to initialize BPF RSS keys");
1833 * Create BPF RSS MAP
1835 pmd->map_fd = tap_flow_bpf_rss_map_create(sizeof(__u32), /* key size */
1836 sizeof(struct rss_key),
1838 if (pmd->map_fd < 0) {
1840 "Failed to create BPF map (%d): %s\n",
1841 errno, strerror(errno));
1843 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1844 "Kernel too old or not configured "
1845 "to support BPF maps");
1851 * Add a rule per queue to match reclassified packets and direct them to
1852 * the correct queue.
1854 for (i = 0; i < pmd->dev->data->nb_rx_queues; i++) {
1855 pmd->bpf_fd[i] = tap_flow_bpf_cls_q(i);
1856 if (pmd->bpf_fd[i] < 0) {
1858 "Failed to load BPF section %s for queue %d",
1861 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1863 "Kernel too old or not configured "
1864 "to support BPF programs loading");
1869 rss_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1872 "Cannot allocate memory for rte_flow");
1875 msg = &rss_flow->msg;
1876 tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER, NLM_F_REQUEST |
1877 NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
1878 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1879 tap_flow_set_handle(rss_flow);
1880 uint16_t group = attr->group << GROUP_SHIFT;
1881 uint16_t prio = group | (i + PRIORITY_OFFSET);
1882 msg->t.tcm_info = TC_H_MAKE(prio << 16, msg->t.tcm_info);
1883 msg->t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);
1885 tap_nlattr_add(&msg->nh, TCA_KIND, sizeof("bpf"), "bpf");
1886 if (tap_nlattr_nested_start(msg, TCA_OPTIONS) < 0)
1888 tap_nlattr_add32(&msg->nh, TCA_BPF_FD, pmd->bpf_fd[i]);
1889 snprintf(annotation, sizeof(annotation), "[%s%d]",
1891 tap_nlattr_add(&msg->nh, TCA_BPF_NAME, strlen(annotation) + 1,
1895 struct action_data adata = {
1899 .action = TC_ACT_PIPE,
1904 if (add_actions(rss_flow, 1, &adata, TCA_BPF_ACT) < 0)
1907 tap_nlattr_nested_finish(msg); /* nested TCA_OPTIONS */
1909 /* Netlink message is now ready to be sent */
1910 if (tap_nl_send(pmd->nlsk_fd, &msg->nh) < 0)
1912 err = tap_nl_recv_ack(pmd->nlsk_fd);
1915 "Kernel refused TC filter rule creation (%d): %s\n",
1916 errno, strerror(errno));
1919 LIST_INSERT_HEAD(&pmd->rss_flows, rss_flow, next);
1922 pmd->rss_enabled = 1;
1927 * Manage bpf RSS keys repository with operations: init, get, release
1930 * Command on RSS keys: init, get, release
1932 * @param[in, out] key_idx
1933 * Pointer to RSS Key index (out for get command, in for release command)
1935 * @return -1 if couldn't get, release or init the RSS keys, 0 otherwise.
1937 static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx)
1941 static __u32 num_used_keys;
1942 static __u32 rss_keys[MAX_RSS_KEYS] = {KEY_STAT_UNSPEC};
1943 static __u32 rss_keys_initialized;
1948 if (!rss_keys_initialized) {
1953 if (num_used_keys == RTE_DIM(rss_keys)) {
1958 *key_idx = num_used_keys % RTE_DIM(rss_keys);
1959 while (rss_keys[*key_idx] == KEY_STAT_USED)
1960 *key_idx = (*key_idx + 1) % RTE_DIM(rss_keys);
1962 rss_keys[*key_idx] = KEY_STAT_USED;
1965 * Add an offset to key_idx in order to handle a case of
1966 * RSS and non RSS flows mixture.
1967 * If a non RSS flow is destroyed it has an eBPF map
1968 * index 0 (initialized on flow creation) and might
1969 * unintentionally remove RSS entry 0 from eBPF map.
1970 * To avoid this issue, add an offset to the real index
1971 * during a KEY_CMD_GET operation and subtract this offset
1972 * during a KEY_CMD_RELEASE operation in order to restore
1975 *key_idx += KEY_IDX_OFFSET;
1979 case KEY_CMD_RELEASE:
1980 if (!rss_keys_initialized)
1984 * Subtract offest to restore real key index
1985 * If a non RSS flow is falsely trying to release map
1986 * entry 0 - the offset subtraction will calculate the real
1987 * map index as an out-of-range value and the release operation
1988 * will be silently ignored.
1990 key = *key_idx - KEY_IDX_OFFSET;
1991 if (key >= RTE_DIM(rss_keys))
1994 if (rss_keys[key] == KEY_STAT_USED) {
1995 rss_keys[key] = KEY_STAT_AVAILABLE;
2001 for (i = 0; i < RTE_DIM(rss_keys); i++)
2002 rss_keys[i] = KEY_STAT_AVAILABLE;
2004 rss_keys_initialized = 1;
2008 case KEY_CMD_DEINIT:
2009 for (i = 0; i < RTE_DIM(rss_keys); i++)
2010 rss_keys[i] = KEY_STAT_UNSPEC;
2012 rss_keys_initialized = 0;
2024 * Add RSS hash calculations and queue selection
2026 * @param[in, out] pmd
2027 * Pointer to internal structure. Used to set/get RSS map fd
2030 * Pointer to RSS flow actions
2033 * Pointer to error reporting if not NULL.
2035 * @return 0 on success, negative value on failure
2037 static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,
2038 const struct rte_flow_action_rss *rss,
2039 struct rte_flow_error *error)
2041 /* 4096 is the maximum number of instructions for a BPF program */
2044 struct rss_key rss_entry = { .hash_fields = 0,
2047 /* Get a new map key for a new RSS rule */
2048 err = bpf_rss_key(KEY_CMD_GET, &flow->key_idx);
2051 error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2052 "Failed to get BPF RSS key");
2057 /* Update RSS map entry with queues */
2058 rss_entry.nb_queues = rss->num;
2059 for (i = 0; i < rss->num; i++)
2060 rss_entry.queues[i] = rss->queue[i];
2061 rss_entry.hash_fields =
2062 (1 << HASH_FIELD_IPV4_L3_L4) | (1 << HASH_FIELD_IPV6_L3_L4);
2064 /* Add this RSS entry to map */
2065 err = tap_flow_bpf_update_rss_elem(pmd->map_fd,
2066 &flow->key_idx, &rss_entry);
2070 "Failed to update BPF map entry #%u (%d): %s\n",
2071 flow->key_idx, errno, strerror(errno));
2073 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2074 "Kernel too old or not configured "
2075 "to support BPF maps updates");
2082 * Load bpf rules to calculate hash for this key_idx
2085 flow->bpf_fd[SEC_L3_L4] =
2086 tap_flow_bpf_calc_l3_l4_hash(flow->key_idx, pmd->map_fd);
2087 if (flow->bpf_fd[SEC_L3_L4] < 0) {
2089 "Failed to load BPF section %s (%d): %s\n",
2090 sec_name[SEC_L3_L4], errno, strerror(errno));
2092 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2093 "Kernel too old or not configured "
2094 "to support BPF program loading");
2101 struct action_data adata[] = {
2105 .bpf_fd = flow->bpf_fd[SEC_L3_L4],
2106 .annotation = sec_name[SEC_L3_L4],
2108 .action = TC_ACT_PIPE,
2114 if (add_actions(flow, RTE_DIM(adata), adata,
2115 TCA_FLOWER_ACT) < 0)
2123 * Manage filter operations.
2126 * Pointer to Ethernet device structure.
2127 * @param filter_type
2130 * Operation to perform.
2132 * Pointer to operation-specific structure.
2135 * 0 on success, negative errno value on failure.
2138 tap_dev_filter_ctrl(struct rte_eth_dev *dev,
2139 enum rte_filter_type filter_type,
2140 enum rte_filter_op filter_op,
2143 switch (filter_type) {
2144 case RTE_ETH_FILTER_GENERIC:
2145 if (filter_op != RTE_ETH_FILTER_GET)
2147 *(const void **)arg = &tap_flow_ops;
2150 RTE_LOG(ERR, PMD, "%p: filter type (%d) not supported\n",
2151 (void *)dev, filter_type);