@@ -102,6 +102,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;
@@ -176,6 +181,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).
*/
@@ -192,6 +209,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)
@@ -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);
@@ -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);