This patch enables MPLS tunnel filter by replacing
inner_mac filter.
This configuration will be set when adding MPLSoUDP
and MPLSoGRE filter rules, and it will be invalid
only by NIC core reset.

Signed-off-by: Beilei Xing <beilei.x...@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c |  45 +++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |  11 ++++-
 drivers/net/i40e/i40e_flow.c   | 110 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 149 insertions(+), 17 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 506b957..5e6e2f5 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6954,6 +6954,7 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
        struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
        struct i40e_tunnel_filter *tunnel, *node;
        struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+       uint32_t teid_le;
        bool big_buffer = 0;
 
        cld_filter = rte_zmalloc("tunnel_filter",
@@ -7002,6 +7003,32 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
        case I40E_TUNNEL_TYPE_IP_IN_GRE:
                tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
                break;
+       case I40E_TUNNEL_TYPE_MPLSoUDP:
+               i40e_replace_mpls_l1_filter(pf);
+               i40e_replace_mpls_cloud_filter(pf);
+               teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+                       teid_le >> 4;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+                       (teid_le & 0xF) << 12;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+                       0x40;
+               big_buffer = 1;
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+               break;
+       case I40E_TUNNEL_TYPE_MPLSoGRE:
+               i40e_replace_mpls_l1_filter(pf);
+               i40e_replace_mpls_cloud_filter(pf);
+               teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+                       teid_le >> 4;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+                       (teid_le & 0xF) << 12;
+               pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+                       0x0;
+               big_buffer = 1;
+               tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+               break;
        default:
                /* Other tunnel types is not supported. */
                PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7009,11 +7036,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf 
*pf,
                return -EINVAL;
        }
 
-       val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-                                      &pfilter->element.flags);
-       if (val < 0) {
-               rte_free(cld_filter);
-               return -EINVAL;
+       if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+               pfilter->element.flags =
+                       I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+       else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+               pfilter->element.flags =
+                       I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+       else {
+               val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+                                               &pfilter->element.flags);
+               if (val < 0) {
+                       rte_free(cld_filter);
+                       return -EINVAL;
+               }
        }
 
        pfilter->element.flags |= rte_cpu_to_le_16(
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index df345b1..934c679 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -500,8 +500,13 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12
+#define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
 
 enum i40e_tunnel_iptype {
        I40E_TUNNEL_IPTYPE_IPV4,
@@ -863,6 +868,8 @@ int i40e_dev_consistent_tunnel_filter_set(struct i40e_pf 
*pf,
                                  struct i40e_tunnel_filter_conf *tunnel_filter,
                                  uint8_t add);
 int i40e_fdir_flush(struct rte_eth_dev *dev);
+enum i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf);
+enum i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
        RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index eefb15b..8d7765a 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
                   filter->input.general_fields,
                   sizeof(cld_filter.general_fields));
 
-       if (((filter->input.flags &
-             (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
-              I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
-            (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
-             I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
-           ((filter->input.flags &
-             (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
-              I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
-            (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
-             I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
+       if ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+           I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
+           (filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+           I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
                big_buffer = 1;
 
        if (big_buffer)
@@ -2103,3 +2097,99 @@ i40e_flow_flush_tunnel_filter(struct i40e_pf *pf)
 
        return ret;
 }
+
+enum
+i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+       struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+       struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       enum i40e_status_code status = I40E_SUCCESS;
+
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+       /* create L1 filter */
+       filter_replace.old_filter_type =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+       filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+       filter_replace.tr_bit = 0xFF;
+
+       /* Prepare the buffer, 3 entries */
+       filter_replace_buf.data[0] =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[2] = 0xff;
+       filter_replace_buf.data[3] = 0xff;
+       filter_replace_buf.data[4] =
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[7] = 0xf0;
+       filter_replace_buf.data[8] = 0x48;
+       filter_replace_buf.data[8] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[10] = 0x4c;
+       filter_replace_buf.data[11] = 0x8c;
+
+       status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                                              &filter_replace_buf);
+       return status;
+}
+
+enum
+i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+       struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+       struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       enum i40e_status_code status = I40E_SUCCESS;
+
+       /* For MPLSoUDP */
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+       filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+               I40E_AQC_MIRROR_CLOUD_FILTER;
+       filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+       filter_replace.new_filter_type =
+               I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+       /* Prepare the buffer, 2 entries */
+       filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                                              &filter_replace_buf);
+       if (status < 0)
+               return status;
+
+       /* For MPLSoGRE */
+       memset(&filter_replace, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+       memset(&filter_replace_buf, 0,
+              sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+       filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+               I40E_AQC_MIRROR_CLOUD_FILTER;
+       filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+       filter_replace.new_filter_type =
+               I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+       /* Prepare the buffer, 2 entries */
+       filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+       filter_replace_buf.data[0] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+       filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+       filter_replace_buf.data[4] |=
+               I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+       status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+                                              &filter_replace_buf);
+       return status;
+}
-- 
2.5.5

Reply via email to