This patch extended flow director to select vlan id
as filter's input set and program the filter rule with vlan id.

Signed-off-by: Jingjing Wu <jingjing.wu at intel.com>
---
 doc/guides/rel_notes/release_16_04.rst |  2 ++
 drivers/net/i40e/i40e_ethdev.c         | 11 ++++++++
 drivers/net/i40e/i40e_fdir.c           | 49 ++++++++++++++++++++++++++--------
 3 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/doc/guides/rel_notes/release_16_04.rst 
b/doc/guides/rel_notes/release_16_04.rst
index 26af339..b6ee8b3 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -105,6 +105,8 @@ This section should contain new features added in this 
release. Sample format:
   be down.
   We added the support of auto-neg by SW to avoid this link down issue.

+* **Added Flow director enhancements on Intel X710/XL710.**
+

 Resolved Issues
 ---------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index af87298..39a7280 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6618,58 +6618,69 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
         */
        static const uint64_t valid_fdir_inset_table[] = {
                [I40E_FILTER_PCTYPE_FRAG_IPV4] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO |
                I40E_INSET_IPV4_TTL,
                [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
                [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
                [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
                I40E_INSET_SCTP_VT,
                [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
                I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO |
                I40E_INSET_IPV4_TTL,
                [I40E_FILTER_PCTYPE_FRAG_IPV6] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_NEXT_HDR |
                I40E_INSET_IPV6_HOP_LIMIT,
                [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
                [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
                [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT |
                I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
                I40E_INSET_SCTP_VT,
                [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
                I40E_INSET_IPV6_TC | I40E_INSET_IPV6_NEXT_HDR |
                I40E_INSET_IPV6_HOP_LIMIT,
                [I40E_FILTER_PCTYPE_L2_PAYLOAD] =
+               I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
                I40E_INSET_TUNNEL_ID |
                I40E_INSET_LAST_ETHER_TYPE,
        };
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index e4ac79d..e905f9f 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -687,34 +687,50 @@ i40e_fdir_configure(struct rte_eth_dev *dev)
        return ret;
 }

-static inline void
+static inline int
 i40e_fdir_fill_ether_head(const struct rte_eth_fdir_input *fdir_input,
-                              unsigned char *pkt)
+                              unsigned char *pkt, bool vlan)
 {
-       struct ether_hdr *ether = (struct ether_hdr *)pkt;
+       static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
+       uint16_t *ether_type;
+       uint8_t len = 2 * sizeof(struct ether_addr);
+
+       pkt += 2 * sizeof(struct ether_addr);
+       if (vlan && fdir_input->flow_ext.vlan_tci) {
+               rte_memcpy(pkt, vlan_frame, sizeof(vlan_frame));
+               rte_memcpy(pkt + sizeof(uint16_t),
+                          &fdir_input->flow_ext.vlan_tci,
+                          sizeof(uint16_t));
+               pkt += sizeof(vlan_frame);
+               len += sizeof(vlan_frame);
+       }
+       ether_type = (uint16_t *)pkt;
+
        switch (fdir_input->flow_type) {
        case RTE_ETH_FLOW_L2_PAYLOAD:
-               ether->ether_type = fdir_input->flow.l2_flow.ether_type;
+               *ether_type = fdir_input->flow.l2_flow.ether_type;
                break;
        case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
        case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
        case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
        case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
        case RTE_ETH_FLOW_FRAG_IPV4:
-               ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+               *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
                break;
        case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
        case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
        case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
        case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
        case RTE_ETH_FLOW_FRAG_IPV6:
-               ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+               *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
                break;
        default:
                PMD_DRV_LOG(ERR, "unknown flow type %u.",
                            fdir_input->flow_type);
-               break;
+               return -1;
        }
+       len += sizeof(uint16_t);
+       return len;
 }

 static inline void
@@ -814,6 +830,8 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
        struct sctp_hdr *sctp;
        uint8_t size, dst = 0;
        uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
+       int len;
+       static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
        static uint8_t gre4_frame[] = {0x08, 0,
                        0x45, 0, 0, 0x3A, 0, 0, 0, 0, 0x40, 0x2F,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0x08, 0,
@@ -833,6 +851,14 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                        0, 0, 0, 0}; /*Mac + IP + NVGRE hdr*/

        inner_pkt += 2 * sizeof(struct ether_addr);
+       if (fdir_input->flow_ext.vlan_tci) {
+               rte_memcpy(inner_pkt, vlan_frame, sizeof(vlan_frame));
+               rte_memcpy(inner_pkt + sizeof(uint16_t),
+                          &fdir_input->flow_ext.vlan_tci,
+                          sizeof(uint16_t));
+               inner_pkt += sizeof(vlan_frame);
+       }
+
        /* fill the tunnel header if required */
        switch (fdir_input->flow.tunnel_flow.tunnel_type) {
        case RTE_FDIR_TUNNEL_TYPE_GRE:
@@ -862,7 +888,7 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                           &fdir_input->flow.tunnel_flow.tunnel_id,
                           I40E_TUNNEL_KEY_LEN);
                /* fill the ethernet and IP head of inner frame */
-               i40e_fdir_fill_ether_head(fdir_input, inner_pkt);
+               i40e_fdir_fill_ether_head(fdir_input, inner_pkt, FALSE);
                inner_pkt += sizeof(struct ether_hdr);
                break;
        case RTE_FDIR_TUNNEL_TYPE_NVGRE:
@@ -872,13 +898,13 @@ i40e_fdir_construct_pkt(struct i40e_pf *pf,
                           &fdir_input->flow.tunnel_flow.tunnel_id,
                           I40E_TUNNEL_KEY_LEN);
                /* fill the Ether header of inner frame */
-               i40e_fdir_fill_ether_head(fdir_input, inner_pkt);
+               i40e_fdir_fill_ether_head(fdir_input, inner_pkt, FALSE);
                inner_pkt += sizeof(struct ether_hdr);
                break;
        default:
                /* fill the Ether header of single frame */
-               i40e_fdir_fill_ether_head(fdir_input, raw_pkt);
-               inner_pkt = raw_pkt + sizeof(struct ether_hdr);
+               len = i40e_fdir_fill_ether_head(fdir_input, raw_pkt, TRUE);
+               inner_pkt = raw_pkt + len;
                break;
        }

@@ -1123,6 +1149,7 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
                PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
                return ret;
        }
+
        pctype = i40e_flowtype_to_pctype(filter->input.flow_type);
        ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
        if (ret < 0) {
-- 
2.4.0

Reply via email to