Add possibility to use RTE_FLOW_ITEM_TYPE_ETH

Signed-off-by: Serhii Iliushyk <sil-...@napatech.com>
---
 doc/guides/nics/features/ntnic.ini            |   1 +
 drivers/net/ntnic/include/hw_mod_backend.h    |  23 +++
 .../profile_inline/flow_api_profile_inline.c  | 180 ++++++++++++++++++
 3 files changed, 204 insertions(+)

diff --git a/doc/guides/nics/features/ntnic.ini 
b/doc/guides/nics/features/ntnic.ini
index 372653695d..36b8212bae 100644
--- a/doc/guides/nics/features/ntnic.ini
+++ b/doc/guides/nics/features/ntnic.ini
@@ -15,6 +15,7 @@ x86-64               = Y
 
 [rte_flow items]
 any                  = Y
+eth                  = Y
 
 [rte_flow actions]
 drop                 = Y
diff --git a/drivers/net/ntnic/include/hw_mod_backend.h 
b/drivers/net/ntnic/include/hw_mod_backend.h
index 99b207a01c..0c22129fb4 100644
--- a/drivers/net/ntnic/include/hw_mod_backend.h
+++ b/drivers/net/ntnic/include/hw_mod_backend.h
@@ -120,6 +120,29 @@ enum {
                }                                                               
                  \
        } while (0)
 
