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 32CA0AFD0 for ; Sat, 24 May 2014 03:37:38 +0200 (CEST) Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 23 May 2014 18:37:47 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.98,898,1392192000"; d="scan'208";a="436280944" Received: from shilc102.sh.intel.com ([10.239.39.44]) by azsmga001.ch.intel.com with ESMTP; 23 May 2014 18:37: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 s4O1bf43027816; Sat, 24 May 2014 09:37: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 s4O1bc3K032564; Sat, 24 May 2014 09:37:40 +0800 Received: (from wujingji@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s4O1bcHh032560; Sat, 24 May 2014 09:37:38 +0800 From: Jingjing Wu To: dev@dpdk.org Date: Sat, 24 May 2014 09:37:21 +0800 Message-Id: <1400895442-32433-4-git-send-email-jingjing.wu@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1400895442-32433-1-git-send-email-jingjing.wu@intel.com> References: <1400895442-32433-1-git-send-email-jingjing.wu@intel.com> Subject: [dpdk-dev] [PATCH v2 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: Sat, 24 May 2014 01:37:39 -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 | 409 ++++++++++++++++++++++++++++++++++++ lib/librte_pmd_ixgbe/ixgbe_ethdev.h | 33 +++ 2 files changed, 442 insertions(+) diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index c9b5fe4..340c7cb 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 @@ -182,6 +183,23 @@ static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev, static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id); +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 */ @@ -301,6 +319,14 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { .bypass_ver_show = ixgbe_bypass_ver_show, .bypass_wd_reset = ixgbe_bypass_wd_reset, #endif /* RTE_NIC_BYPASS */ + .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, }; /* @@ -3062,6 +3088,389 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id) return 0; } +/* + * 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 9d7e93f..c5c2845 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h @@ -67,6 +67,29 @@ #define IXGBE_LPBK_82599_NONE 0x0 /* Default value. Loopback is disabled. */ #define IXGBE_LPBK_82599_TX_RX 0x1 /* Tx->Rx loopback operation is enabled. */ +#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. */ @@ -150,6 +173,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