From: Alvin Zhang <alvinx.zh...@intel.com>

Support putting all TCP SYN packets into a specified queue.

Signed-off-by: Alvin Zhang <alvinx.zh...@intel.com>
---
 drivers/net/igc/igc_ethdev.h |  18 ++++++
 drivers/net/igc/igc_filter.c | 129 +++++++++++++++++++++++++++++++++++++++++++
 drivers/net/igc/igc_filter.h |   3 +
 3 files changed, 150 insertions(+)

diff --git a/drivers/net/igc/igc_ethdev.h b/drivers/net/igc/igc_ethdev.h
index 49075c8..91a3198 100644
--- a/drivers/net/igc/igc_ethdev.h
+++ b/drivers/net/igc/igc_ethdev.h
@@ -101,6 +101,11 @@
 #define IGC_MAX_2TUPLE_FILTERS         8
 #define IGC_2TUPLE_MAX_PRI             7
 
+#define IGC_SYN_FILTER_ENABLE          0x01    /* syn filter enable field */
+#define IGC_SYN_FILTER_QUEUE_SHIFT     1       /* syn filter queue field */
+#define IGC_SYN_FILTER_QUEUE   0x0000000E      /* syn filter queue field */
+#define IGC_RFCTL_SYNQFP       0x00080000      /* SYNQFP in RFCTL register */
+
 /* structure for interrupt relative data */
 struct igc_interrupt {
        uint32_t flags;
@@ -175,6 +180,18 @@ struct igc_2tuple_filter {
        uint8_t queue;
 };
 
+/* Structure of TCP SYN filter */
+struct igc_syn_filter {
+       uint8_t queue;
+       /*
+        * Defines the priority between SYNQF and 2 tuple filter
+        * 0b = 2-tuple filter priority
+        * 1b = SYN filter priority
+        */
+       uint8_t priority:1,
+               enable:1;       /* 1-enable; 0-disable */
+};
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -191,6 +208,7 @@ struct igc_adapter {
 
        struct igc_ethertype_filter ethertype_filters[IGC_MAX_ETQF_FILTERS];
        struct igc_2tuple_filter tuple2_filters[IGC_MAX_2TUPLE_FILTERS];
+       struct igc_syn_filter syn_filter;
 };
 
 #define IGC_DEV_PRIVATE(_dev)  ((_dev)->data->dev_private)
diff --git a/drivers/net/igc/igc_filter.c b/drivers/net/igc/igc_filter.c
index 340dbee..5203d82 100644
--- a/drivers/net/igc/igc_filter.c
+++ b/drivers/net/igc/igc_filter.c
@@ -546,11 +546,136 @@
        return ret;
 }
 