+static inline int is_non_zero(const void *addr, size_t n)
+{
+       size_t i = 0;
+       const uint8_t *p = (const uint8_t *)addr;
+
+       for (i = 0; i < n; i++)
+               if (p[i] != 0)
+                       return 1;
+
+       return 0;
+}
+
+enum frame_offs_e {
+       DYN_L2 = 1,
+       DYN_L3 = 4,
+       DYN_L4 = 7,
+       DYN_L4_PAYLOAD = 8,
+       DYN_TUN_L3 = 13,
+       DYN_TUN_L4 = 16,
+};
+
+/* Sideband info bit indicator */
+
 enum km_flm_if_select_e {
        KM_FLM_IF_FIRST = 0,
        KM_FLM_IF_SECOND = 1
diff --git 
a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c 
b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
index 64168fcc7d..93f666a054 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
@@ -55,6 +55,36 @@ struct flm_flow_key_def_s {
 /*
  * Flow Matcher functionality
  */
+static inline void set_key_def_qw(struct flm_flow_key_def_s *key_def, unsigned 
int qw,
+       unsigned int dyn, unsigned int ofs)
+{
+       assert(qw < 2);
+
+       if (qw == 0) {
+               key_def->qw0_dyn = dyn & 0x7f;
+               key_def->qw0_ofs = ofs & 0xff;
+
+       } else {
+               key_def->qw4_dyn = dyn & 0x7f;
+               key_def->qw4_ofs = ofs & 0xff;
+       }
+}
+
+static inline void set_key_def_sw(struct flm_flow_key_def_s *key_def, unsigned 
int sw,
+       unsigned int dyn, unsigned int ofs)
+{
+       assert(sw < 2);
+
+       if (sw == 0) {
+               key_def->sw8_dyn = dyn & 0x7f;
+               key_def->sw8_ofs = ofs & 0xff;
+
+       } else {
+               key_def->sw9_dyn = dyn & 0x7f;
+               key_def->sw9_ofs = ofs & 0xff;
+       }
+}
+
 static uint8_t get_port_from_port_id(const struct flow_nic_dev *ndev, uint32_t 
port_id)
 {
        struct flow_eth_dev *dev = ndev->eth_base;
@@ -457,6 +487,11 @@ static int interpret_flow_elements(const struct 
flow_eth_dev *dev,
        uint32_t *packet_mask,
        struct flm_flow_key_def_s *key_def)
 {
+       uint32_t any_count = 0;
+
+       unsigned int qw_counter = 0;
+       unsigned int sw_counter = 0;
+
        *in_port_id = UINT32_MAX;
 
        memset(packet_data, 0x0, sizeof(uint32_t) * 10);
@@ -472,6 +507,28 @@ static int interpret_flow_elements(const struct 
flow_eth_dev *dev,
        int qw_reserved_mac = 0;
        int qw_reserved_ipv6 = 0;
 
+       for (int eidx = 0; elem[eidx].type != RTE_FLOW_ITEM_TYPE_END; ++eidx) {
+               switch (elem[eidx].type) {
+               case RTE_FLOW_ITEM_TYPE_ETH: {
+                       const struct rte_ether_hdr *eth_spec =
+                               (const struct rte_ether_hdr *)elem[eidx].spec;
+                       const struct rte_ether_hdr *eth_mask =
+                               (const struct rte_ether_hdr *)elem[eidx].mask;
+
+                       if (eth_spec != NULL && eth_mask != NULL) {
+                               if (is_non_zero(eth_mask->dst_addr.addr_bytes, 
6) ||
+                                       
is_non_zero(eth_mask->src_addr.addr_bytes, 6)) {
+                                       qw_reserved_mac += 1;
+                               }
+                       }
+               }
+               break;
+
+               default:
+                       break;
+               }
+       }
+
        int qw_free = 2 - qw_reserved_mac - qw_reserved_ipv6;
 
        if (qw_free < 0) {
@@ -484,6 +541,129 @@ static int interpret_flow_elements(const struct 
flow_eth_dev *dev,
                switch (elem[eidx].type) {
                case RTE_FLOW_ITEM_TYPE_ANY:
                        NT_LOG(DBG, FILTER, "Adap %i, Port %i: 
RTE_FLOW_ITEM_TYPE_ANY",
+                               dev->ndev->adapter_no, dev->port);
+                       any_count += 1;
+                       break;
+
+               case RTE_FLOW_ITEM_TYPE_ETH:
+                       NT_LOG(DBG, FILTER, "Adap %i, Port %i: 
RTE_FLOW_ITEM_TYPE_ETH",
+                               dev->ndev->adapter_no, dev->port);
+                       {
+                               const struct rte_ether_hdr *eth_spec =
+                                       (const struct rte_ether_hdr 
*)elem[eidx].spec;
+                               const struct rte_ether_hdr *eth_mask =
+                                       (const struct rte_ether_hdr 
*)elem[eidx].mask;
+
+                               if (any_count > 0) {
+                                       NT_LOG(ERR, FILTER,
+                                               "Tunneled L2 ethernet not 
supported");
+                                       flow_nic_set_error(ERR_FAILED, error);
+                                       return -1;
+                               }
+
+                               if (eth_spec == NULL || eth_mask == NULL) {
+                                       fd->l2_prot = PROT_L2_ETH2;
+                                       break;
+                               }
+
+                               int non_zero = 
is_non_zero(eth_mask->dst_addr.addr_bytes, 6) ||
+                                       
is_non_zero(eth_mask->src_addr.addr_bytes, 6);
+
+                               if (non_zero ||
+                                       (eth_mask->ether_type != 0 && 
sw_counter >= 2)) {
+                                       if (qw_counter >= 2) {
+                                               NT_LOG(ERR, FILTER,
+                                                       "Key size too big. Out 
of QW resources.");
+                                               flow_nic_set_error(ERR_FAILED, 
error);
+                                               return -1;
+                                       }
+
+                                       uint32_t *qw_data =
+                                               &packet_data[2 + 4 - qw_counter 
* 4];
+                                       uint32_t *qw_mask =
+                                               &packet_mask[2 + 4 - qw_counter 
* 4];
+
+                                       qw_data[0] = 
((eth_spec->dst_addr.addr_bytes[0] &
+                                               
eth_mask->dst_addr.addr_bytes[0]) << 24) +
+                                               
((eth_spec->dst_addr.addr_bytes[1] &
+                                               
eth_mask->dst_addr.addr_bytes[1]) << 16) +
+                                               
((eth_spec->dst_addr.addr_bytes[2] &
+                                               
eth_mask->dst_addr.addr_bytes[2]) << 8) +
+                                               
(eth_spec->dst_addr.addr_bytes[3] &
+                                               
eth_mask->dst_addr.addr_bytes[3]);
+
+                                       qw_data[1] = 
((eth_spec->dst_addr.addr_bytes[4] &
+                                               
eth_mask->dst_addr.addr_bytes[4]) << 24) +
+                                               
((eth_spec->dst_addr.addr_bytes[5] &
+                                               
eth_mask->dst_addr.addr_bytes[5]) << 16) +
+                                               
((eth_spec->src_addr.addr_bytes[0] &
+                                               
eth_mask->src_addr.addr_bytes[0]) << 8) +
+                                               
(eth_spec->src_addr.addr_bytes[1] &
+                                               
eth_mask->src_addr.addr_bytes[1]);
+
+                                       qw_data[2] = 
((eth_spec->src_addr.addr_bytes[2] &
+                                               
eth_mask->src_addr.addr_bytes[2]) << 24) +
+                                               
((eth_spec->src_addr.addr_bytes[3] &
+                                               
eth_mask->src_addr.addr_bytes[3]) << 16) +
+                                               
((eth_spec->src_addr.addr_bytes[4] &
+                                               
eth_mask->src_addr.addr_bytes[4]) << 8) +
+                                               
(eth_spec->src_addr.addr_bytes[5] &
+                                               
eth_mask->src_addr.addr_bytes[5]);
+
+                                       qw_data[3] = ntohs(eth_spec->ether_type 
&
+                                               eth_mask->ether_type) << 16;
+
+                                       qw_mask[0] = 
(eth_mask->dst_addr.addr_bytes[0] << 24) +
+                                               
(eth_mask->dst_addr.addr_bytes[1] << 16) +
+                                               
(eth_mask->dst_addr.addr_bytes[2] << 8) +
+                                               
eth_mask->dst_addr.addr_bytes[3];
+
+                                       qw_mask[1] = 
(eth_mask->dst_addr.addr_bytes[4] << 24) +
+                                               
(eth_mask->dst_addr.addr_bytes[5] << 16) +
+                                               
(eth_mask->src_addr.addr_bytes[0] << 8) +
+                                               
eth_mask->src_addr.addr_bytes[1];
+
+                                       qw_mask[2] = 
(eth_mask->src_addr.addr_bytes[2] << 24) +
+                                               
(eth_mask->src_addr.addr_bytes[3] << 16) +
+                                               
(eth_mask->src_addr.addr_bytes[4] << 8) +
+                                               
eth_mask->src_addr.addr_bytes[5];
+
+                                       qw_mask[3] = 
ntohs(eth_mask->ether_type) << 16;
+
+                                       km_add_match_elem(&fd->km,
+                                               &qw_data[(size_t)(qw_counter * 
4)],
+                                               &qw_mask[(size_t)(qw_counter * 
4)], 4, DYN_L2, 0);
+                                       set_key_def_qw(key_def, qw_counter, 
DYN_L2, 0);
+                                       qw_counter += 1;
+
+                                       if (!non_zero)
+                                               qw_free -= 1;
+
+                               } else if (eth_mask->ether_type != 0) {
+                                       if (sw_counter >= 2) {
+                                               NT_LOG(ERR, FILTER,
+                                                       "Key size too big. Out 
of SW-QW resources.");
+                                               flow_nic_set_error(ERR_FAILED, 
error);
+                                               return -1;
+                                       }
+
+                                       uint32_t *sw_data = &packet_data[1 - 
sw_counter];
+                                       uint32_t *sw_mask = &packet_mask[1 - 
sw_counter];
+
+                                       sw_mask[0] = 
ntohs(eth_mask->ether_type) << 16;
+                                       sw_data[0] = 
ntohs(eth_spec->ether_type) << 16 & sw_mask[0];
+
+                                       km_add_match_elem(&fd->km, &sw_data[0],
+                                               &sw_mask[0], 1, DYN_L2, 12);
+                                       set_key_def_sw(key_def, sw_counter, 
DYN_L2, 12);
+                                       sw_counter += 1;
+                               }
+
+                               fd->l2_prot = PROT_L2_ETH2;
+                       }
+
+                       break;
+
                                dev->ndev->adapter_no, dev->port);
                        break;
 
-- 
2.45.0

Reply via email to