net/cxgbe: add action to swap MAC addresses
authorRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Mon, 15 Oct 2018 14:05:13 +0000 (19:35 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 18 Oct 2018 08:24:39 +0000 (10:24 +0200)
Implement RTE_FLOW_ACTION_TYPE_MAC_SWAP to offload flows with
action to swap the source and destination MAC addresses in the
outermost Ethernet header.

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/t4fw_interface.h
drivers/net/cxgbe/cxgbe_filter.c
drivers/net/cxgbe/cxgbe_filter.h
drivers/net/cxgbe/cxgbe_flow.c

index 67df5c1..87a410f 100644 (file)
@@ -93,7 +93,8 @@ New Features
   * Match items: destination MAC address.
   * Action items: push/pop/rewrite vlan header,
     rewrite IP addresses in outermost IPv4/IPv6 header,
-    rewrite port numbers in outermost TCP/UDP header.
+    rewrite port numbers in outermost TCP/UDP header,
+    swap MAC addresses in outermost Ethernet header.
 
 * **Added a devarg to use the latest supported vector path in i40e.**
   A new devarg ``use-latest-supported-vec`` was introduced to allow users to
index 6494f18..9e052b0 100644 (file)
@@ -163,6 +163,9 @@ struct work_request_hdr {
 #define S_CCTRL_ECN    27
 #define V_CCTRL_ECN(x) ((x) << S_CCTRL_ECN)
 
+#define S_SACK_EN    30
+#define V_SACK_EN(x) ((x) << S_SACK_EN)
+
 #define S_T5_OPT_2_VALID    31
 #define V_T5_OPT_2_VALID(x) ((x) << S_T5_OPT_2_VALID)
 #define F_T5_OPT_2_VALID    V_T5_OPT_2_VALID(1U)
index b4c95c5..06d3ef3 100644 (file)
@@ -314,6 +314,9 @@ struct fw_filter2_wr {
 #define S_FW_FILTER_WR_MATCHTYPEM      0
 #define V_FW_FILTER_WR_MATCHTYPEM(x)   ((x) << S_FW_FILTER_WR_MATCHTYPEM)
 
+#define S_FW_FILTER2_WR_SWAPMAC                0
+#define V_FW_FILTER2_WR_SWAPMAC(x)     ((x) << S_FW_FILTER2_WR_SWAPMAC)
+
 #define S_FW_FILTER2_WR_NATMODE                5
 #define V_FW_FILTER2_WR_NATMODE(x)     ((x) << S_FW_FILTER2_WR_NATMODE)
 
index b876abf..ef1102b 100644 (file)
@@ -92,6 +92,9 @@ int validate_filter(struct adapter *adapter, struct ch_filter_specification *fs)
        if (!fs->cap && fs->nat_mode && !adapter->params.filter2_wr_support)
                return -EOPNOTSUPP;
 
+       if (!fs->cap && fs->swapmac && !adapter->params.filter2_wr_support)
+               return -EOPNOTSUPP;
+
        return 0;
 }
 
@@ -456,6 +459,7 @@ static void mk_act_open_req6(struct filter_entry *f, struct rte_mbuf *mbuf,
                            V_RSS_QUEUE(f->fs.iq) |
                            F_T5_OPT_2_VALID |
                            F_RX_CHANNEL |
+                           V_SACK_EN(f->fs.swapmac) |
                            V_CONG_CNTRL((f->fs.action == FILTER_DROP) |
                                         (f->fs.dirsteer << 1)) |
                            V_CCTRL_ECN(f->fs.action == FILTER_SWITCH));
@@ -502,6 +506,7 @@ static void mk_act_open_req(struct filter_entry *f, struct rte_mbuf *mbuf,
                            V_RSS_QUEUE(f->fs.iq) |
                            F_T5_OPT_2_VALID |
                            F_RX_CHANNEL |
+                           V_SACK_EN(f->fs.swapmac) |
                            V_CONG_CNTRL((f->fs.action == FILTER_DROP) |
                                         (f->fs.dirsteer << 1)) |
                            V_CCTRL_ECN(f->fs.action == FILTER_SWITCH));
@@ -773,9 +778,13 @@ int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
        fwr->fp = cpu_to_be16(f->fs.val.fport);
        fwr->fpm = cpu_to_be16(f->fs.mask.fport);
 
-       if (adapter->params.filter2_wr_support && f->fs.nat_mode) {
+       if (adapter->params.filter2_wr_support) {
+               fwr->filter_type_swapmac =
+                        V_FW_FILTER2_WR_SWAPMAC(f->fs.swapmac);
                fwr->natmode_to_ulp_type =
-                       V_FW_FILTER2_WR_ULP_TYPE(ULP_MODE_TCPDDP) |
+                       V_FW_FILTER2_WR_ULP_TYPE(f->fs.nat_mode ?
+                                                ULP_MODE_TCPDDP :
+                                                ULP_MODE_NONE) |
                        V_FW_FILTER2_WR_NATMODE(f->fs.nat_mode);
                memcpy(fwr->newlip, f->fs.nat_lip, sizeof(fwr->newlip));
                memcpy(fwr->newfip, f->fs.nat_fip, sizeof(fwr->newfip));
index 950fa0b..b7bcbf5 100644 (file)
@@ -100,6 +100,7 @@ struct ch_filter_specification {
        uint32_t iq:10;         /* ingress queue */
 
        uint32_t eport:2;       /* egress port to switch packet out */
+       uint32_t swapmac:1;     /* swap SMAC/DMAC for loopback packet */
        uint32_t newvlan:2;     /* rewrite VLAN Tag */
        uint8_t dmac[ETHER_ADDR_LEN];   /* new destination MAC address */
        uint16_t vlan;          /* VLAN Tag to insert */
index 3e4acf3..ccd165b 100644 (file)
@@ -552,6 +552,16 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,
                fs->nat_lport = be16_to_cpu(tp_port->port);
                *nmode |= 1 << 3;
                break;
+       case RTE_FLOW_ACTION_TYPE_MAC_SWAP:
+               item_index = cxgbe_get_flow_item_index(items,
+                                                      RTE_FLOW_ITEM_TYPE_ETH);
+               if (item_index < 0)
+                       return rte_flow_error_set(e, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ACTION, a,
+                                                 "No RTE_FLOW_ITEM_TYPE_ETH "
+                                                 "found");
+               fs->swapmac = 1;
+               break;
        default:
                /* We are not supposed to come here */
                return rte_flow_error_set(e, EINVAL,
@@ -611,6 +621,7 @@ cxgbe_rtef_parse_actions(struct rte_flow *flow,
                case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
                case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
                case RTE_FLOW_ACTION_TYPE_PHY_PORT:
+               case RTE_FLOW_ACTION_TYPE_MAC_SWAP:
                case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
                case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
                        nat_ipv4++;