From: Adrien Mazarguil <adrien.mazarguil@6wind.com>
To: Shahaf Shuler <shahafs@mellanox.com>
Cc: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>,
Yongseok Koh <yskoh@mellanox.com>,
dev@dpdk.org
Subject: [dpdk-dev] [PATCH 5/6] net/mlx5: add VLAN item and actions to switch flow rules
Date: Wed, 27 Jun 2018 20:08:18 +0200 [thread overview]
Message-ID: <20180627173355.4718-6-adrien.mazarguil@6wind.com> (raw)
In-Reply-To: <20180627173355.4718-1-adrien.mazarguil@6wind.com>
This enables flow rules to explicitly match VLAN traffic (VLAN pattern
item) and perform various operations on VLAN headers at the switch level
(OF_POP_VLAN, OF_PUSH_VLAN, OF_SET_VLAN_VID and OF_SET_VLAN_PCP actions).
Testpmd examples:
- Directing all VLAN traffic received on port ID 1 to port ID 0:
flow create 1 ingress transfer pattern eth / vlan / end actions
port_id id 0 / end
- Adding a VLAN header to IPv6 traffic received on port ID 1 and directing
it to port ID 0:
flow create 1 ingress transfer pattern eth / ipv6 / end actions
of_push_vlan ethertype 0x8100 / of_set_vlan_vid / port_id id 0 / end
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
drivers/net/mlx5/mlx5_nl_flow.c | 177 ++++++++++++++++++++++++++++++++++-
1 file changed, 173 insertions(+), 4 deletions(-)
diff --git a/drivers/net/mlx5/mlx5_nl_flow.c b/drivers/net/mlx5/mlx5_nl_flow.c
index ad1e001c6..a45d94fae 100644
--- a/drivers/net/mlx5/mlx5_nl_flow.c
+++ b/drivers/net/mlx5/mlx5_nl_flow.c
@@ -13,6 +13,7 @@
#include <linux/rtnetlink.h>
#include <linux/tc_act/tc_gact.h>
#include <linux/tc_act/tc_mirred.h>
+#include <linux/tc_act/tc_vlan.h>
#include <netinet/in.h>
#include <stdalign.h>
#include <stdbool.h>
@@ -36,6 +37,7 @@ enum mlx5_nl_flow_trans {
PATTERN,
ITEM_VOID,
ITEM_ETH,
+ ITEM_VLAN,
ITEM_IPV4,
ITEM_IPV6,
ITEM_TCP,
@@ -44,6 +46,10 @@ enum mlx5_nl_flow_trans {
ACTION_VOID,
ACTION_PORT_ID,
ACTION_DROP,
+ ACTION_OF_POP_VLAN,
+ ACTION_OF_PUSH_VLAN,
+ ACTION_OF_SET_VLAN_VID,
+ ACTION_OF_SET_VLAN_PCP,
END,
};
@@ -52,7 +58,8 @@ enum mlx5_nl_flow_trans {
#define PATTERN_COMMON \
ITEM_VOID, ACTIONS
#define ACTIONS_COMMON \
- ACTION_VOID
+ ACTION_VOID, ACTION_OF_POP_VLAN, ACTION_OF_PUSH_VLAN, \
+ ACTION_OF_SET_VLAN_VID, ACTION_OF_SET_VLAN_PCP
#define ACTIONS_FATE \
ACTION_PORT_ID, ACTION_DROP
@@ -63,7 +70,8 @@ static const enum mlx5_nl_flow_trans *const mlx5_nl_flow_trans[] = {
[ATTR] = TRANS(PATTERN),
[PATTERN] = TRANS(ITEM_ETH, PATTERN_COMMON),
[ITEM_VOID] = TRANS(BACK),
- [ITEM_ETH] = TRANS(ITEM_IPV4, ITEM_IPV6, PATTERN_COMMON),
+ [ITEM_ETH] = TRANS(ITEM_IPV4, ITEM_IPV6, ITEM_VLAN, PATTERN_COMMON),
+ [ITEM_VLAN] = TRANS(ITEM_IPV4, ITEM_IPV6, PATTERN_COMMON),
[ITEM_IPV4] = TRANS(ITEM_TCP, ITEM_UDP, PATTERN_COMMON),
[ITEM_IPV6] = TRANS(ITEM_TCP, ITEM_UDP, PATTERN_COMMON),
[ITEM_TCP] = TRANS(PATTERN_COMMON),
@@ -72,12 +80,17 @@ static const enum mlx5_nl_flow_trans *const mlx5_nl_flow_trans[] = {
[ACTION_VOID] = TRANS(BACK),
[ACTION_PORT_ID] = TRANS(ACTION_VOID, END),
[ACTION_DROP] = TRANS(ACTION_VOID, END),
+ [ACTION_OF_POP_VLAN] = TRANS(ACTIONS_FATE, ACTIONS_COMMON),
+ [ACTION_OF_PUSH_VLAN] = TRANS(ACTIONS_FATE, ACTIONS_COMMON),
+ [ACTION_OF_SET_VLAN_VID] = TRANS(ACTIONS_FATE, ACTIONS_COMMON),
+ [ACTION_OF_SET_VLAN_PCP] = TRANS(ACTIONS_FATE, ACTIONS_COMMON),
[END] = NULL,
};
/** Empty masks for known item types. */
static const union {
struct rte_flow_item_eth eth;
+ struct rte_flow_item_vlan vlan;
struct rte_flow_item_ipv4 ipv4;
struct rte_flow_item_ipv6 ipv6;
struct rte_flow_item_tcp tcp;
@@ -87,6 +100,7 @@ static const union {
/** Supported masks for known item types. */
static const struct {
struct rte_flow_item_eth eth;
+ struct rte_flow_item_vlan vlan;
struct rte_flow_item_ipv4 ipv4;
struct rte_flow_item_ipv6 ipv6;
struct rte_flow_item_tcp tcp;
@@ -97,6 +111,11 @@ static const struct {
.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
},
+ .vlan = {
+ /* PCP and VID only, no DEI. */
+ .tci = RTE_BE16(0xefff),
+ .inner_type = RTE_BE16(0xffff),
+ },
.ipv4.hdr = {
.next_proto_id = 0xff,
.src_addr = RTE_BE32(0xffffffff),
@@ -242,9 +261,13 @@ mlx5_nl_flow_transpose(void *buf,
unsigned int n;
uint32_t act_index_cur;
bool eth_type_set;
+ bool vlan_present;
+ bool vlan_eth_type_set;
bool ip_proto_set;
struct nlattr *na_flower;
struct nlattr *na_flower_act;
+ struct nlattr *na_vlan_id;
+ struct nlattr *na_vlan_priority;
const enum mlx5_nl_flow_trans *trans;
const enum mlx5_nl_flow_trans *back;
@@ -256,15 +279,20 @@ mlx5_nl_flow_transpose(void *buf,
n = 0;
act_index_cur = 0;
eth_type_set = false;
+ vlan_present = false;
+ vlan_eth_type_set = false;
ip_proto_set = false;
na_flower = NULL;
na_flower_act = NULL;
+ na_vlan_id = NULL;
+ na_vlan_priority = NULL;
trans = TRANS(ATTR);
back = trans;
trans:
switch (trans[n++]) {
union {
const struct rte_flow_item_eth *eth;
+ const struct rte_flow_item_vlan *vlan;
const struct rte_flow_item_ipv4 *ipv4;
const struct rte_flow_item_ipv6 *ipv6;
const struct rte_flow_item_tcp *tcp;
@@ -272,6 +300,11 @@ mlx5_nl_flow_transpose(void *buf,
} spec, mask;
union {
const struct rte_flow_action_port_id *port_id;
+ const struct rte_flow_action_of_push_vlan *of_push_vlan;
+ const struct rte_flow_action_of_set_vlan_vid *
+ of_set_vlan_vid;
+ const struct rte_flow_action_of_set_vlan_pcp *
+ of_set_vlan_pcp;
} conf;
struct nlmsghdr *nlh;
struct tcmsg *tcm;
@@ -408,6 +441,58 @@ mlx5_nl_flow_transpose(void *buf,
goto error_nobufs;
++item;
break;
+ case ITEM_VLAN:
+ if (item->type != RTE_FLOW_ITEM_TYPE_VLAN)
+ goto trans;
+ mask.vlan = mlx5_nl_flow_item_mask
+ (item, &rte_flow_item_vlan_mask,
+ &mlx5_nl_flow_mask_supported.vlan,
+ &mlx5_nl_flow_mask_empty.vlan,
+ sizeof(mlx5_nl_flow_mask_supported.vlan), error);
+ if (!mask.vlan)
+ return -rte_errno;
+ if (!eth_type_set &&
+ !mnl_attr_put_u16_check(buf, size,
+ TCA_FLOWER_KEY_ETH_TYPE,
+ RTE_BE16(ETH_P_8021Q)))
+ goto error_nobufs;
+ eth_type_set = 1;
+ vlan_present = 1;
+ if (mask.vlan == &mlx5_nl_flow_mask_empty.vlan) {
+ ++item;
+ break;
+ }
+ spec.vlan = item->spec;
+ if ((mask.vlan->tci & RTE_BE16(0xe000) &&
+ (mask.vlan->tci & RTE_BE16(0xe000)) != RTE_BE16(0xe000)) ||
+ (mask.vlan->tci & RTE_BE16(0x0fff) &&
+ (mask.vlan->tci & RTE_BE16(0x0fff)) != RTE_BE16(0x0fff)) ||
+ (mask.vlan->inner_type &&
+ mask.vlan->inner_type != RTE_BE16(0xffff)))
+ return rte_flow_error_set
+ (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK,
+ mask.vlan,
+ "no support for partial masks on"
+ " \"tci\" (PCP and VID parts) and"
+ " \"inner_type\" fields");
+ if (mask.vlan->inner_type) {
+ if (!mnl_attr_put_u16_check
+ (buf, size, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
+ spec.vlan->inner_type))
+ goto error_nobufs;
+ vlan_eth_type_set = 1;
+ }
+ if ((mask.vlan->tci & RTE_BE16(0xe000) &&
+ !mnl_attr_put_u8_check
+ (buf, size, TCA_FLOWER_KEY_VLAN_PRIO,
+ (rte_be_to_cpu_16(spec.vlan->tci) >> 13) & 0x7)) ||
+ (mask.vlan->tci & RTE_BE16(0x0fff) &&
+ !mnl_attr_put_u16_check
+ (buf, size, TCA_FLOWER_KEY_VLAN_ID,
+ spec.vlan->tci & RTE_BE16(0x0fff))))
+ goto error_nobufs;
+ ++item;
+ break;
case ITEM_IPV4:
if (item->type != RTE_FLOW_ITEM_TYPE_IPV4)
goto trans;
@@ -418,12 +503,15 @@ mlx5_nl_flow_transpose(void *buf,
sizeof(mlx5_nl_flow_mask_supported.ipv4), error);
if (!mask.ipv4)
return -rte_errno;
- if (!eth_type_set &&
+ if ((!eth_type_set || !vlan_eth_type_set) &&
!mnl_attr_put_u16_check(buf, size,
+ vlan_present ?
+ TCA_FLOWER_KEY_VLAN_ETH_TYPE :
TCA_FLOWER_KEY_ETH_TYPE,
RTE_BE16(ETH_P_IP)))
goto error_nobufs;
eth_type_set = 1;
+ vlan_eth_type_set = 1;
if (mask.ipv4 == &mlx5_nl_flow_mask_empty.ipv4) {
++item;
break;
@@ -470,12 +558,15 @@ mlx5_nl_flow_transpose(void *buf,
sizeof(mlx5_nl_flow_mask_supported.ipv6), error);
if (!mask.ipv6)
return -rte_errno;
- if (!eth_type_set &&
+ if ((!eth_type_set || !vlan_eth_type_set) &&
!mnl_attr_put_u16_check(buf, size,
+ vlan_present ?
+ TCA_FLOWER_KEY_VLAN_ETH_TYPE :
TCA_FLOWER_KEY_ETH_TYPE,
RTE_BE16(ETH_P_IPV6)))
goto error_nobufs;
eth_type_set = 1;
+ vlan_eth_type_set = 1;
if (mask.ipv6 == &mlx5_nl_flow_mask_empty.ipv6) {
++item;
break;
@@ -681,6 +772,84 @@ mlx5_nl_flow_transpose(void *buf,
mnl_attr_nest_end(buf, act_index);
++action;
break;
+ case ACTION_OF_POP_VLAN:
+ if (action->type != RTE_FLOW_ACTION_TYPE_OF_POP_VLAN)
+ goto trans;
+ conf.of_push_vlan = NULL;
+ i = TCA_VLAN_ACT_POP;
+ goto action_of_vlan;
+ case ACTION_OF_PUSH_VLAN:
+ if (action->type != RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN)
+ goto trans;
+ conf.of_push_vlan = action->conf;
+ i = TCA_VLAN_ACT_PUSH;
+ goto action_of_vlan;
+ case ACTION_OF_SET_VLAN_VID:
+ if (action->type != RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)
+ goto trans;
+ conf.of_set_vlan_vid = action->conf;
+ if (na_vlan_id)
+ goto override_na_vlan_id;
+ i = TCA_VLAN_ACT_MODIFY;
+ goto action_of_vlan;
+ case ACTION_OF_SET_VLAN_PCP:
+ if (action->type != RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)
+ goto trans;
+ conf.of_set_vlan_pcp = action->conf;
+ if (na_vlan_priority)
+ goto override_na_vlan_priority;
+ i = TCA_VLAN_ACT_MODIFY;
+ goto action_of_vlan;
+action_of_vlan:
+ act_index =
+ mnl_attr_nest_start_check(buf, size, act_index_cur++);
+ if (!act_index ||
+ !mnl_attr_put_strz_check(buf, size, TCA_ACT_KIND, "vlan"))
+ goto error_nobufs;
+ act = mnl_attr_nest_start_check(buf, size, TCA_ACT_OPTIONS);
+ if (!act)
+ goto error_nobufs;
+ if (!mnl_attr_put_check(buf, size, TCA_VLAN_PARMS,
+ sizeof(struct tc_vlan),
+ &(struct tc_vlan){
+ .action = TC_ACT_PIPE,
+ .v_action = i,
+ }))
+ goto error_nobufs;
+ if (i == TCA_VLAN_ACT_POP) {
+ mnl_attr_nest_end(buf, act);
+ ++action;
+ break;
+ }
+ if (i == TCA_VLAN_ACT_PUSH &&
+ !mnl_attr_put_u16_check(buf, size,
+ TCA_VLAN_PUSH_VLAN_PROTOCOL,
+ conf.of_push_vlan->ethertype))
+ goto error_nobufs;
+ na_vlan_id = mnl_nlmsg_get_payload_tail(buf);
+ if (!mnl_attr_put_u16_check(buf, size, TCA_VLAN_PAD, 0))
+ goto error_nobufs;
+ na_vlan_priority = mnl_nlmsg_get_payload_tail(buf);
+ if (!mnl_attr_put_u8_check(buf, size, TCA_VLAN_PAD, 0))
+ goto error_nobufs;
+ mnl_attr_nest_end(buf, act);
+ mnl_attr_nest_end(buf, act_index);
+ if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) {
+override_na_vlan_id:
+ na_vlan_id->nla_type = TCA_VLAN_PUSH_VLAN_ID;
+ *(uint16_t *)mnl_attr_get_payload(na_vlan_id) =
+ rte_be_to_cpu_16
+ (conf.of_set_vlan_vid->vlan_vid);
+ } else if (action->type ==
+ RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) {
+override_na_vlan_priority:
+ na_vlan_priority->nla_type =
+ TCA_VLAN_PUSH_VLAN_PRIORITY;
+ *(uint8_t *)mnl_attr_get_payload(na_vlan_priority) =
+ conf.of_set_vlan_pcp->vlan_pcp;
+ }
+ ++action;
+ break;
case END:
if (item->type != RTE_FLOW_ITEM_TYPE_END ||
action->type != RTE_FLOW_ACTION_TYPE_END)
--
2.11.0
next prev parent reply other threads:[~2018-06-27 18:08 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-27 18:08 [dpdk-dev] [PATCH 0/6] net/mlx5: add support for " Adrien Mazarguil
2018-06-27 18:08 ` [dpdk-dev] [PATCH 1/6] net/mlx5: lay groundwork for switch offloads Adrien Mazarguil
2018-07-12 0:17 ` Yongseok Koh
2018-07-12 10:46 ` Adrien Mazarguil
2018-07-12 17:33 ` Yongseok Koh
2018-06-27 18:08 ` [dpdk-dev] [PATCH 2/6] net/mlx5: add framework for switch flow rules Adrien Mazarguil
2018-07-12 0:59 ` Yongseok Koh
2018-07-12 10:46 ` Adrien Mazarguil
2018-07-12 18:25 ` Yongseok Koh
2018-06-27 18:08 ` [dpdk-dev] [PATCH 3/6] net/mlx5: add fate actions to " Adrien Mazarguil
2018-07-12 1:00 ` Yongseok Koh
2018-06-27 18:08 ` [dpdk-dev] [PATCH 4/6] net/mlx5: add L2-L4 pattern items " Adrien Mazarguil
2018-07-12 1:02 ` Yongseok Koh
2018-06-27 18:08 ` Adrien Mazarguil [this message]
2018-07-12 1:10 ` [dpdk-dev] [PATCH 5/6] net/mlx5: add VLAN item and actions " Yongseok Koh
2018-07-12 10:47 ` Adrien Mazarguil
2018-07-12 18:49 ` Yongseok Koh
2018-06-27 18:08 ` [dpdk-dev] [PATCH 6/6] net/mlx5: add port ID pattern item " Adrien Mazarguil
2018-07-12 1:13 ` Yongseok Koh
2018-06-28 9:05 ` [dpdk-dev] [PATCH 0/6] net/mlx5: add support for " Nélio Laranjeiro
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 " Adrien Mazarguil
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 1/6] net/mlx5: lay groundwork for switch offloads Adrien Mazarguil
2018-07-14 1:29 ` Yongseok Koh
2018-07-23 21:40 ` Ferruh Yigit
2018-07-24 0:50 ` Stephen Hemminger
2018-07-24 4:35 ` Shahaf Shuler
2018-07-24 19:33 ` Stephen Hemminger
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 2/6] net/mlx5: add framework for switch flow rules Adrien Mazarguil
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 3/6] net/mlx5: add fate actions to " Adrien Mazarguil
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 4/6] net/mlx5: add L2-L4 pattern items " Adrien Mazarguil
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 5/6] net/mlx5: add VLAN item and actions " Adrien Mazarguil
2018-07-13 9:40 ` [dpdk-dev] [PATCH v2 6/6] net/mlx5: add port ID pattern item " Adrien Mazarguil
2018-07-22 11:21 ` [dpdk-dev] [PATCH v2 0/6] net/mlx5: add support for " Shahaf Shuler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180627173355.4718-6-adrien.mazarguil@6wind.com \
--to=adrien.mazarguil@6wind.com \
--cc=dev@dpdk.org \
--cc=nelio.laranjeiro@6wind.com \
--cc=shahafs@mellanox.com \
--cc=yskoh@mellanox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).