4 * Copyright 2017 6WIND S.A.
5 * Copyright 2017 Mellanox.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of 6WIND S.A. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/queue.h>
38 #include <rte_byteorder.h>
39 #include <rte_jhash.h>
40 #include <rte_malloc.h>
41 #include <rte_eth_tap.h>
43 #include <tap_autoconf.h>
44 #include <tap_tcmsgs.h>
46 #ifndef HAVE_TC_FLOWER
48 * For kernels < 4.2, this enum is not defined. Runtime checks will be made to
49 * avoid sending TC messages the kernel cannot understand.
56 TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */
57 TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */
58 TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */
59 TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */
60 TCA_FLOWER_KEY_ETH_TYPE, /* be16 */
61 TCA_FLOWER_KEY_IP_PROTO, /* u8 */
62 TCA_FLOWER_KEY_IPV4_SRC, /* be32 */
63 TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */
64 TCA_FLOWER_KEY_IPV4_DST, /* be32 */
65 TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */
66 TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */
67 TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */
68 TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */
69 TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */
70 TCA_FLOWER_KEY_TCP_SRC, /* be16 */
71 TCA_FLOWER_KEY_TCP_DST, /* be16 */
72 TCA_FLOWER_KEY_UDP_SRC, /* be16 */
73 TCA_FLOWER_KEY_UDP_DST, /* be16 */
76 #ifndef HAVE_TC_VLAN_ID
78 /* TCA_FLOWER_FLAGS, */
79 TCA_FLOWER_KEY_VLAN_ID = TCA_FLOWER_KEY_UDP_DST + 2, /* be16 */
80 TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */
81 TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */
85 #define ISOLATE_HANDLE 1
88 LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */
89 struct rte_flow *remote_flow; /* associated remote flow */
97 struct rte_flow *flow;
101 struct rte_flow_attr attr;
102 struct rte_flow_item items[2];
103 struct rte_flow_action actions[2];
107 static int tap_flow_create_eth(const struct rte_flow_item *item, void *data);
108 static int tap_flow_create_vlan(const struct rte_flow_item *item, void *data);
109 static int tap_flow_create_ipv4(const struct rte_flow_item *item, void *data);
110 static int tap_flow_create_ipv6(const struct rte_flow_item *item, void *data);
111 static int tap_flow_create_udp(const struct rte_flow_item *item, void *data);
112 static int tap_flow_create_tcp(const struct rte_flow_item *item, void *data);
114 tap_flow_validate(struct rte_eth_dev *dev,
115 const struct rte_flow_attr *attr,
116 const struct rte_flow_item items[],
117 const struct rte_flow_action actions[],
118 struct rte_flow_error *error);
120 static struct rte_flow *
121 tap_flow_create(struct rte_eth_dev *dev,
122 const struct rte_flow_attr *attr,
123 const struct rte_flow_item items[],
124 const struct rte_flow_action actions[],
125 struct rte_flow_error *error);
128 tap_flow_destroy(struct rte_eth_dev *dev,
129 struct rte_flow *flow,
130 struct rte_flow_error *error);
133 tap_flow_isolate(struct rte_eth_dev *dev,
135 struct rte_flow_error *error);
137 static const struct rte_flow_ops tap_flow_ops = {
138 .validate = tap_flow_validate,
139 .create = tap_flow_create,
140 .destroy = tap_flow_destroy,
141 .flush = tap_flow_flush,
142 .isolate = tap_flow_isolate,
145 /* Static initializer for items. */
147 (const enum rte_flow_item_type []){ \
148 __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
151 /* Structure to generate a simple graph of layers supported by the NIC. */
152 struct tap_flow_items {
153 /* Bit-mask corresponding to what is supported for this item. */
155 const unsigned int mask_sz; /* Bit-mask size in bytes. */
157 * Bit-mask corresponding to the default mask, if none is provided
158 * along with the item.
160 const void *default_mask;
162 * Conversion function from rte_flow to netlink attributes.
165 * rte_flow item to convert.
167 * Internal structure to store the conversion.
170 * 0 on success, negative value otherwise.
172 int (*convert)(const struct rte_flow_item *item, void *data);
173 /** List of possible following items. */
174 const enum rte_flow_item_type *const items;
177 /* Graph of supported items and associated actions. */
178 static const struct tap_flow_items tap_flow_items[] = {
179 [RTE_FLOW_ITEM_TYPE_END] = {
180 .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH),
182 [RTE_FLOW_ITEM_TYPE_ETH] = {
184 RTE_FLOW_ITEM_TYPE_VLAN,
185 RTE_FLOW_ITEM_TYPE_IPV4,
186 RTE_FLOW_ITEM_TYPE_IPV6),
187 .mask = &(const struct rte_flow_item_eth){
188 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
189 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
192 .mask_sz = sizeof(struct rte_flow_item_eth),
193 .default_mask = &rte_flow_item_eth_mask,
194 .convert = tap_flow_create_eth,
196 [RTE_FLOW_ITEM_TYPE_VLAN] = {
197 .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4,
198 RTE_FLOW_ITEM_TYPE_IPV6),
199 .mask = &(const struct rte_flow_item_vlan){
201 /* DEI matching is not supported */
202 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
208 .mask_sz = sizeof(struct rte_flow_item_vlan),
209 .default_mask = &rte_flow_item_vlan_mask,
210 .convert = tap_flow_create_vlan,
212 [RTE_FLOW_ITEM_TYPE_IPV4] = {
213 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
214 RTE_FLOW_ITEM_TYPE_TCP),
215 .mask = &(const struct rte_flow_item_ipv4){
222 .mask_sz = sizeof(struct rte_flow_item_ipv4),
223 .default_mask = &rte_flow_item_ipv4_mask,
224 .convert = tap_flow_create_ipv4,
226 [RTE_FLOW_ITEM_TYPE_IPV6] = {
227 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
228 RTE_FLOW_ITEM_TYPE_TCP),
229 .mask = &(const struct rte_flow_item_ipv6){
232 "\xff\xff\xff\xff\xff\xff\xff\xff"
233 "\xff\xff\xff\xff\xff\xff\xff\xff",
236 "\xff\xff\xff\xff\xff\xff\xff\xff"
237 "\xff\xff\xff\xff\xff\xff\xff\xff",
242 .mask_sz = sizeof(struct rte_flow_item_ipv6),
243 .default_mask = &rte_flow_item_ipv6_mask,
244 .convert = tap_flow_create_ipv6,
246 [RTE_FLOW_ITEM_TYPE_UDP] = {
247 .mask = &(const struct rte_flow_item_udp){
253 .mask_sz = sizeof(struct rte_flow_item_udp),
254 .default_mask = &rte_flow_item_udp_mask,
255 .convert = tap_flow_create_udp,
257 [RTE_FLOW_ITEM_TYPE_TCP] = {
258 .mask = &(const struct rte_flow_item_tcp){
264 .mask_sz = sizeof(struct rte_flow_item_tcp),
265 .default_mask = &rte_flow_item_tcp_mask,
266 .convert = tap_flow_create_tcp,
271 * TC rules, by growing priority
273 * Remote netdevice Tap netdevice
274 * +-------------+-------------+ +-------------+-------------+
275 * | Ingress | Egress | | Ingress | Egress |
276 * |-------------|-------------| |-------------|-------------|
277 * | | \ / | | | REMOTE TX | prio 1
278 * | | \ / | | | \ / | prio 2
279 * | EXPLICIT | \ / | | EXPLICIT | \ / | .
280 * | | \ / | | | \ / | .
281 * | RULES | X | | RULES | X | .
282 * | . | / \ | | . | / \ | .
283 * | . | / \ | | . | / \ | .
284 * | . | / \ | | . | / \ | .
285 * | . | / \ | | . | / \ | .
287 * .... .... .... ....
289 * | . | \ / | | . | \ / | .
290 * | . | \ / | | . | \ / | .
291 * | | \ / | | | \ / |
292 * | LOCAL_MAC | \ / | | \ / | \ / | last prio - 5
293 * | PROMISC | X | | \ / | X | last prio - 4
294 * | ALLMULTI | / \ | | X | / \ | last prio - 3
295 * | BROADCAST | / \ | | / \ | / \ | last prio - 2
296 * | BROADCASTV6 | / \ | | / \ | / \ | last prio - 1
297 * | xx | / \ | | ISOLATE | / \ | last prio
298 * +-------------+-------------+ +-------------+-------------+
300 * The implicit flow rules are stored in a list in with mandatorily the last two
301 * being the ISOLATE and REMOTE_TX rules. e.g.:
303 * LOCAL_MAC -> BROADCAST -> BROADCASTV6 -> REMOTE_TX -> ISOLATE -> NULL
305 * That enables tap_flow_isolate() to remove implicit rules by popping the list
306 * head and remove it as long as it applies on the remote netdevice. The
307 * implicit rule for TX redirection is not removed, as isolate concerns only
311 static struct remote_rule implicit_rte_flows[TAP_REMOTE_MAX_IDX] = {
312 [TAP_REMOTE_LOCAL_MAC] = {
315 .priority = PRIORITY_MASK - TAP_REMOTE_LOCAL_MAC,
319 .type = RTE_FLOW_ITEM_TYPE_ETH,
320 .mask = &(const struct rte_flow_item_eth){
321 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
325 .type = RTE_FLOW_ITEM_TYPE_END,
327 .mirred = TCA_EGRESS_REDIR,
329 [TAP_REMOTE_BROADCAST] = {
332 .priority = PRIORITY_MASK - TAP_REMOTE_BROADCAST,
336 .type = RTE_FLOW_ITEM_TYPE_ETH,
337 .mask = &(const struct rte_flow_item_eth){
338 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
340 .spec = &(const struct rte_flow_item_eth){
341 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
345 .type = RTE_FLOW_ITEM_TYPE_END,
347 .mirred = TCA_EGRESS_MIRROR,
349 [TAP_REMOTE_BROADCASTV6] = {
352 .priority = PRIORITY_MASK - TAP_REMOTE_BROADCASTV6,
356 .type = RTE_FLOW_ITEM_TYPE_ETH,
357 .mask = &(const struct rte_flow_item_eth){
358 .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
360 .spec = &(const struct rte_flow_item_eth){
361 .dst.addr_bytes = "\x33\x33\x00\x00\x00\x00",
365 .type = RTE_FLOW_ITEM_TYPE_END,
367 .mirred = TCA_EGRESS_MIRROR,
369 [TAP_REMOTE_PROMISC] = {
372 .priority = PRIORITY_MASK - TAP_REMOTE_PROMISC,
376 .type = RTE_FLOW_ITEM_TYPE_VOID,
379 .type = RTE_FLOW_ITEM_TYPE_END,
381 .mirred = TCA_EGRESS_MIRROR,
383 [TAP_REMOTE_ALLMULTI] = {
386 .priority = PRIORITY_MASK - TAP_REMOTE_ALLMULTI,
390 .type = RTE_FLOW_ITEM_TYPE_ETH,
391 .mask = &(const struct rte_flow_item_eth){
392 .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
394 .spec = &(const struct rte_flow_item_eth){
395 .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00",
399 .type = RTE_FLOW_ITEM_TYPE_END,
401 .mirred = TCA_EGRESS_MIRROR,
406 .priority = TAP_REMOTE_TX,
410 .type = RTE_FLOW_ITEM_TYPE_VOID,
413 .type = RTE_FLOW_ITEM_TYPE_END,
415 .mirred = TCA_EGRESS_MIRROR,
420 .priority = PRIORITY_MASK - TAP_ISOLATE,
424 .type = RTE_FLOW_ITEM_TYPE_VOID,
427 .type = RTE_FLOW_ITEM_TYPE_END,
433 * Make as much checks as possible on an Ethernet item, and if a flow is
434 * provided, fill it appropriately with Ethernet info.
437 * Item specification.
438 * @param[in, out] data
439 * Additional data structure to tell next layers we've been here.
442 * 0 if checks are alright, -1 otherwise.
445 tap_flow_create_eth(const struct rte_flow_item *item, void *data)
447 struct convert_data *info = (struct convert_data *)data;
448 const struct rte_flow_item_eth *spec = item->spec;
449 const struct rte_flow_item_eth *mask = item->mask;
450 struct rte_flow *flow = info->flow;
453 /* use default mask if none provided */
455 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_ETH].default_mask;
456 /* TC does not support eth_type masking. Only accept if exact match. */
457 if (mask->type && mask->type != 0xffff)
461 /* store eth_type for consistency if ipv4/6 pattern item comes next */
462 if (spec->type & mask->type)
463 info->eth_type = spec->type;
467 if (!is_zero_ether_addr(&spec->dst)) {
468 nlattr_add(&msg->nh, TCA_FLOWER_KEY_ETH_DST, ETHER_ADDR_LEN,
469 &spec->dst.addr_bytes);
471 TCA_FLOWER_KEY_ETH_DST_MASK, ETHER_ADDR_LEN,
472 &mask->dst.addr_bytes);
474 if (!is_zero_ether_addr(&mask->src)) {
475 nlattr_add(&msg->nh, TCA_FLOWER_KEY_ETH_SRC, ETHER_ADDR_LEN,
476 &spec->src.addr_bytes);
478 TCA_FLOWER_KEY_ETH_SRC_MASK, ETHER_ADDR_LEN,
479 &mask->src.addr_bytes);
485 * Make as much checks as possible on a VLAN item, and if a flow is provided,
486 * fill it appropriately with VLAN info.
489 * Item specification.
490 * @param[in, out] data
491 * Additional data structure to tell next layers we've been here.
494 * 0 if checks are alright, -1 otherwise.
497 tap_flow_create_vlan(const struct rte_flow_item *item, void *data)
499 struct convert_data *info = (struct convert_data *)data;
500 const struct rte_flow_item_vlan *spec = item->spec;
501 const struct rte_flow_item_vlan *mask = item->mask;
502 struct rte_flow *flow = info->flow;
505 /* use default mask if none provided */
507 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_VLAN].default_mask;
508 /* TC does not support tpid masking. Only accept if exact match. */
509 if (mask->tpid && mask->tpid != 0xffff)
511 /* Double-tagging not supported. */
512 if (spec && mask->tpid && spec->tpid != htons(ETH_P_8021Q))
518 msg->t.tcm_info = TC_H_MAKE(msg->t.tcm_info, htons(ETH_P_8021Q));
519 #define VLAN_PRIO(tci) ((tci) >> 13)
520 #define VLAN_ID(tci) ((tci) & 0xfff)
524 uint16_t tci = ntohs(spec->tci) & mask->tci;
525 uint16_t prio = VLAN_PRIO(tci);
526 uint8_t vid = VLAN_ID(tci);
529 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_VLAN_PRIO, prio);
531 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_VLAN_ID, vid);
537 * Make as much checks as possible on an IPv4 item, and if a flow is provided,
538 * fill it appropriately with IPv4 info.
541 * Item specification.
542 * @param[in, out] data
543 * Additional data structure to tell next layers we've been here.
546 * 0 if checks are alright, -1 otherwise.
549 tap_flow_create_ipv4(const struct rte_flow_item *item, void *data)
551 struct convert_data *info = (struct convert_data *)data;
552 const struct rte_flow_item_ipv4 *spec = item->spec;
553 const struct rte_flow_item_ipv4 *mask = item->mask;
554 struct rte_flow *flow = info->flow;
557 /* use default mask if none provided */
559 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_IPV4].default_mask;
560 /* check that previous eth type is compatible with ipv4 */
561 if (info->eth_type && info->eth_type != htons(ETH_P_IP))
563 /* store ip_proto for consistency if udp/tcp pattern item comes next */
565 info->ip_proto = spec->hdr.next_proto_id;
570 info->eth_type = htons(ETH_P_IP);
573 if (spec->hdr.dst_addr) {
574 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_DST,
576 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_DST_MASK,
579 if (spec->hdr.src_addr) {
580 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_SRC,
582 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_SRC_MASK,
585 if (spec->hdr.next_proto_id)
586 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO,
587 spec->hdr.next_proto_id);
592 * Make as much checks as possible on an IPv6 item, and if a flow is provided,
593 * fill it appropriately with IPv6 info.
596 * Item specification.
597 * @param[in, out] data
598 * Additional data structure to tell next layers we've been here.
601 * 0 if checks are alright, -1 otherwise.
604 tap_flow_create_ipv6(const struct rte_flow_item *item, void *data)
606 struct convert_data *info = (struct convert_data *)data;
607 const struct rte_flow_item_ipv6 *spec = item->spec;
608 const struct rte_flow_item_ipv6 *mask = item->mask;
609 struct rte_flow *flow = info->flow;
610 uint8_t empty_addr[16] = { 0 };
613 /* use default mask if none provided */
615 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_IPV6].default_mask;
616 /* check that previous eth type is compatible with ipv6 */
617 if (info->eth_type && info->eth_type != htons(ETH_P_IPV6))
619 /* store ip_proto for consistency if udp/tcp pattern item comes next */
621 info->ip_proto = spec->hdr.proto;
626 info->eth_type = htons(ETH_P_IPV6);
629 if (memcmp(spec->hdr.dst_addr, empty_addr, 16)) {
630 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST,
631 sizeof(spec->hdr.dst_addr), &spec->hdr.dst_addr);
632 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST_MASK,
633 sizeof(mask->hdr.dst_addr), &mask->hdr.dst_addr);
635 if (memcmp(spec->hdr.src_addr, empty_addr, 16)) {
636 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC,
637 sizeof(spec->hdr.src_addr), &spec->hdr.src_addr);
638 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC_MASK,
639 sizeof(mask->hdr.src_addr), &mask->hdr.src_addr);
642 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, spec->hdr.proto);
647 * Make as much checks as possible on a UDP item, and if a flow is provided,
648 * fill it appropriately with UDP info.
651 * Item specification.
652 * @param[in, out] data
653 * Additional data structure to tell next layers we've been here.
656 * 0 if checks are alright, -1 otherwise.
659 tap_flow_create_udp(const struct rte_flow_item *item, void *data)
661 struct convert_data *info = (struct convert_data *)data;
662 const struct rte_flow_item_udp *spec = item->spec;
663 const struct rte_flow_item_udp *mask = item->mask;
664 struct rte_flow *flow = info->flow;
667 /* use default mask if none provided */
669 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_UDP].default_mask;
670 /* check that previous ip_proto is compatible with udp */
671 if (info->ip_proto && info->ip_proto != IPPROTO_UDP)
673 /* TC does not support UDP port masking. Only accept if exact match. */
674 if ((mask->hdr.src_port && mask->hdr.src_port != 0xffff) ||
675 (mask->hdr.dst_port && mask->hdr.dst_port != 0xffff))
680 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, IPPROTO_UDP);
683 if (spec->hdr.dst_port & mask->hdr.dst_port)
684 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_UDP_DST,
686 if (spec->hdr.src_port & mask->hdr.src_port)
687 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_UDP_SRC,
693 * Make as much checks as possible on a TCP item, and if a flow is provided,
694 * fill it appropriately with TCP info.
697 * Item specification.
698 * @param[in, out] data
699 * Additional data structure to tell next layers we've been here.
702 * 0 if checks are alright, -1 otherwise.
705 tap_flow_create_tcp(const struct rte_flow_item *item, void *data)
707 struct convert_data *info = (struct convert_data *)data;
708 const struct rte_flow_item_tcp *spec = item->spec;
709 const struct rte_flow_item_tcp *mask = item->mask;
710 struct rte_flow *flow = info->flow;
713 /* use default mask if none provided */
715 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_TCP].default_mask;
716 /* check that previous ip_proto is compatible with tcp */
717 if (info->ip_proto && info->ip_proto != IPPROTO_TCP)
719 /* TC does not support TCP port masking. Only accept if exact match. */
720 if ((mask->hdr.src_port && mask->hdr.src_port != 0xffff) ||
721 (mask->hdr.dst_port && mask->hdr.dst_port != 0xffff))
726 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, IPPROTO_TCP);
729 if (spec->hdr.dst_port & mask->hdr.dst_port)
730 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_TCP_DST,
732 if (spec->hdr.src_port & mask->hdr.src_port)
733 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_TCP_SRC,
739 * Check support for a given item.
742 * Item specification.
744 * Bit-Mask size in bytes.
745 * @param[in] supported_mask
746 * Bit-mask covering supported fields to compare with spec, last and mask in
748 * @param[in] default_mask
749 * Bit-mask default mask if none is provided in \item.
755 tap_flow_item_validate(const struct rte_flow_item *item,
757 const uint8_t *supported_mask,
758 const uint8_t *default_mask)
762 /* An empty layer is allowed, as long as all fields are NULL */
763 if (!item->spec && (item->mask || item->last))
765 /* Is the item spec compatible with what the NIC supports? */
766 if (item->spec && !item->mask) {
768 const uint8_t *spec = item->spec;
770 for (i = 0; i < size; ++i)
771 if ((spec[i] | supported_mask[i]) != supported_mask[i])
773 /* Is the default mask compatible with what the NIC supports? */
774 for (i = 0; i < size; i++)
775 if ((default_mask[i] | supported_mask[i]) !=
779 /* Is the item last compatible with what the NIC supports? */
780 if (item->last && !item->mask) {
782 const uint8_t *spec = item->last;
784 for (i = 0; i < size; ++i)
785 if ((spec[i] | supported_mask[i]) != supported_mask[i])
788 /* Is the item mask compatible with what the NIC supports? */
791 const uint8_t *spec = item->mask;
793 for (i = 0; i < size; ++i)
794 if ((spec[i] | supported_mask[i]) != supported_mask[i])
798 * Once masked, Are item spec and item last equal?
799 * TC does not support range so anything else is invalid.
801 if (item->spec && item->last) {
804 const uint8_t *apply = default_mask;
809 for (i = 0; i < size; ++i) {
810 spec[i] = ((const uint8_t *)item->spec)[i] & apply[i];
811 last[i] = ((const uint8_t *)item->last)[i] & apply[i];
813 ret = memcmp(spec, last, size);
819 * Transform a DROP/PASSTHRU action item in the provided flow for TC.
821 * @param[in, out] flow
824 * Appropriate action to be set in the TCA_GACT_PARMS structure.
827 * 0 if checks are alright, -1 otherwise.
830 add_action_gact(struct rte_flow *flow, int action)
832 struct nlmsg *msg = &flow->msg;
833 size_t act_index = 1;
838 if (nlattr_nested_start(msg, TCA_FLOWER_ACT) < 0)
840 if (nlattr_nested_start(msg, act_index++) < 0)
842 nlattr_add(&msg->nh, TCA_ACT_KIND, sizeof("gact"), "gact");
843 if (nlattr_nested_start(msg, TCA_ACT_OPTIONS) < 0)
845 nlattr_add(&msg->nh, TCA_GACT_PARMS, sizeof(p), &p);
846 nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
847 nlattr_nested_finish(msg); /* nested act_index */
848 nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
853 * Transform a MIRRED action item in the provided flow for TC.
855 * @param[in, out] flow
858 * Netdevice ifindex, where to mirror/redirect packet to.
859 * @param[in] action_type
860 * Either TCA_EGRESS_REDIR for redirection or TCA_EGRESS_MIRROR for mirroring.
863 * 0 if checks are alright, -1 otherwise.
866 add_action_mirred(struct rte_flow *flow, uint16_t ifindex, uint16_t action_type)
868 struct nlmsg *msg = &flow->msg;
869 size_t act_index = 1;
870 struct tc_mirred p = {
871 .eaction = action_type,
875 if (nlattr_nested_start(msg, TCA_FLOWER_ACT) < 0)
877 if (nlattr_nested_start(msg, act_index++) < 0)
879 nlattr_add(&msg->nh, TCA_ACT_KIND, sizeof("mirred"), "mirred");
880 if (nlattr_nested_start(msg, TCA_ACT_OPTIONS) < 0)
882 if (action_type == TCA_EGRESS_MIRROR)
883 p.action = TC_ACT_PIPE;
885 p.action = TC_ACT_STOLEN;
886 nlattr_add(&msg->nh, TCA_MIRRED_PARMS, sizeof(p), &p);
887 nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
888 nlattr_nested_finish(msg); /* nested act_index */
889 nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
894 * Transform a QUEUE action item in the provided flow for TC.
896 * @param[in, out] flow
902 * 0 if checks are alright, -1 otherwise.
905 add_action_skbedit(struct rte_flow *flow, uint16_t queue)
907 struct nlmsg *msg = &flow->msg;
908 size_t act_index = 1;
909 struct tc_skbedit p = {
910 .action = TC_ACT_PIPE
913 if (nlattr_nested_start(msg, TCA_FLOWER_ACT) < 0)
915 if (nlattr_nested_start(msg, act_index++) < 0)
917 nlattr_add(&msg->nh, TCA_ACT_KIND, sizeof("skbedit"), "skbedit");
918 if (nlattr_nested_start(msg, TCA_ACT_OPTIONS) < 0)
920 nlattr_add(&msg->nh, TCA_SKBEDIT_PARMS, sizeof(p), &p);
921 nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING, queue);
922 nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
923 nlattr_nested_finish(msg); /* nested act_index */
924 nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
929 * Validate a flow supported by TC.
930 * If flow param is not NULL, then also fill the netlink message inside.
933 * Pointer to private structure.
935 * Flow rule attributes.
937 * Pattern specification (list terminated by the END pattern item).
939 * Associated actions (list terminated by the END action).
941 * Perform verbose error reporting if not NULL.
942 * @param[in, out] flow
943 * Flow structure to update.
945 * If set to TCA_EGRESS_REDIR, provided actions will be replaced with a
946 * redirection to the tap netdevice, and the TC rule will be configured
947 * on the remote netdevice in pmd.
948 * If set to TCA_EGRESS_MIRROR, provided actions will be replaced with a
949 * mirroring to the tap netdevice, and the TC rule will be configured
950 * on the remote netdevice in pmd. Matching packets will thus be duplicated.
951 * If set to 0, the standard behavior is to be used: set correct actions for
952 * the TC rule, and apply it on the tap netdevice.
955 * 0 on success, a negative errno value otherwise and rte_errno is set.
958 priv_flow_process(struct pmd_internals *pmd,
959 const struct rte_flow_attr *attr,
960 const struct rte_flow_item items[],
961 const struct rte_flow_action actions[],
962 struct rte_flow_error *error,
963 struct rte_flow *flow,
966 const struct tap_flow_items *cur_item = tap_flow_items;
967 struct convert_data data = {
972 int action = 0; /* Only one action authorized for now */
974 if (attr->group > MAX_GROUP) {
976 error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
977 NULL, "group value too big: cannot exceed 15");
980 if (attr->priority > MAX_PRIORITY) {
982 error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
983 NULL, "priority value too big");
986 uint16_t group = attr->group << GROUP_SHIFT;
987 uint16_t prio = group | (attr->priority + PRIORITY_OFFSET);
988 flow->msg.t.tcm_info = TC_H_MAKE(prio << 16,
989 flow->msg.t.tcm_info);
994 * If attr->ingress, the rule applies on remote ingress
995 * to match incoming packets
996 * If attr->egress, the rule applies on tap ingress (as
997 * seen from the kernel) to deal with packets going out
1000 flow->msg.t.tcm_parent = TC_H_MAKE(TC_H_INGRESS, 0);
1002 /* Standard rule on tap egress (kernel standpoint). */
1003 flow->msg.t.tcm_parent =
1004 TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);
1006 /* use flower filter type */
1007 nlattr_add(&flow->msg.nh, TCA_KIND, sizeof("flower"), "flower");
1008 if (nlattr_nested_start(&flow->msg, TCA_OPTIONS) < 0)
1009 goto exit_item_not_supported;
1011 for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) {
1012 const struct tap_flow_items *token = NULL;
1016 if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
1020 cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END;
1022 if (cur_item->items[i] == items->type) {
1023 token = &tap_flow_items[items->type];
1028 goto exit_item_not_supported;
1030 err = tap_flow_item_validate(
1031 items, cur_item->mask_sz,
1032 (const uint8_t *)cur_item->mask,
1033 (const uint8_t *)cur_item->default_mask);
1035 goto exit_item_not_supported;
1036 if (flow && cur_item->convert) {
1037 err = cur_item->convert(items, &data);
1039 goto exit_item_not_supported;
1044 nlattr_add16(&flow->msg.nh, TCA_FLOWER_KEY_ETH_TYPE,
1045 htons(ETH_P_8021Q));
1046 nlattr_add16(&flow->msg.nh,
1047 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
1049 data.eth_type : htons(ETH_P_ALL));
1050 } else if (data.eth_type) {
1051 nlattr_add16(&flow->msg.nh, TCA_FLOWER_KEY_ETH_TYPE,
1055 if (mirred && flow) {
1056 uint16_t if_index = pmd->if_index;
1059 * If attr->egress && mirred, then this is a special
1060 * case where the rule must be applied on the tap, to
1061 * redirect packets coming from the DPDK App, out
1062 * through the remote netdevice.
1065 if_index = pmd->remote_if_index;
1066 if (add_action_mirred(flow, if_index, mirred) < 0)
1067 goto exit_action_not_supported;
1071 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
1074 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
1076 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
1078 goto exit_action_not_supported;
1081 err = add_action_gact(flow, TC_ACT_SHOT);
1082 } else if (actions->type == RTE_FLOW_ACTION_TYPE_PASSTHRU) {
1084 goto exit_action_not_supported;
1087 err = add_action_gact(flow, TC_ACT_UNSPEC);
1088 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
1089 const struct rte_flow_action_queue *queue =
1090 (const struct rte_flow_action_queue *)
1093 goto exit_action_not_supported;
1095 if (!queue || (queue->index >= pmd->nb_queues))
1096 goto exit_action_not_supported;
1098 err = add_action_skbedit(flow, queue->index);
1100 goto exit_action_not_supported;
1103 goto exit_action_not_supported;
1107 nlattr_nested_finish(&flow->msg); /* nested TCA_OPTIONS */
1109 exit_item_not_supported:
1110 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
1111 items, "item not supported");
1113 exit_action_not_supported:
1114 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
1115 actions, "action not supported");
1124 * @see rte_flow_validate()
1128 tap_flow_validate(struct rte_eth_dev *dev,
1129 const struct rte_flow_attr *attr,
1130 const struct rte_flow_item items[],
1131 const struct rte_flow_action actions[],
1132 struct rte_flow_error *error)
1134 struct pmd_internals *pmd = dev->data->dev_private;
1136 return priv_flow_process(pmd, attr, items, actions, error, NULL, 0);
1140 * Set a unique handle in a flow.
1142 * The kernel supports TC rules with equal priority, as long as they use the
1143 * same matching fields (e.g.: dst mac and ipv4) with different values (and
1144 * full mask to ensure no collision is possible).
1145 * In those rules, the handle (uint32_t) is the part that would identify
1146 * specifically each rule.
1148 * On 32-bit architectures, the handle can simply be the flow's pointer address.
1149 * On 64-bit architectures, we rely on jhash(flow) to find a (sufficiently)
1152 * @param[in, out] flow
1153 * The flow that needs its handle set.
1156 tap_flow_set_handle(struct rte_flow *flow)
1158 uint32_t handle = 0;
1160 if (sizeof(flow) > 4)
1161 handle = rte_jhash(&flow, sizeof(flow), 1);
1163 handle = (uintptr_t)flow;
1164 /* must be at least 1 to avoid letting the kernel choose one for us */
1167 flow->msg.t.tcm_handle = handle;
1173 * @see rte_flow_create()
1176 static struct rte_flow *
1177 tap_flow_create(struct rte_eth_dev *dev,
1178 const struct rte_flow_attr *attr,
1179 const struct rte_flow_item items[],
1180 const struct rte_flow_action actions[],
1181 struct rte_flow_error *error)
1183 struct pmd_internals *pmd = dev->data->dev_private;
1184 struct rte_flow *remote_flow = NULL;
1185 struct rte_flow *flow = NULL;
1186 struct nlmsg *msg = NULL;
1189 if (!pmd->if_index) {
1190 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1192 "can't create rule, ifindex not found");
1196 * No rules configured through standard rte_flow should be set on the
1197 * priorities used by implicit rules.
1199 if ((attr->group == MAX_GROUP) &&
1200 attr->priority > (MAX_PRIORITY - TAP_REMOTE_MAX_IDX)) {
1202 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1203 NULL, "priority value too big");
1206 flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1208 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1209 NULL, "cannot allocate memory for rte_flow");
1213 tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER,
1214 NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
1215 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1216 tap_flow_set_handle(flow);
1217 if (priv_flow_process(pmd, attr, items, actions, error, flow, 0))
1219 err = nl_send(pmd->nlsk_fd, &msg->nh);
1221 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1222 NULL, "couldn't send request to kernel");
1225 err = nl_recv_ack(pmd->nlsk_fd);
1228 "Kernel refused TC filter rule creation (%d): %s\n",
1229 errno, strerror(errno));
1230 rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_HANDLE,
1232 "overlapping rules or Kernel too old for flower support");
1235 LIST_INSERT_HEAD(&pmd->flows, flow, next);
1237 * If a remote device is configured, a TC rule with identical items for
1238 * matching must be set on that device, with a single action: redirect
1239 * to the local pmd->if_index.
1241 if (pmd->remote_if_index) {
1242 remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1245 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1246 "cannot allocate memory for rte_flow");
1249 msg = &remote_flow->msg;
1250 /* set the rule if_index for the remote netdevice */
1252 msg, pmd->remote_if_index, RTM_NEWTFILTER,
1253 NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
1254 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1255 tap_flow_set_handle(remote_flow);
1256 if (priv_flow_process(pmd, attr, items, NULL,
1257 error, remote_flow, TCA_EGRESS_REDIR)) {
1259 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1260 NULL, "rte flow rule validation failed");
1263 err = nl_send(pmd->nlsk_fd, &msg->nh);
1266 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1267 NULL, "Failure sending nl request");
1270 err = nl_recv_ack(pmd->nlsk_fd);
1273 "Kernel refused TC filter rule creation (%d): %s\n",
1274 errno, strerror(errno));
1276 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1278 "overlapping rules or Kernel too old for flower support");
1281 flow->remote_flow = remote_flow;
1286 rte_free(remote_flow);
1293 * Destroy a flow using pointer to pmd_internal.
1295 * @param[in, out] pmd
1296 * Pointer to private structure.
1298 * Pointer to the flow to destroy.
1299 * @param[in, out] error
1300 * Pointer to the flow error handler
1302 * @return 0 if the flow could be destroyed, -1 otherwise.
1305 tap_flow_destroy_pmd(struct pmd_internals *pmd,
1306 struct rte_flow *flow,
1307 struct rte_flow_error *error)
1309 struct rte_flow *remote_flow = flow->remote_flow;
1312 LIST_REMOVE(flow, next);
1313 flow->msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1314 flow->msg.nh.nlmsg_type = RTM_DELTFILTER;
1316 ret = nl_send(pmd->nlsk_fd, &flow->msg.nh);
1318 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1319 NULL, "couldn't send request to kernel");
1322 ret = nl_recv_ack(pmd->nlsk_fd);
1323 /* If errno is ENOENT, the rule is already no longer in the kernel. */
1324 if (ret < 0 && errno == ENOENT)
1328 "Kernel refused TC filter rule deletion (%d): %s\n",
1329 errno, strerror(errno));
1331 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1332 "couldn't receive kernel ack to our request");
1336 remote_flow->msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1337 remote_flow->msg.nh.nlmsg_type = RTM_DELTFILTER;
1339 ret = nl_send(pmd->nlsk_fd, &remote_flow->msg.nh);
1342 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1343 NULL, "Failure sending nl request");
1346 ret = nl_recv_ack(pmd->nlsk_fd);
1347 if (ret < 0 && errno == ENOENT)
1351 "Kernel refused TC filter rule deletion (%d): %s\n",
1352 errno, strerror(errno));
1354 error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1355 NULL, "Failure trying to receive nl ack");
1361 rte_free(remote_flow);
1369 * @see rte_flow_destroy()
1373 tap_flow_destroy(struct rte_eth_dev *dev,
1374 struct rte_flow *flow,
1375 struct rte_flow_error *error)
1377 struct pmd_internals *pmd = dev->data->dev_private;
1379 return tap_flow_destroy_pmd(pmd, flow, error);
1383 * Enable/disable flow isolation.
1385 * @see rte_flow_isolate()
1389 tap_flow_isolate(struct rte_eth_dev *dev,
1391 struct rte_flow_error *error __rte_unused)
1393 struct pmd_internals *pmd = dev->data->dev_private;
1396 pmd->flow_isolate = 1;
1398 pmd->flow_isolate = 0;
1400 * If netdevice is there, setup appropriate flow rules immediately.
1401 * Otherwise it will be set when bringing up the netdevice (tun_alloc).
1403 if (!pmd->rxq[0].fd)
1406 struct rte_flow *flow;
1409 flow = LIST_FIRST(&pmd->implicit_flows);
1413 * Remove all implicit rules on the remote.
1414 * Keep the local rule to redirect packets on TX.
1415 * Keep also the last implicit local rule: ISOLATE.
1417 if (flow->msg.t.tcm_ifindex == pmd->if_index)
1419 if (tap_flow_destroy_pmd(pmd, flow, NULL) < 0)
1422 /* Switch the TC rule according to pmd->flow_isolate */
1423 if (tap_flow_implicit_create(pmd, TAP_ISOLATE) == -1)
1426 /* Switch the TC rule according to pmd->flow_isolate */
1427 if (tap_flow_implicit_create(pmd, TAP_ISOLATE) == -1)
1429 if (!pmd->remote_if_index)
1431 if (tap_flow_implicit_create(pmd, TAP_REMOTE_TX) < 0)
1433 if (tap_flow_implicit_create(pmd, TAP_REMOTE_LOCAL_MAC) < 0)
1435 if (tap_flow_implicit_create(pmd, TAP_REMOTE_BROADCAST) < 0)
1437 if (tap_flow_implicit_create(pmd, TAP_REMOTE_BROADCASTV6) < 0)
1439 if (dev->data->promiscuous &&
1440 tap_flow_implicit_create(pmd, TAP_REMOTE_PROMISC) < 0)
1442 if (dev->data->all_multicast &&
1443 tap_flow_implicit_create(pmd, TAP_REMOTE_ALLMULTI) < 0)
1448 pmd->flow_isolate = 0;
1449 return -rte_flow_error_set(
1450 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1451 "TC rule creation failed");
1455 * Destroy all flows.
1457 * @see rte_flow_flush()
1461 tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1463 struct pmd_internals *pmd = dev->data->dev_private;
1464 struct rte_flow *flow;
1466 while (!LIST_EMPTY(&pmd->flows)) {
1467 flow = LIST_FIRST(&pmd->flows);
1468 if (tap_flow_destroy(dev, flow, error) < 0)
1475 * Add an implicit flow rule on the remote device to make sure traffic gets to
1476 * the tap netdevice from there.
1479 * Pointer to private structure.
1481 * The idx in the implicit_rte_flows array specifying which rule to apply.
1483 * @return -1 if the rule couldn't be applied, 0 otherwise.
1485 int tap_flow_implicit_create(struct pmd_internals *pmd,
1486 enum implicit_rule_index idx)
1488 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
1489 struct rte_flow_action *actions = implicit_rte_flows[idx].actions;
1490 struct rte_flow_action isolate_actions[2] = {
1492 .type = RTE_FLOW_ACTION_TYPE_END,
1495 struct rte_flow_item *items = implicit_rte_flows[idx].items;
1496 struct rte_flow_attr *attr = &implicit_rte_flows[idx].attr;
1497 struct rte_flow_item_eth eth_local = { .type = 0 };
1498 uint16_t if_index = pmd->remote_if_index;
1499 struct rte_flow *remote_flow = NULL;
1500 struct nlmsg *msg = NULL;
1502 struct rte_flow_item items_local[2] = {
1504 .type = items[0].type,
1506 .mask = items[0].mask,
1509 .type = items[1].type,
1513 remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
1515 RTE_LOG(ERR, PMD, "Cannot allocate memory for rte_flow\n");
1518 msg = &remote_flow->msg;
1519 if (idx == TAP_REMOTE_TX) {
1520 if_index = pmd->if_index;
1521 } else if (idx == TAP_ISOLATE) {
1522 if_index = pmd->if_index;
1523 /* Don't be exclusive for this rule, it can be changed later. */
1524 flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE;
1525 isolate_actions[0].type = pmd->flow_isolate ?
1526 RTE_FLOW_ACTION_TYPE_DROP :
1527 RTE_FLOW_ACTION_TYPE_PASSTHRU;
1528 actions = isolate_actions;
1529 } else if (idx == TAP_REMOTE_LOCAL_MAC) {
1531 * eth addr couldn't be set in implicit_rte_flows[] as it is not
1532 * known at compile time.
1534 memcpy(ð_local.dst, &pmd->eth_addr, sizeof(pmd->eth_addr));
1535 items = items_local;
1537 tc_init_msg(msg, if_index, RTM_NEWTFILTER, flags);
1538 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
1540 * The ISOLATE rule is always present and must have a static handle, as
1541 * the action is changed whether the feature is enabled (DROP) or
1542 * disabled (PASSTHRU).
1544 if (idx == TAP_ISOLATE)
1545 remote_flow->msg.t.tcm_handle = ISOLATE_HANDLE;
1547 tap_flow_set_handle(remote_flow);
1548 if (priv_flow_process(pmd, attr, items, actions, NULL,
1549 remote_flow, implicit_rte_flows[idx].mirred)) {
1550 RTE_LOG(ERR, PMD, "rte flow rule validation failed\n");
1553 err = nl_send(pmd->nlsk_fd, &msg->nh);
1555 RTE_LOG(ERR, PMD, "Failure sending nl request\n");
1558 err = nl_recv_ack(pmd->nlsk_fd);
1561 "Kernel refused TC filter rule creation (%d): %s\n",
1562 errno, strerror(errno));
1565 LIST_INSERT_HEAD(&pmd->implicit_flows, remote_flow, next);
1569 rte_free(remote_flow);
1574 * Remove specific implicit flow rule on the remote device.
1576 * @param[in, out] pmd
1577 * Pointer to private structure.
1579 * The idx in the implicit_rte_flows array specifying which rule to remove.
1581 * @return -1 if one of the implicit rules couldn't be created, 0 otherwise.
1583 int tap_flow_implicit_destroy(struct pmd_internals *pmd,
1584 enum implicit_rule_index idx)
1586 struct rte_flow *remote_flow;
1588 int idx_prio = implicit_rte_flows[idx].attr.priority + PRIORITY_OFFSET;
1590 for (remote_flow = LIST_FIRST(&pmd->implicit_flows);
1592 remote_flow = LIST_NEXT(remote_flow, next)) {
1593 cur_prio = (remote_flow->msg.t.tcm_info >> 16) & PRIORITY_MASK;
1594 if (cur_prio != idx_prio)
1596 return tap_flow_destroy_pmd(pmd, remote_flow, NULL);
1602 * Destroy all implicit flows.
1604 * @see rte_flow_flush()
1607 tap_flow_implicit_flush(struct pmd_internals *pmd, struct rte_flow_error *error)
1609 struct rte_flow *remote_flow;
1611 while (!LIST_EMPTY(&pmd->implicit_flows)) {
1612 remote_flow = LIST_FIRST(&pmd->implicit_flows);
1613 if (tap_flow_destroy_pmd(pmd, remote_flow, error) < 0)
1620 * Manage filter operations.
1623 * Pointer to Ethernet device structure.
1624 * @param filter_type
1627 * Operation to perform.
1629 * Pointer to operation-specific structure.
1632 * 0 on success, negative errno value on failure.
1635 tap_dev_filter_ctrl(struct rte_eth_dev *dev,
1636 enum rte_filter_type filter_type,
1637 enum rte_filter_op filter_op,
1640 switch (filter_type) {
1641 case RTE_ETH_FILTER_GENERIC:
1642 if (filter_op != RTE_ETH_FILTER_GET)
1644 *(const void **)arg = &tap_flow_ops;
1647 RTE_LOG(ERR, PMD, "%p: filter type (%d) not supported\n",
1648 (void *)dev, filter_type);