+int
+igc_set_syn_filter(struct rte_eth_dev *dev,
+               const struct rte_eth_syn_filter *filter)
+{
+       struct igc_hw *hw;
+       struct igc_adapter *igc;
+       struct igc_syn_filter *syn_filter;
+       uint32_t synqf, rfctl;
+
+       if (filter->queue >= IGC_QUEUE_PAIRS_NUM) {
+               PMD_DRV_LOG(ERR, "out of range queue %u(max is %u)",
+                       filter->queue, IGC_QUEUE_PAIRS_NUM);
+               return -EINVAL;
+       }
+
+       igc = IGC_DEV_PRIVATE(dev);
+       syn_filter = &igc->syn_filter;
+
+       if (syn_filter->enable) {
+               PMD_DRV_LOG(ERR, "SYN filter has been enabled before!");
+               return -EEXIST;
+       }
+
+       hw = IGC_DEV_PRIVATE_HW(dev);
+       synqf = (uint32_t)filter->queue << IGC_SYN_FILTER_QUEUE_SHIFT;
+       synqf |= IGC_SYN_FILTER_ENABLE;
+
+       rfctl = IGC_READ_REG(hw, IGC_RFCTL);
+       if (filter->hig_pri) {
+               syn_filter->priority = 1;
+               rfctl |= IGC_RFCTL_SYNQFP;
+       } else {
+               syn_filter->priority = 0;
+               rfctl &= ~IGC_RFCTL_SYNQFP;
+       }
+
+       syn_filter->enable = 1;
+       syn_filter->queue = filter->queue;
+       IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
+       IGC_WRITE_REG(hw, IGC_SYNQF(0), synqf);
+       IGC_WRITE_FLUSH(hw);
+       return 0;
+}
+
+int
+igc_del_syn_filter(struct rte_eth_dev *dev)
+{
+       struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+       struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
+       struct igc_syn_filter *syn_filter = &igc->syn_filter;
+
+       if (syn_filter->enable == 0)
+               return 0;
+
+       syn_filter->enable = 0;
+
+       IGC_WRITE_REG(hw, IGC_SYNQF(0), 0);
+       IGC_WRITE_FLUSH(hw);
+       return 0;
+}
+
+static int
+igc_syn_filter_get(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter)
+{
+       struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
+       struct igc_syn_filter *syn_filter = &igc->syn_filter;
+
+       if (syn_filter->enable == 0) {
+               PMD_DRV_LOG(ERR, "syn filter not been set.\n");
+               return -ENOENT;
+       }
+
+       filter->hig_pri = syn_filter->priority;
+       filter->queue = syn_filter->queue;
+       return 0;
+}
+
+/* clear the SYN filter */
+static void
+igc_clear_syn_filter(struct rte_eth_dev *dev)
+{
+       struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+       struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
+
+       IGC_WRITE_REG(hw, IGC_SYNQF(0), 0);
+       IGC_WRITE_FLUSH(hw);
+
+       memset(&igc->syn_filter, 0, sizeof(igc->syn_filter));
+}
+
+static int
+igc_syn_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op,
+               struct rte_eth_syn_filter *filter)
+{
+       int ret;
+
+       if (filter_op == RTE_ETH_FILTER_NOP)
+               return 0;
+
+       if (filter == NULL) {
+               PMD_DRV_LOG(ERR, "filter shouldn't be NULL for operation %u",
+                           filter_op);
+               return -EINVAL;
+       }
+
+       switch (filter_op) {
+       case RTE_ETH_FILTER_ADD:
+               ret = igc_set_syn_filter(dev, filter);
+               break;
+       case RTE_ETH_FILTER_DELETE:
+               ret = igc_del_syn_filter(dev);
+               break;
+       case RTE_ETH_FILTER_GET:
+               ret = igc_syn_filter_get(dev, filter);
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "unsupported operation %u", filter_op);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
 void
 igc_clear_all_filter(struct rte_eth_dev *dev)
 {
        igc_clear_all_ethertype_filter(dev);
        igc_clear_all_ntuple_filter(dev);
+       igc_clear_syn_filter(dev);
 }
 
 int
@@ -568,6 +693,10 @@
                ret = igc_ntuple_filter_handle(dev, filter_op,
                        (struct rte_eth_ntuple_filter *)arg);
                break;
+       case RTE_ETH_FILTER_SYN:
+               ret = igc_syn_filter_handle(dev, filter_op,
+                       (struct rte_eth_syn_filter *)arg);
+               break;
        default:
                PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
                                                        filter_type);
diff --git a/drivers/net/igc/igc_filter.h b/drivers/net/igc/igc_filter.h
index 7c5e843..4fad8e0 100644
--- a/drivers/net/igc/igc_filter.h
+++ b/drivers/net/igc/igc_filter.h
@@ -20,6 +20,9 @@ int igc_del_ethertype_filter(struct rte_eth_dev *dev,
 int igc_add_del_ntuple_filter(struct rte_eth_dev *dev,
                        const struct rte_eth_ntuple_filter *ntuple,
                        bool add);
+int igc_set_syn_filter(struct rte_eth_dev *dev,
+               const struct rte_eth_syn_filter *filter);
+int igc_del_syn_filter(struct rte_eth_dev *dev);
 void
 igc_clear_all_filter(struct rte_eth_dev *dev);
 
-- 
1.8.3.1

Reply via email to