From 1decc62b1cbecc53cb9962366f1f12cb660ac499 Mon Sep 17 00:00:00 2001 From: Shagun Agrawal Date: Mon, 27 Aug 2018 18:22:30 +0530 Subject: [PATCH] net/cxgbe: add flow operations to offload VLAN actions Add flow API operations to offload vlan push, pop, and rewrite actions. For vlan push or rewrite actions, allocate and program an entry from L2T table. Use the L2T index to program vlan actions for LETCAM (maskfull) and HASH (maskless) filters. Signed-off-by: Shagun Agrawal Signed-off-by: Rahul Lakkireddy --- doc/guides/rel_notes/release_18_11.rst | 6 +++ drivers/net/cxgbe/base/t4_msg.h | 6 +++ drivers/net/cxgbe/base/t4_tcb.h | 5 +++ drivers/net/cxgbe/cxgbe_filter.c | 62 ++++++++++++++++++++++++-- drivers/net/cxgbe/cxgbe_filter.h | 9 ++++ drivers/net/cxgbe/cxgbe_flow.c | 24 ++++++++++ 6 files changed, 109 insertions(+), 3 deletions(-) diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst index 24204e67b2..605e7d2412 100644 --- a/doc/guides/rel_notes/release_18_11.rst +++ b/doc/guides/rel_notes/release_18_11.rst @@ -54,6 +54,12 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Add support to offload more flow match and actions for CXGBE PMD** + + Flow API support has been enhanced for CXGBE Poll Mode Driver to offload: + + * Action items: push/pop/rewrite vlan header. + API Changes ----------- diff --git a/drivers/net/cxgbe/base/t4_msg.h b/drivers/net/cxgbe/base/t4_msg.h index 094a153f2c..2128da64fd 100644 --- a/drivers/net/cxgbe/base/t4_msg.h +++ b/drivers/net/cxgbe/base/t4_msg.h @@ -138,6 +138,12 @@ struct work_request_hdr { #define V_TCAM_BYPASS(x) ((__u64)(x) << S_TCAM_BYPASS) #define F_TCAM_BYPASS V_TCAM_BYPASS(1ULL) +#define S_L2T_IDX 36 +#define V_L2T_IDX(x) ((__u64)(x) << S_L2T_IDX) + +#define S_NAGLE 49 +#define V_NAGLE(x) ((__u64)(x) << S_NAGLE) + /* option 2 fields */ #define S_RSS_QUEUE 0 #define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE) diff --git a/drivers/net/cxgbe/base/t4_tcb.h b/drivers/net/cxgbe/base/t4_tcb.h index 25435f9f44..68cda77301 100644 --- a/drivers/net/cxgbe/base/t4_tcb.h +++ b/drivers/net/cxgbe/base/t4_tcb.h @@ -6,6 +6,9 @@ #ifndef _T4_TCB_DEFS_H #define _T4_TCB_DEFS_H +/* 95:32 */ +#define W_TCB_T_FLAGS 1 + /* 105:96 */ #define W_TCB_RSS_INFO 3 #define S_TCB_RSS_INFO 0 @@ -23,4 +26,6 @@ #define M_TCB_T_RTT_TS_RECENT_AGE 0xffffffffULL #define V_TCB_T_RTT_TS_RECENT_AGE(x) ((x) << S_TCB_T_RTT_TS_RECENT_AGE) +#define S_TF_CCTRL_RFR 62 + #endif /* _T4_TCB_DEFS_H */ diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c index 7f0d38001b..4d3f3ebeec 100644 --- a/drivers/net/cxgbe/cxgbe_filter.c +++ b/drivers/net/cxgbe/cxgbe_filter.c @@ -8,6 +8,7 @@ #include "t4_regs.h" #include "cxgbe_filter.h" #include "clip_tbl.h" +#include "l2t.h" /** * Initialize Hash Filters @@ -164,6 +165,16 @@ static void set_tcb_field(struct adapter *adapter, unsigned int ftid, t4_mgmt_tx(ctrlq, mbuf); } +/** + * Set one of the t_flags bits in the TCB. + */ +static void set_tcb_tflag(struct adapter *adap, unsigned int ftid, + unsigned int bit_pos, unsigned int val, int no_reply) +{ + set_tcb_field(adap, ftid, W_TCB_T_FLAGS, 1ULL << bit_pos, + (unsigned long long)val << bit_pos, no_reply); +} + /** * Build a CPL_SET_TCB_FIELD message as payload of a ULP_TX_PKT command. */ @@ -425,7 +436,10 @@ static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf, req->local_ip_lo = local_lo; req->peer_ip_hi = peer_hi; req->peer_ip_lo = peer_lo; - req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) | + req->opt0 = cpu_to_be64(V_NAGLE(f->fs.newvlan == VLAN_REMOVE || + f->fs.newvlan == VLAN_REWRITE) | + V_DELACK(f->fs.hitcnts) | + V_L2T_IDX(f->l2t ? f->l2t->idx : 0) | V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F) << 1) | V_TX_CHAN(f->fs.eport) | @@ -468,7 +482,10 @@ static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf, f->fs.val.lip[2] << 16 | f->fs.val.lip[3] << 24; req->peer_ip = f->fs.val.fip[0] | f->fs.val.fip[1] << 8 | f->fs.val.fip[2] << 16 | f->fs.val.fip[3] << 24; - req->opt0 = cpu_to_be64(V_DELACK(f->fs.hitcnts) | + req->opt0 = cpu_to_be64(V_NAGLE(f->fs.newvlan == VLAN_REMOVE || + f->fs.newvlan == VLAN_REWRITE) | + V_DELACK(f->fs.hitcnts) | + V_L2T_IDX(f->l2t ? f->l2t->idx : 0) | V_SMAC_SEL((cxgbe_port_viid(f->dev) & 0x7F) << 1) | V_TX_CHAN(f->fs.eport) | @@ -518,6 +535,22 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev, f->dev = dev; f->fs.iq = iq; + /* + * If the new filter requires loopback Destination MAC and/or VLAN + * rewriting then we need to allocate a Layer 2 Table (L2T) entry for + * the filter. + */ + if (f->fs.newvlan == VLAN_INSERT || + f->fs.newvlan == VLAN_REWRITE) { + /* allocate L2T entry for new filter */ + f->l2t = cxgbe_l2t_alloc_switching(dev, f->fs.vlan, + f->fs.eport, f->fs.dmac); + if (!f->l2t) { + ret = -ENOMEM; + goto out_err; + } + } + atid = cxgbe_alloc_atid(t, f); if (atid < 0) goto out_err; @@ -653,6 +686,19 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) unsigned int port_id = ethdev2pinfo(dev)->port_id; int ret; + /* + * If the new filter requires loopback Destination MAC and/or VLAN + * rewriting then we need to allocate a Layer 2 Table (L2T) entry for + * the filter. + */ + if (f->fs.newvlan) { + /* allocate L2T entry for new filter */ + f->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan, + f->fs.eport, f->fs.dmac); + if (!f->l2t) + return -ENOMEM; + } + ctrlq = &adapter->sge.ctrlq[port_id]; mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool); if (!mbuf) { @@ -680,9 +726,16 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) cpu_to_be32(V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | + V_FW_FILTER_WR_INSVLAN + (f->fs.newvlan == VLAN_INSERT || + f->fs.newvlan == VLAN_REWRITE) | + V_FW_FILTER_WR_RMVLAN + (f->fs.newvlan == VLAN_REMOVE || + f->fs.newvlan == VLAN_REWRITE) | V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) | V_FW_FILTER_WR_TXCHAN(f->fs.eport) | - V_FW_FILTER_WR_PRIO(f->fs.prio)); + V_FW_FILTER_WR_PRIO(f->fs.prio) | + V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0)); fwr->ethtype = cpu_to_be16(f->fs.val.ethtype); fwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype); fwr->smac_sel = 0; @@ -1046,6 +1099,9 @@ void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl) V_TCB_TIMESTAMP(0ULL) | V_TCB_T_RTT_TS_RECENT_AGE(0ULL), 1); + if (f->fs.newvlan == VLAN_INSERT || + f->fs.newvlan == VLAN_REWRITE) + set_tcb_tflag(adap, tid, S_TF_CCTRL_RFR, 1, 1); break; } default: diff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h index be12e231ac..c7d9366a6d 100644 --- a/drivers/net/cxgbe/cxgbe_filter.h +++ b/drivers/net/cxgbe/cxgbe_filter.h @@ -99,6 +99,9 @@ struct ch_filter_specification { uint32_t iq:10; /* ingress queue */ uint32_t eport:2; /* egress port to switch packet out */ + uint32_t newvlan:2; /* rewrite VLAN Tag */ + uint8_t dmac[ETHER_ADDR_LEN]; /* new destination MAC address */ + uint16_t vlan; /* VLAN Tag to insert */ /* Filter rule value/mask pairs. */ struct ch_filter_tuple val; @@ -111,6 +114,12 @@ enum { FILTER_SWITCH }; +enum { + VLAN_REMOVE = 1, + VLAN_INSERT, + VLAN_REWRITE +}; + enum filter_type { FILTER_TYPE_IPV4 = 0, FILTER_TYPE_IPV6, diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c index 038d479d6b..52bec92bce 100644 --- a/drivers/net/cxgbe/cxgbe_flow.c +++ b/drivers/net/cxgbe/cxgbe_flow.c @@ -331,9 +331,30 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a, struct ch_filter_specification *fs, struct rte_flow_error *e) { + const struct rte_flow_action_of_set_vlan_vid *vlanid; + const struct rte_flow_action_of_push_vlan *pushvlan; const struct rte_flow_action_phy_port *port; switch (a->type) { + case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: + vlanid = (const struct rte_flow_action_of_set_vlan_vid *) + a->conf; + fs->newvlan = VLAN_REWRITE; + fs->vlan = vlanid->vlan_vid; + break; + case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: + pushvlan = (const struct rte_flow_action_of_push_vlan *) + a->conf; + if (pushvlan->ethertype != ETHER_TYPE_VLAN) + return rte_flow_error_set(e, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, a, + "only ethertype 0x8100 " + "supported for push vlan."); + fs->newvlan = VLAN_INSERT; + break; + case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: + fs->newvlan = VLAN_REMOVE; + break; case RTE_FLOW_ACTION_TYPE_PHY_PORT: port = (const struct rte_flow_action_phy_port *)a->conf; fs->eport = port->index; @@ -391,6 +412,9 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow, case RTE_FLOW_ACTION_TYPE_COUNT: fs->hitcnts = 1; break; + case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: + case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: + case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: case RTE_FLOW_ACTION_TYPE_PHY_PORT: /* We allow multiple switch actions, but switch is * not compatible with either queue or drop -- 2.20.1