net/cxgbe: add flow operations to offload VLAN actions
authorShagun Agrawal <shaguna@chelsio.com>
Mon, 27 Aug 2018 12:52:30 +0000 (18:22 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 14 Sep 2018 18:08:41 +0000 (20:08 +0200)
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 <shaguna@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
doc/guides/rel_notes/release_18_11.rst
drivers/net/cxgbe/base/t4_msg.h
drivers/net/cxgbe/base/t4_tcb.h
drivers/net/cxgbe/cxgbe_filter.c
drivers/net/cxgbe/cxgbe_filter.h
drivers/net/cxgbe/cxgbe_flow.c

index 24204e6..605e7d2 100644 (file)
@@ -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
 -----------
index 094a153..2128da6 100644 (file)
@@ -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)
index 25435f9..68cda77 100644 (file)
@@ -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 */
index 7f0d380..4d3f3eb 100644 (file)
@@ -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:
index be12e23..c7d9366 100644 (file)
@@ -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,
index 038d479..52bec92 100644 (file)
@@ -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