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.
34 #include <sys/queue.h>
36 #include <rte_byteorder.h>
37 #include <rte_jhash.h>
38 #include <rte_malloc.h>
39 #include <rte_eth_tap.h>
41 #include <tap_autoconf.h>
42 #include <tap_tcmsgs.h>
44 #ifndef HAVE_TC_FLOWER
46 * For kernels < 4.2, this enum is not defined. Runtime checks will be made to
47 * avoid sending TC messages the kernel cannot understand.
54 TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */
55 TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */
56 TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */
57 TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */
58 TCA_FLOWER_KEY_ETH_TYPE, /* be16 */
59 TCA_FLOWER_KEY_IP_PROTO, /* u8 */
60 TCA_FLOWER_KEY_IPV4_SRC, /* be32 */
61 TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */
62 TCA_FLOWER_KEY_IPV4_DST, /* be32 */
63 TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */
64 TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */
65 TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */
66 TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */
67 TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */
68 TCA_FLOWER_KEY_TCP_SRC, /* be16 */
69 TCA_FLOWER_KEY_TCP_DST, /* be16 */
70 TCA_FLOWER_KEY_UDP_SRC, /* be16 */
71 TCA_FLOWER_KEY_UDP_DST, /* be16 */
74 #ifndef HAVE_TC_VLAN_ID
76 /* TCA_FLOWER_FLAGS, */
77 TCA_FLOWER_KEY_VLAN_ID = TCA_FLOWER_KEY_UDP_DST + 2, /* be16 */
78 TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */
79 TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */
84 LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */
92 struct rte_flow *flow;
95 static int tap_flow_create_eth(const struct rte_flow_item *item, void *data);
96 static int tap_flow_create_vlan(const struct rte_flow_item *item, void *data);
97 static int tap_flow_create_ipv4(const struct rte_flow_item *item, void *data);
98 static int tap_flow_create_ipv6(const struct rte_flow_item *item, void *data);
99 static int tap_flow_create_udp(const struct rte_flow_item *item, void *data);
100 static int tap_flow_create_tcp(const struct rte_flow_item *item, void *data);
102 tap_flow_validate(struct rte_eth_dev *dev,
103 const struct rte_flow_attr *attr,
104 const struct rte_flow_item items[],
105 const struct rte_flow_action actions[],
106 struct rte_flow_error *error);
108 static struct rte_flow *
109 tap_flow_create(struct rte_eth_dev *dev,
110 const struct rte_flow_attr *attr,
111 const struct rte_flow_item items[],
112 const struct rte_flow_action actions[],
113 struct rte_flow_error *error);
116 tap_flow_destroy(struct rte_eth_dev *dev,
117 struct rte_flow *flow,
118 struct rte_flow_error *error);
120 static const struct rte_flow_ops tap_flow_ops = {
121 .validate = tap_flow_validate,
122 .create = tap_flow_create,
123 .destroy = tap_flow_destroy,
124 .flush = tap_flow_flush,
127 /* Static initializer for items. */
129 (const enum rte_flow_item_type []){ \
130 __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
133 /* Structure to generate a simple graph of layers supported by the NIC. */
134 struct tap_flow_items {
135 /* Bit-mask corresponding to what is supported for this item. */
137 const unsigned int mask_sz; /* Bit-mask size in bytes. */
139 * Bit-mask corresponding to the default mask, if none is provided
140 * along with the item.
142 const void *default_mask;
144 * Conversion function from rte_flow to netlink attributes.
147 * rte_flow item to convert.
149 * Internal structure to store the conversion.
152 * 0 on success, negative value otherwise.
154 int (*convert)(const struct rte_flow_item *item, void *data);
155 /** List of possible following items. */
156 const enum rte_flow_item_type *const items;
159 /* Graph of supported items and associated actions. */
160 static const struct tap_flow_items tap_flow_items[] = {
161 [RTE_FLOW_ITEM_TYPE_END] = {
162 .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH),
164 [RTE_FLOW_ITEM_TYPE_ETH] = {
166 RTE_FLOW_ITEM_TYPE_VLAN,
167 RTE_FLOW_ITEM_TYPE_IPV4,
168 RTE_FLOW_ITEM_TYPE_IPV6),
169 .mask = &(const struct rte_flow_item_eth){
170 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
171 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
174 .mask_sz = sizeof(struct rte_flow_item_eth),
175 .default_mask = &rte_flow_item_eth_mask,
176 .convert = tap_flow_create_eth,
178 [RTE_FLOW_ITEM_TYPE_VLAN] = {
179 .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4,
180 RTE_FLOW_ITEM_TYPE_IPV6),
181 .mask = &(const struct rte_flow_item_vlan){
183 /* DEI matching is not supported */
184 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
190 .mask_sz = sizeof(struct rte_flow_item_vlan),
191 .default_mask = &rte_flow_item_vlan_mask,
192 .convert = tap_flow_create_vlan,
194 [RTE_FLOW_ITEM_TYPE_IPV4] = {
195 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
196 RTE_FLOW_ITEM_TYPE_TCP),
197 .mask = &(const struct rte_flow_item_ipv4){
204 .mask_sz = sizeof(struct rte_flow_item_ipv4),
205 .default_mask = &rte_flow_item_ipv4_mask,
206 .convert = tap_flow_create_ipv4,
208 [RTE_FLOW_ITEM_TYPE_IPV6] = {
209 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
210 RTE_FLOW_ITEM_TYPE_TCP),
211 .mask = &(const struct rte_flow_item_ipv6){
214 "\xff\xff\xff\xff\xff\xff\xff\xff"
215 "\xff\xff\xff\xff\xff\xff\xff\xff",
218 "\xff\xff\xff\xff\xff\xff\xff\xff"
219 "\xff\xff\xff\xff\xff\xff\xff\xff",
224 .mask_sz = sizeof(struct rte_flow_item_ipv6),
225 .default_mask = &rte_flow_item_ipv6_mask,
226 .convert = tap_flow_create_ipv6,
228 [RTE_FLOW_ITEM_TYPE_UDP] = {
229 .mask = &(const struct rte_flow_item_udp){
235 .mask_sz = sizeof(struct rte_flow_item_udp),
236 .default_mask = &rte_flow_item_udp_mask,
237 .convert = tap_flow_create_udp,
239 [RTE_FLOW_ITEM_TYPE_TCP] = {
240 .mask = &(const struct rte_flow_item_tcp){
246 .mask_sz = sizeof(struct rte_flow_item_tcp),
247 .default_mask = &rte_flow_item_tcp_mask,
248 .convert = tap_flow_create_tcp,
253 * Make as much checks as possible on an Ethernet item, and if a flow is
254 * provided, fill it appropriately with Ethernet info.
257 * Item specification.
258 * @param[in, out] data
259 * Additional data structure to tell next layers we've been here.
262 * 0 if checks are alright, -1 otherwise.
265 tap_flow_create_eth(const struct rte_flow_item *item, void *data)
267 struct convert_data *info = (struct convert_data *)data;
268 const struct rte_flow_item_eth *spec = item->spec;
269 const struct rte_flow_item_eth *mask = item->mask;
270 struct rte_flow *flow = info->flow;
273 /* use default mask if none provided */
275 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_ETH].default_mask;
276 /* TC does not support eth_type masking. Only accept if exact match. */
277 if (mask->type && mask->type != 0xffff)
281 /* store eth_type for consistency if ipv4/6 pattern item comes next */
282 if (spec->type & mask->type)
283 info->eth_type = spec->type;
287 if (spec->type & mask->type)
288 msg->t.tcm_info = TC_H_MAKE(msg->t.tcm_info,
289 (spec->type & mask->type));
290 if (!is_zero_ether_addr(&spec->dst)) {
291 nlattr_add(&msg->nh, TCA_FLOWER_KEY_ETH_DST, ETHER_ADDR_LEN,
292 &spec->dst.addr_bytes);
294 TCA_FLOWER_KEY_ETH_DST_MASK, ETHER_ADDR_LEN,
295 &mask->dst.addr_bytes);
297 if (!is_zero_ether_addr(&mask->src)) {
298 nlattr_add(&msg->nh, TCA_FLOWER_KEY_ETH_SRC, ETHER_ADDR_LEN,
299 &spec->src.addr_bytes);
301 TCA_FLOWER_KEY_ETH_SRC_MASK, ETHER_ADDR_LEN,
302 &mask->src.addr_bytes);
308 * Make as much checks as possible on a VLAN item, and if a flow is provided,
309 * fill it appropriately with VLAN info.
312 * Item specification.
313 * @param[in, out] data
314 * Additional data structure to tell next layers we've been here.
317 * 0 if checks are alright, -1 otherwise.
320 tap_flow_create_vlan(const struct rte_flow_item *item, void *data)
322 struct convert_data *info = (struct convert_data *)data;
323 const struct rte_flow_item_vlan *spec = item->spec;
324 const struct rte_flow_item_vlan *mask = item->mask;
325 struct rte_flow *flow = info->flow;
328 /* use default mask if none provided */
330 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_VLAN].default_mask;
331 /* TC does not support tpid masking. Only accept if exact match. */
332 if (mask->tpid && mask->tpid != 0xffff)
334 /* Double-tagging not supported. */
335 if (spec && mask->tpid && spec->tpid != htons(ETH_P_8021Q))
341 msg->t.tcm_info = TC_H_MAKE(msg->t.tcm_info, htons(ETH_P_8021Q));
342 #define VLAN_PRIO(tci) ((tci) >> 13)
343 #define VLAN_ID(tci) ((tci) & 0xfff)
347 uint16_t tci = ntohs(spec->tci) & mask->tci;
348 uint16_t prio = VLAN_PRIO(tci);
349 uint8_t vid = VLAN_ID(tci);
352 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_VLAN_PRIO, prio);
354 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_VLAN_ID, vid);
360 * Make as much checks as possible on an IPv4 item, and if a flow is provided,
361 * fill it appropriately with IPv4 info.
364 * Item specification.
365 * @param[in, out] data
366 * Additional data structure to tell next layers we've been here.
369 * 0 if checks are alright, -1 otherwise.
372 tap_flow_create_ipv4(const struct rte_flow_item *item, void *data)
374 struct convert_data *info = (struct convert_data *)data;
375 const struct rte_flow_item_ipv4 *spec = item->spec;
376 const struct rte_flow_item_ipv4 *mask = item->mask;
377 struct rte_flow *flow = info->flow;
380 /* use default mask if none provided */
382 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_IPV4].default_mask;
383 /* check that previous eth type is compatible with ipv4 */
384 if (info->eth_type && info->eth_type != htons(ETH_P_IP))
386 /* store ip_proto for consistency if udp/tcp pattern item comes next */
388 info->ip_proto = spec->hdr.next_proto_id;
393 info->eth_type = htons(ETH_P_IP);
395 msg->t.tcm_info = TC_H_MAKE(msg->t.tcm_info, htons(ETH_P_IP));
398 if (spec->hdr.dst_addr) {
399 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_DST,
401 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_DST_MASK,
404 if (spec->hdr.src_addr) {
405 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_SRC,
407 nlattr_add32(&msg->nh, TCA_FLOWER_KEY_IPV4_SRC_MASK,
410 if (spec->hdr.next_proto_id)
411 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO,
412 spec->hdr.next_proto_id);
417 * Make as much checks as possible on an IPv6 item, and if a flow is provided,
418 * fill it appropriately with IPv6 info.
421 * Item specification.
422 * @param[in, out] data
423 * Additional data structure to tell next layers we've been here.
426 * 0 if checks are alright, -1 otherwise.
429 tap_flow_create_ipv6(const struct rte_flow_item *item, void *data)
431 struct convert_data *info = (struct convert_data *)data;
432 const struct rte_flow_item_ipv6 *spec = item->spec;
433 const struct rte_flow_item_ipv6 *mask = item->mask;
434 struct rte_flow *flow = info->flow;
435 uint8_t empty_addr[16] = { 0 };
438 /* use default mask if none provided */
440 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_IPV6].default_mask;
441 /* check that previous eth type is compatible with ipv6 */
442 if (info->eth_type && info->eth_type != htons(ETH_P_IPV6))
444 /* store ip_proto for consistency if udp/tcp pattern item comes next */
446 info->ip_proto = spec->hdr.proto;
451 info->eth_type = htons(ETH_P_IPV6);
453 msg->t.tcm_info = TC_H_MAKE(msg->t.tcm_info, htons(ETH_P_IPV6));
456 if (memcmp(spec->hdr.dst_addr, empty_addr, 16)) {
457 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST,
458 sizeof(spec->hdr.dst_addr), &spec->hdr.dst_addr);
459 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST_MASK,
460 sizeof(mask->hdr.dst_addr), &mask->hdr.dst_addr);
462 if (memcmp(spec->hdr.src_addr, empty_addr, 16)) {
463 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC,
464 sizeof(spec->hdr.src_addr), &spec->hdr.src_addr);
465 nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC_MASK,
466 sizeof(mask->hdr.src_addr), &mask->hdr.src_addr);
469 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, spec->hdr.proto);
474 * Make as much checks as possible on a UDP item, and if a flow is provided,
475 * fill it appropriately with UDP info.
478 * Item specification.
479 * @param[in, out] data
480 * Additional data structure to tell next layers we've been here.
483 * 0 if checks are alright, -1 otherwise.
486 tap_flow_create_udp(const struct rte_flow_item *item, void *data)
488 struct convert_data *info = (struct convert_data *)data;
489 const struct rte_flow_item_udp *spec = item->spec;
490 const struct rte_flow_item_udp *mask = item->mask;
491 struct rte_flow *flow = info->flow;
494 /* use default mask if none provided */
496 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_UDP].default_mask;
497 /* check that previous ip_proto is compatible with udp */
498 if (info->ip_proto && info->ip_proto != IPPROTO_UDP)
503 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, IPPROTO_UDP);
506 if (spec->hdr.dst_port &&
507 (spec->hdr.dst_port & mask->hdr.dst_port) == spec->hdr.dst_port)
508 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_UDP_DST,
510 if (spec->hdr.src_port &&
511 (spec->hdr.src_port & mask->hdr.src_port) == spec->hdr.src_port)
512 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_UDP_SRC,
518 * Make as much checks as possible on a TCP item, and if a flow is provided,
519 * fill it appropriately with TCP info.
522 * Item specification.
523 * @param[in, out] data
524 * Additional data structure to tell next layers we've been here.
527 * 0 if checks are alright, -1 otherwise.
530 tap_flow_create_tcp(const struct rte_flow_item *item, void *data)
532 struct convert_data *info = (struct convert_data *)data;
533 const struct rte_flow_item_tcp *spec = item->spec;
534 const struct rte_flow_item_tcp *mask = item->mask;
535 struct rte_flow *flow = info->flow;
538 /* use default mask if none provided */
540 mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_TCP].default_mask;
541 /* check that previous ip_proto is compatible with tcp */
542 if (info->ip_proto && info->ip_proto != IPPROTO_TCP)
547 nlattr_add8(&msg->nh, TCA_FLOWER_KEY_IP_PROTO, IPPROTO_TCP);
550 if (spec->hdr.dst_port &&
551 (spec->hdr.dst_port & mask->hdr.dst_port) == spec->hdr.dst_port)
552 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_TCP_DST,
554 if (spec->hdr.src_port &&
555 (spec->hdr.src_port & mask->hdr.src_port) == spec->hdr.src_port)
556 nlattr_add16(&msg->nh, TCA_FLOWER_KEY_TCP_SRC,
562 * Check support for a given item.
565 * Item specification.
567 * Bit-Mask size in bytes.
568 * @param[in] supported_mask
569 * Bit-mask covering supported fields to compare with spec, last and mask in
571 * @param[in] default_mask
572 * Bit-mask default mask if none is provided in \item.
578 tap_flow_item_validate(const struct rte_flow_item *item,
580 const uint8_t *supported_mask,
581 const uint8_t *default_mask)
585 /* An empty layer is allowed, as long as all fields are NULL */
586 if (!item->spec && (item->mask || item->last))
588 /* Is the item spec compatible with what the NIC supports? */
589 if (item->spec && !item->mask) {
591 const uint8_t *spec = item->spec;
593 for (i = 0; i < size; ++i)
594 if ((spec[i] | supported_mask[i]) != supported_mask[i])
596 /* Is the default mask compatible with what the NIC supports? */
597 for (i = 0; i < size; i++)
598 if ((default_mask[i] | supported_mask[i]) !=
602 /* Is the item last compatible with what the NIC supports? */
603 if (item->last && !item->mask) {
605 const uint8_t *spec = item->last;
607 for (i = 0; i < size; ++i)
608 if ((spec[i] | supported_mask[i]) != supported_mask[i])
611 /* Is the item mask compatible with what the NIC supports? */
614 const uint8_t *spec = item->mask;
616 for (i = 0; i < size; ++i)
617 if ((spec[i] | supported_mask[i]) != supported_mask[i])
621 * Once masked, Are item spec and item last equal?
622 * TC does not support range so anything else is invalid.
624 if (item->spec && item->last) {
627 const uint8_t *apply = default_mask;
632 for (i = 0; i < size; ++i) {
633 spec[i] = ((const uint8_t *)item->spec)[i] & apply[i];
634 last[i] = ((const uint8_t *)item->last)[i] & apply[i];
636 ret = memcmp(spec, last, size);
642 * Transform a DROP/PASSTHRU action item in the provided flow for TC.
644 * @param[in, out] flow
647 * Appropriate action to be set in the TCA_GACT_PARMS structure.
650 * 0 if checks are alright, -1 otherwise.
653 add_action_gact(struct rte_flow *flow, int action)
655 struct nlmsg *msg = &flow->msg;
656 size_t act_index = 1;
661 if (nlattr_nested_start(msg, TCA_FLOWER_ACT) < 0)
663 if (nlattr_nested_start(msg, act_index++) < 0)
665 nlattr_add(&msg->nh, TCA_ACT_KIND, sizeof("gact"), "gact");
666 if (nlattr_nested_start(msg, TCA_ACT_OPTIONS) < 0)
668 nlattr_add(&msg->nh, TCA_GACT_PARMS, sizeof(p), &p);
669 nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
670 nlattr_nested_finish(msg); /* nested act_index */
671 nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
676 * Transform a QUEUE action item in the provided flow for TC.
678 * @param[in, out] flow
684 * 0 if checks are alright, -1 otherwise.
687 add_action_skbedit(struct rte_flow *flow, uint16_t queue)
689 struct nlmsg *msg = &flow->msg;
690 size_t act_index = 1;
691 struct tc_skbedit p = {
692 .action = TC_ACT_PIPE
695 if (nlattr_nested_start(msg, TCA_FLOWER_ACT) < 0)
697 if (nlattr_nested_start(msg, act_index++) < 0)
699 nlattr_add(&msg->nh, TCA_ACT_KIND, sizeof("skbedit"), "skbedit");
700 if (nlattr_nested_start(msg, TCA_ACT_OPTIONS) < 0)
702 nlattr_add(&msg->nh, TCA_SKBEDIT_PARMS, sizeof(p), &p);
703 nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING, queue);
704 nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */
705 nlattr_nested_finish(msg); /* nested act_index */
706 nlattr_nested_finish(msg); /* nested TCA_FLOWER_ACT */
711 * Validate a flow supported by TC.
712 * If flow param is not NULL, then also fill the netlink message inside.
715 * Pointer to private structure.
717 * Flow rule attributes.
719 * Pattern specification (list terminated by the END pattern item).
721 * Associated actions (list terminated by the END action).
723 * Perform verbose error reporting if not NULL.
724 * @param[in, out] flow
725 * Flow structure to update.
728 * 0 on success, a negative errno value otherwise and rte_errno is set.
731 priv_flow_process(struct pmd_internals *pmd,
732 const struct rte_flow_attr *attr,
733 const struct rte_flow_item items[],
734 const struct rte_flow_action actions[],
735 struct rte_flow_error *error,
736 struct rte_flow *flow)
738 const struct tap_flow_items *cur_item = tap_flow_items;
739 struct convert_data data = {
744 int action = 0; /* Only one action authorized for now */
746 if (attr->group > MAX_GROUP) {
748 error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
749 NULL, "group value too big: cannot exceed 15");
752 if (attr->priority > MAX_PRIORITY) {
754 error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
755 NULL, "priority value too big");
758 uint16_t group = attr->group << GROUP_SHIFT;
759 uint16_t prio = group | (attr->priority + PRIORITY_OFFSET);
760 flow->msg.t.tcm_info = TC_H_MAKE(prio << 16,
761 flow->msg.t.tcm_info);
763 if (!attr->ingress) {
764 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR,
765 NULL, "direction should be ingress");
768 /* rte_flow ingress is actually egress as seen in the kernel */
769 if (attr->ingress && flow)
770 flow->msg.t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);
772 /* use flower filter type */
773 nlattr_add(&flow->msg.nh, TCA_KIND, sizeof("flower"), "flower");
774 if (nlattr_nested_start(&flow->msg, TCA_OPTIONS) < 0)
775 goto exit_item_not_supported;
777 for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) {
778 const struct tap_flow_items *token = NULL;
782 if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
786 cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END;
788 if (cur_item->items[i] == items->type) {
789 token = &tap_flow_items[items->type];
794 goto exit_item_not_supported;
796 err = tap_flow_item_validate(
797 items, cur_item->mask_sz,
798 (const uint8_t *)cur_item->mask,
799 (const uint8_t *)cur_item->default_mask);
801 goto exit_item_not_supported;
802 if (flow && cur_item->convert) {
803 if (!pmd->flower_vlan_support &&
804 cur_item->convert == tap_flow_create_vlan)
805 goto exit_item_not_supported;
806 err = cur_item->convert(items, &data);
808 goto exit_item_not_supported;
812 if (pmd->flower_vlan_support && data.vlan) {
813 nlattr_add16(&flow->msg.nh, TCA_FLOWER_KEY_ETH_TYPE,
815 nlattr_add16(&flow->msg.nh,
816 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
818 data.eth_type : htons(ETH_P_ALL));
819 } else if (data.eth_type) {
820 nlattr_add16(&flow->msg.nh, TCA_FLOWER_KEY_ETH_TYPE,
824 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
827 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
829 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
831 goto exit_action_not_supported;
834 err = add_action_gact(flow, TC_ACT_SHOT);
835 } else if (actions->type == RTE_FLOW_ACTION_TYPE_PASSTHRU) {
837 goto exit_action_not_supported;
840 err = add_action_gact(flow, TC_ACT_UNSPEC);
841 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
842 const struct rte_flow_action_queue *queue =
843 (const struct rte_flow_action_queue *)
846 goto exit_action_not_supported;
848 if (!queue || (queue->index >= pmd->nb_queues))
849 goto exit_action_not_supported;
851 err = add_action_skbedit(flow, queue->index);
853 goto exit_action_not_supported;
856 goto exit_action_not_supported;
859 nlattr_nested_finish(&flow->msg); /* nested TCA_OPTIONS */
861 exit_item_not_supported:
862 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
863 items, "item not supported");
865 exit_action_not_supported:
866 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
867 actions, "action not supported");
876 * @see rte_flow_validate()
880 tap_flow_validate(struct rte_eth_dev *dev,
881 const struct rte_flow_attr *attr,
882 const struct rte_flow_item items[],
883 const struct rte_flow_action actions[],
884 struct rte_flow_error *error)
886 struct pmd_internals *pmd = dev->data->dev_private;
888 return priv_flow_process(pmd, attr, items, actions, error, NULL);
892 * Set a unique handle in a flow.
894 * The kernel supports TC rules with equal priority, as long as they use the
895 * same matching fields (e.g.: dst mac and ipv4) with different values (and
896 * full mask to ensure no collision is possible).
897 * In those rules, the handle (uint32_t) is the part that would identify
898 * specifically each rule.
900 * On 32-bit architectures, the handle can simply be the flow's pointer address.
901 * On 64-bit architectures, we rely on jhash(flow) to find a (sufficiently)
904 * @param[in, out] flow
905 * The flow that needs its handle set.
908 tap_flow_set_handle(struct rte_flow *flow)
912 if (sizeof(flow) > 4)
913 handle = rte_jhash(&flow, sizeof(flow), 1);
915 handle = (uintptr_t)flow;
916 /* must be at least 1 to avoid letting the kernel choose one for us */
919 flow->msg.t.tcm_handle = handle;
925 * @see rte_flow_create()
928 static struct rte_flow *
929 tap_flow_create(struct rte_eth_dev *dev,
930 const struct rte_flow_attr *attr,
931 const struct rte_flow_item items[],
932 const struct rte_flow_action actions[],
933 struct rte_flow_error *error)
935 struct pmd_internals *pmd = dev->data->dev_private;
936 struct rte_flow *flow = NULL;
937 struct nlmsg *msg = NULL;
940 if (!pmd->if_index) {
941 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
943 "can't create rule, ifindex not found");
946 flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
948 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
949 NULL, "cannot allocate memory for rte_flow");
953 tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER,
954 NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);
955 msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));
956 tap_flow_set_handle(flow);
957 if (priv_flow_process(pmd, attr, items, actions, error, flow))
959 err = nl_send(pmd->nlsk_fd, &msg->nh);
961 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
962 NULL, "couldn't send request to kernel");
965 err = nl_recv_ack(pmd->nlsk_fd);
967 rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_HANDLE,
968 NULL, "overlapping rules");
971 LIST_INSERT_HEAD(&pmd->flows, flow, next);
982 * @see rte_flow_destroy()
986 tap_flow_destroy(struct rte_eth_dev *dev,
987 struct rte_flow *flow,
988 struct rte_flow_error *error)
990 struct pmd_internals *pmd = dev->data->dev_private;
993 LIST_REMOVE(flow, next);
994 flow->msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
995 flow->msg.nh.nlmsg_type = RTM_DELTFILTER;
997 ret = nl_send(pmd->nlsk_fd, &flow->msg.nh);
999 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1000 NULL, "couldn't send request to kernel");
1003 ret = nl_recv_ack(pmd->nlsk_fd);
1006 error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1007 "couldn't receive kernel ack to our request");
1014 * Destroy all flows.
1016 * @see rte_flow_flush()
1020 tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1022 struct pmd_internals *pmd = dev->data->dev_private;
1023 struct rte_flow *flow;
1025 while (!LIST_EMPTY(&pmd->flows)) {
1026 flow = LIST_FIRST(&pmd->flows);
1027 if (tap_flow_destroy(dev, flow, error) < 0)
1034 * Manage filter operations.
1037 * Pointer to Ethernet device structure.
1038 * @param filter_type
1041 * Operation to perform.
1043 * Pointer to operation-specific structure.
1046 * 0 on success, negative errno value on failure.
1049 tap_dev_filter_ctrl(struct rte_eth_dev *dev,
1050 enum rte_filter_type filter_type,
1051 enum rte_filter_op filter_op,
1054 struct pmd_internals *pmd = dev->data->dev_private;
1056 if (!pmd->flower_support)
1058 switch (filter_type) {
1059 case RTE_ETH_FILTER_GENERIC:
1060 if (filter_op != RTE_ETH_FILTER_GET)
1062 *(const void **)arg = &tap_flow_ops;
1065 RTE_LOG(ERR, PMD, "%p: filter type (%d) not supported",
1066 (void *)dev, filter_type);