Support add and delete operaions on ethertype filter.

Signed-off-by: Jiawen Wu <jiawe...@trustnetic.com>
---
 drivers/net/txgbe/txgbe_ethdev.c | 111 +++++++++++++++++++++++++++++++
 drivers/net/txgbe/txgbe_ethdev.h |  19 ++++++
 2 files changed, 130 insertions(+)

diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 1804802e5..b479c9152 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -3983,6 +3983,77 @@ txgbe_add_del_ntuple_filter(struct rte_eth_dev *dev,
        return 0;
 }
 
+int
+txgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ethertype_filter *filter,
+                       bool add)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+       uint32_t etqf = 0;
+       uint32_t etqs = 0;
+       int ret;
+       struct txgbe_ethertype_filter ethertype_filter;
+
+       if (filter->queue >= TXGBE_MAX_RX_QUEUE_NUM)
+               return -EINVAL;
+
+       if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
+           filter->ether_type == RTE_ETHER_TYPE_IPV6) {
+               PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in"
+                       " ethertype filter.", filter->ether_type);
+               return -EINVAL;
+       }
+
+       if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) {
+               PMD_DRV_LOG(ERR, "mac compare is unsupported.");
+               return -EINVAL;
+       }
+       if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) {
+               PMD_DRV_LOG(ERR, "drop option is unsupported.");
+               return -EINVAL;
+       }
+
+       ret = txgbe_ethertype_filter_lookup(filter_info, filter->ether_type);
+       if (ret >= 0 && add) {
+               PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.",
+                           filter->ether_type);
+               return -EEXIST;
+       }
+       if (ret < 0 && !add) {
+               PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.",
+                           filter->ether_type);
+               return -ENOENT;
+       }
+
+       if (add) {
+               etqf = TXGBE_ETFLT_ENA;
+               etqf |= TXGBE_ETFLT_ETID(filter->ether_type);
+               etqs |= TXGBE_ETCLS_QPID(filter->queue);
+               etqs |= TXGBE_ETCLS_QENA;
+
+               ethertype_filter.ethertype = filter->ether_type;
+               ethertype_filter.etqf = etqf;
+               ethertype_filter.etqs = etqs;
+               ethertype_filter.conf = FALSE;
+               ret = txgbe_ethertype_filter_insert(filter_info,
+                                                   &ethertype_filter);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "ethertype filters are full.");
+                       return -ENOSPC;
+               }
+       } else {
+               ret = txgbe_ethertype_filter_remove(filter_info, (uint8_t)ret);
+               if (ret < 0)
+                       return -ENOSYS;
+       }
+       wr32(hw, TXGBE_ETFLT(ret), etqf);
+       wr32(hw, TXGBE_ETCLS(ret), etqs);
+       txgbe_flush(hw);
+
+       return 0;
+}
+
 static u8 *
 txgbe_dev_addr_list_itr(__rte_unused struct txgbe_hw *hw,
                        u8 **mc_addr_ptr, u32 *vmdq)
@@ -4516,10 +4587,30 @@ txgbe_ntuple_filter_restore(struct rte_eth_dev *dev)
        }
 }
 
+/* restore ethernet type filter */
+static inline void
+txgbe_ethertype_filter_restore(struct rte_eth_dev *dev)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+       int i;
+
+       for (i = 0; i < TXGBE_ETF_ID_MAX; i++) {
+               if (filter_info->ethertype_mask & (1 << i)) {
+                       wr32(hw, TXGBE_ETFLT(i),
+                                       filter_info->ethertype_filters[i].etqf);
+                       wr32(hw, TXGBE_ETCLS(i),
+                                       filter_info->ethertype_filters[i].etqs);
+                       txgbe_flush(hw);
+               }
+       }
+}
+
 static int
 txgbe_filter_restore(struct rte_eth_dev *dev)
 {
        txgbe_ntuple_filter_restore(dev);
+       txgbe_ethertype_filter_restore(dev);
 
        return 0;
 }
@@ -4535,6 +4626,26 @@ txgbe_clear_all_ntuple_filter(struct rte_eth_dev *dev)
                txgbe_remove_5tuple_filter(dev, p_5tuple);
 }
 
+/* remove all the ether type filters */
+void
+txgbe_clear_all_ethertype_filter(struct rte_eth_dev *dev)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+       int i;
+
+       for (i = 0; i < TXGBE_ETF_ID_MAX; i++) {
+               if (filter_info->ethertype_mask & (1 << i) &&
+                   !filter_info->ethertype_filters[i].conf) {
+                       (void)txgbe_ethertype_filter_remove(filter_info,
+                                                           (uint8_t)i);
+                       wr32(hw, TXGBE_ETFLT(i), 0);
+                       wr32(hw, TXGBE_ETCLS(i), 0);
+                       txgbe_flush(hw);
+               }
+       }
+}
+
 static const struct eth_dev_ops txgbe_eth_dev_ops = {
        .dev_configure              = txgbe_dev_configure,
        .dev_infos_get              = txgbe_dev_info_get,
diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h
index c82f0c832..d89af2150 100644
--- a/drivers/net/txgbe/txgbe_ethdev.h
+++ b/drivers/net/txgbe/txgbe_ethdev.h
@@ -317,6 +317,10 @@ bool txgbe_rss_update_sp(enum txgbe_mac_type mac_type);
 int txgbe_add_del_ntuple_filter(struct rte_eth_dev *dev,
                        struct rte_eth_ntuple_filter *filter,
                        bool add);
+int txgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ethertype_filter *filter,
+                       bool add);
+
 void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction,
                               uint8_t queue, uint8_t msix_vector);
 
@@ -337,6 +341,7 @@ int txgbe_pf_host_configure(struct rte_eth_dev *eth_dev);
 
 uint32_t txgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val);
 
+void txgbe_clear_all_ethertype_filter(struct rte_eth_dev *dev);
 void txgbe_clear_all_ntuple_filter(struct rte_eth_dev *dev);
 
 int txgbe_vt_check(struct txgbe_hw *hw);
@@ -382,6 +387,20 @@ txgbe_ethertype_filter_insert(struct txgbe_filter_info 
*filter_info,
        return (i < TXGBE_ETF_ID_MAX ? i : -1);
 }
 
+static inline int
+txgbe_ethertype_filter_remove(struct txgbe_filter_info *filter_info,
+                             uint8_t idx)
+{
+       if (idx >= TXGBE_ETF_ID_MAX)
+               return -1;
+       filter_info->ethertype_mask &= ~(1 << idx);
+       filter_info->ethertype_filters[idx].ethertype = 0;
+       filter_info->ethertype_filters[idx].etqf = 0;
+       filter_info->ethertype_filters[idx].etqs = 0;
+       filter_info->ethertype_filters[idx].etqs = FALSE;
+       return idx;
+}
+
 /* High threshold controlling when to start sending XOFF frames. */
 #define TXGBE_FC_XOFF_HITH              128 /*KB*/
 /* Low threshold controlling when to start sending XON frames. */
-- 
2.18.4



Reply via email to