From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [143.182.124.21]) by dpdk.org (Postfix) with ESMTP id EA08E58EC for ; Thu, 12 Jun 2014 13:51:12 +0200 (CEST) Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 12 Jun 2014 04:50:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.01,464,1400050800"; d="scan'208";a="444659195" Received: from shilc102.sh.intel.com ([10.239.39.44]) by azsmga001.ch.intel.com with ESMTP; 12 Jun 2014 04:50:45 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shilc102.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id s5CBof4B006756; Thu, 12 Jun 2014 19:50:43 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id s5CBocCh031599; Thu, 12 Jun 2014 19:50:40 +0800 Received: (from wujingji@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s5CBoc0C031595; Thu, 12 Jun 2014 19:50:38 +0800 From: Jingjing Wu To: dev@dpdk.org Date: Thu, 12 Jun 2014 19:50:25 +0800 Message-Id: <1402573826-31469-4-git-send-email-jingjing.wu@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1402573826-31469-1-git-send-email-jingjing.wu@intel.com> References: <1402573826-31469-1-git-send-email-jingjing.wu@intel.com> Subject: [dpdk-dev] [PATCH v3 3/4] ixgbe: add ixgbe NIC filters of generic filter feature X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Jun 2014 11:51:13 -0000 This patch adds following ixgbe NIC filters implement: syn filter, ethertype filter, 5tuple filter for intel NIC 82599 Signed-off-by: jingjing.wu --- lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 408 ++++++++++++++++++++++++++++++++++++ lib/librte_pmd_ixgbe/ixgbe_ethdev.h | 34 +++ 2 files changed, 442 insertions(+) diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index 10e5633..5f6a0f7 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -196,6 +197,22 @@ static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index); +static int ixgbe_set_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t rx_queue); +static int ixgbe_get_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t *rx_queue); +static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_ethertype_filter *filter, uint8_t rx_queue); +static int ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index); +static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_ethertype_filter *filter, uint8_t *rx_queue); +static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_5tuple_filter *filter, uint8_t rx_queue); +static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, + uint16_t index); +static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_5tuple_filter *filter, uint8_t *rx_queue); /* * Define VF Stats MACRO for Non "cleared on read" register @@ -326,6 +343,14 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { #endif /* RTE_NIC_BYPASS */ .rss_hash_update = ixgbe_dev_rss_hash_update, .rss_hash_conf_get = ixgbe_dev_rss_hash_conf_get, + .set_syn_filter = ixgbe_set_syn_filter, + .get_syn_filter = ixgbe_get_syn_filter, + .add_ethertype_filter = ixgbe_add_ethertype_filter, + .remove_ethertype_filter = ixgbe_remove_ethertype_filter, + .get_ethertype_filter = ixgbe_get_ethertype_filter, + .add_5tuple_filter = ixgbe_add_5tuple_filter, + .remove_5tuple_filter = ixgbe_remove_5tuple_filter, + .get_5tuple_filter = ixgbe_get_5tuple_filter, }; /* @@ -3388,6 +3413,389 @@ ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index) } } +/* + * set the syn filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * syn: 1 means enable, 0 means disable. + * rx_queue: the queue id the filter assigned to. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_set_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t rx_queue) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t synqf; + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (rx_queue >= IXGBE_MAX_RX_QUEUE_NUM) + return -EINVAL; + + synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); + + if (filter->enable) + synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) & + IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE); + else + synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE); + + if (filter->hig_pri) + synqf |= IXGBE_SYN_FILTER_SYNQFP; + else + synqf &= ~IXGBE_SYN_FILTER_SYNQFP; + + IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf); + return 0; +} + +/* + * get the syn filter's info + * + * @param + * dev: Pointer to struct rte_eth_dev. + * *syn: pointer to syn value (1 means enable, 0 means disable). + * *rx_queue: pointer to the queue id the filter assigned to. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_get_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t *rx_queue) + +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t synqf; + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); + filter->enable = (synqf & IXGBE_SYN_FILTER_ENABLE) ? 1 : 0; + filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0; + *rx_queue = (uint8_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1); + return 0; +} + +/* + * add an ethertype filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates. + * filter: ponter to the filter that will be added. + * rx_queue: the queue id the filter assigned to. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index, struct rte_ethertype_filter *filter, + uint8_t rx_queue) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t etqf, etqs = 0; + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (index >= IXGBE_MAX_ETQF_FILTERS || + rx_queue >= IXGBE_MAX_RX_QUEUE_NUM) + return -EINVAL; + + etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index)); + if (etqf & IXGBE_ETQF_FILTER_EN) + return -EINVAL; /* filter index is in use. */ + + etqf = 0; + etqf |= IXGBE_ETQF_FILTER_EN; + etqf |= (uint32_t)filter->ethertype; + + if (filter->priority_en) { + if (filter->priority > IXGBE_ETQF_MAX_PRI) + return -EINVAL; + etqf |= (uint32_t)((filter->priority << IXGBE_ETQF_SHIFT) & IXGBE_ETQF_UP); + etqf |= IXGBE_ETQF_UP_EN; + } + etqs |= (uint32_t)((rx_queue << IXGBE_ETQS_RX_QUEUE_SHIFT) & IXGBE_ETQS_RX_QUEUE); + etqs |= IXGBE_ETQS_QUEUE_EN; + + IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), etqf); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), etqs); + return 0; +} + +/* + * remove an ethertype filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (index >= IXGBE_MAX_ETQF_FILTERS) + return -EINVAL; + + IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), 0); + + return 0; +} + +/* + * gets an ethertype filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates. + * filter: ponter to the filter that will be gotten. + * *rx_queue: the ponited of the queue id the filter assigned to. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index, struct rte_ethertype_filter *filter, + uint8_t *rx_queue) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t etqf, etqs; + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (index >= IXGBE_MAX_ETQF_FILTERS) + return -EINVAL; + + etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index)); + etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(index)); + if (etqf & IXGBE_ETQF_FILTER_EN) { + filter->ethertype = etqf & IXGBE_ETQF_ETHERTYPE; + filter->priority_en = (etqf & IXGBE_ETQF_UP_EN) ? 1 : 0; + if (filter->priority_en) + filter->priority = (etqf & IXGBE_ETQF_UP) >> 16; + *rx_queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT; + return 0; + } + return -ENOENT; +} + +static inline enum ixgbe_5tuple_protocol +convert_protocol_type(uint8_t protocol_value) +{ + if (protocol_value == IPPROTO_TCP) + return IXGBE_FILTER_PROTOCOL_TCP; + else if (protocol_value == IPPROTO_UDP) + return IXGBE_FILTER_PROTOCOL_UDP; + else if (protocol_value == IPPROTO_SCTP) + return IXGBE_FILTER_PROTOCOL_SCTP; + else + return IXGBE_FILTER_PROTOCOL_NONE; +} + +static inline uint8_t +revert_protocol_type(enum ixgbe_5tuple_protocol protocol) +{ + if (protocol == IXGBE_FILTER_PROTOCOL_TCP) + return IPPROTO_TCP; + else if (protocol == IXGBE_FILTER_PROTOCOL_UDP) + return IPPROTO_UDP; + else if (protocol == IXGBE_FILTER_PROTOCOL_SCTP) + return IPPROTO_SCTP; + else + return 0; +} + +/* + * add a 5tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates. + * filter: ponter to the filter that will be added. + * rx_queue: the queue id the filter assigned to. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_5tuple_filter *filter, uint8_t rx_queue) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t ftqf, sdpqf = 0; + uint32_t l34timir = 0; + uint8_t mask = 0xff; + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (index >= IXGBE_MAX_FTQF_FILTERS || + rx_queue >= IXGBE_MAX_RX_QUEUE_NUM || + filter->priority > IXGBE_5TUPLE_MAX_PRI || + filter->priority < IXGBE_5TUPLE_MIN_PRI) + return -EINVAL; /* filter index is out of range. */ + + if (filter->tcp_flags) { + PMD_INIT_LOG(INFO, "82599EB not tcp flags in 5tuple"); + return -EINVAL; + } + + ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index)); + if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) + return -EINVAL; /* filter index is in use. */ + + ftqf = 0; + sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDPQF_DSTPORT_SHIFT); + sdpqf = sdpqf | (filter->src_port & IXGBE_SDPQF_SRCPORT); + + ftqf |= (uint32_t)(convert_protocol_type(filter->protocol) & + IXGBE_FTQF_PROTOCOL_MASK); + ftqf |= (uint32_t)((filter->priority & IXGBE_FTQF_PRIORITY_MASK) << + IXGBE_FTQF_PRIORITY_SHIFT); + if (filter->src_ip_mask == 0) /* 0 means compare. */ + mask &= IXGBE_FTQF_SOURCE_ADDR_MASK; + if (filter->dst_ip_mask == 0) + mask &= IXGBE_FTQF_DEST_ADDR_MASK; + if (filter->src_port_mask == 0) + mask &= IXGBE_FTQF_SOURCE_PORT_MASK; + if (filter->dst_port_mask == 0) + mask &= IXGBE_FTQF_DEST_PORT_MASK; + if (filter->protocol_mask == 0) + mask &= IXGBE_FTQF_PROTOCOL_COMP_MASK; + ftqf |= mask << IXGBE_FTQF_5TUPLE_MASK_SHIFT; + ftqf |= IXGBE_FTQF_POOL_MASK_EN; + ftqf |= IXGBE_FTQF_QUEUE_ENABLE; + + IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), filter->dst_ip); + IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), filter->src_ip); + IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), sdpqf); + IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), ftqf); + + l34timir |= IXGBE_L34T_IMIR_RESERVE; + l34timir |= (uint32_t)(rx_queue << IXGBE_L34T_IMIR_QUEUE_SHIFT); + IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), l34timir); + return 0; +} + +/* + * remove a 5tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, + uint16_t index) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (index >= IXGBE_MAX_FTQF_FILTERS) + return -EINVAL; /* filter index is out of range. */ + + IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0); + IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0); + return 0; +} + +/* + * get a 5tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that returns. + * *rx_queue: pointer of the queue id the filter assigned to. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_5tuple_filter *filter, uint8_t *rx_queue) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t sdpqf, ftqf, l34timir; + uint8_t mask; + enum ixgbe_5tuple_protocol proto; + + if (hw->mac.type != ixgbe_mac_82599EB) + return -ENOSYS; + + if (index >= IXGBE_MAX_FTQF_FILTERS) + return -EINVAL; /* filter index is out of range. */ + + ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index)); + if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) { + proto = (enum ixgbe_5tuple_protocol)(ftqf & IXGBE_FTQF_PROTOCOL_MASK); + filter->protocol = revert_protocol_type(proto); + filter->priority = (ftqf >> IXGBE_FTQF_PRIORITY_SHIFT) & + IXGBE_FTQF_PRIORITY_MASK; + mask = (uint8_t)((ftqf >> IXGBE_FTQF_5TUPLE_MASK_SHIFT) & + IXGBE_FTQF_5TUPLE_MASK_MASK); + filter->src_ip_mask = + (mask & IXGBE_FTQF_SOURCE_ADDR_MASK) ? 1 : 0; + filter->dst_ip_mask = + (mask & IXGBE_FTQF_DEST_ADDR_MASK) ? 1 : 0; + filter->src_port_mask = + (mask & IXGBE_FTQF_SOURCE_PORT_MASK) ? 1 : 0; + filter->dst_port_mask = + (mask & IXGBE_FTQF_DEST_PORT_MASK) ? 1 : 0; + filter->protocol_mask = + (mask & IXGBE_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0; + + sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index)); + filter->dst_port = (sdpqf & IXGBE_SDPQF_DSTPORT) >> + IXGBE_SDPQF_DSTPORT_SHIFT; + filter->src_port = sdpqf & IXGBE_SDPQF_SRCPORT; + filter->dst_ip = IXGBE_READ_REG(hw, IXGBE_DAQF(index)); + filter->src_ip = IXGBE_READ_REG(hw, IXGBE_SAQF(index)); + + l34timir = IXGBE_READ_REG(hw, IXGBE_L34T_IMIR(index)); + *rx_queue = (l34timir & IXGBE_L34T_IMIR_QUEUE) >> + IXGBE_L34T_IMIR_QUEUE_SHIFT; + return 0; + } + return -ENOENT; +} + static struct rte_driver rte_ixgbe_driver = { .type = PMD_PDEV, .init = rte_ixgbe_pmd_init, diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h index 7a4f84c..a5159e5 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h @@ -74,6 +74,30 @@ (IXGBE_RTTBCNRC_RF_INT_MASK_BASE << IXGBE_RTTBCNRC_RF_INT_SHIFT) #define IXGBE_MAX_QUEUE_NUM_PER_VF 8 + +#define IXGBE_SYN_FILTER_ENABLE 0x00000001 /* syn filter enable field */ +#define IXGBE_SYN_FILTER_QUEUE 0x000000FE /* syn filter queue field */ +#define IXGBE_SYN_FILTER_QUEUE_SHIFT 1 /* syn filter queue field shift */ +#define IXGBE_SYN_FILTER_SYNQFP 0x80000000 /* syn filter SYNQFP */ + +#define IXGBE_ETQF_UP 0x00070000 /* ethertype filter priority field */ +#define IXGBE_ETQF_SHIFT 16 +#define IXGBE_ETQF_UP_EN 0x00080000 +#define IXGBE_ETQF_ETHERTYPE 0x0000FFFF /* ethertype filter ethertype field */ +#define IXGBE_ETQF_MAX_PRI 7 + +#define IXGBE_SDPQF_DSTPORT 0xFFFF0000 /* dst port field */ +#define IXGBE_SDPQF_DSTPORT_SHIFT 16 /* dst port field shift */ +#define IXGBE_SDPQF_SRCPORT 0x0000FFFF /* src port field */ + +#define IXGBE_L34T_IMIR_SIZE_BP 0x00001000 +#define IXGBE_L34T_IMIR_RESERVE 0x00080000 /* bit 13 to 19 must be set to 1000000b. */ +#define IXGBE_L34T_IMIR_LLI 0x00100000 +#define IXGBE_L34T_IMIR_QUEUE 0x0FE00000 +#define IXGBE_L34T_IMIR_QUEUE_SHIFT 21 +#define IXGBE_5TUPLE_MAX_PRI 7 +#define IXGBE_5TUPLE_MIN_PRI 1 + /* * Information about the fdir mode. */ @@ -157,6 +181,16 @@ struct ixgbe_adapter { #endif /* RTE_NIC_BYPASS */ }; +/* + * Possible l4type of 5tuple filters. + */ +enum ixgbe_5tuple_protocol { + IXGBE_FILTER_PROTOCOL_TCP = 0, + IXGBE_FILTER_PROTOCOL_UDP, + IXGBE_FILTER_PROTOCOL_SCTP, + IXGBE_FILTER_PROTOCOL_NONE, +}; + #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\ (&((struct ixgbe_adapter *)adapter)->hw) -- 1.8.1.4