From patchwork Thu Jan 15 01:45:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 2271 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id A40FC5A7B; Thu, 15 Jan 2015 02:46:23 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 535FB5A1F for ; Thu, 15 Jan 2015 02:46:13 +0100 (CET) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 14 Jan 2015 17:46:12 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,400,1418112000"; d="scan'208";a="651319402" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by fmsmga001.fm.intel.com with ESMTP; 14 Jan 2015 17:46:11 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id t0F1k9gr016876; Thu, 15 Jan 2015 09:46:09 +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 t0F1k7qx011552; Thu, 15 Jan 2015 09:46:09 +0800 Received: (from wujingji@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t0F1k7bR011548; Thu, 15 Jan 2015 09:46:07 +0800 From: Jingjing Wu To: dev@dpdk.org Date: Thu, 15 Jan 2015 09:45:58 +0800 Message-Id: <1421286361-11504-3-git-send-email-jingjing.wu@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1421286361-11504-1-git-send-email-jingjing.wu@intel.com> References: <1421286361-11504-1-git-send-email-jingjing.wu@intel.com> Subject: [dpdk-dev] [PATCH 2/5] ixgbe: ntuple filter functions replace old ones for 5tuple filter 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch defines new functions dealing with ntuple filters which is corresponding to 5tuple in HW. It removes old functions which deal with 5tuple filters. It also defines ixgbe_dev_filter_ctrl which is binding to filter_ctrl API, and ntuple filter can be dealt with through this new entrance. Signed-off-by: Jingjing Wu --- lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 489 +++++++++++++++++++++++++++--------- lib/librte_pmd_ixgbe/ixgbe_ethdev.h | 62 ++++- 2 files changed, 421 insertions(+), 130 deletions(-) diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index 3fc3738..02a6be1 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -237,13 +237,22 @@ 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, uint16_t *rx_queue); -static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_5tuple_filter *filter, uint16_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, uint16_t *rx_queue); - +static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, + struct ixgbe_5tuple_filter *filter); +static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, + struct ixgbe_5tuple_filter *filter); +static int ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *filter, + bool add); +static int ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg); +static int ixgbe_get_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *filter); +static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg); static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); /* @@ -383,9 +392,7 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { .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, + .filter_ctrl = ixgbe_dev_filter_ctrl, }; /* @@ -732,6 +739,8 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(eth_dev->data->dev_private); struct ixgbe_dcb_config *dcb_config = IXGBE_DEV_PRIVATE_TO_DCB_CFG(eth_dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); uint32_t ctrl_ext; uint16_t csum; int diag, i; @@ -913,6 +922,11 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, /* enable support intr */ ixgbe_enable_intr(eth_dev); + /* initialize 5tuple filter list */ + TAILQ_INIT(&filter_info->fivetuple_list); + memset(filter_info->fivetuple_mask, 0, + sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE); + return 0; } @@ -1602,6 +1616,9 @@ ixgbe_dev_stop(struct rte_eth_dev *dev) IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct ixgbe_5tuple_filter *p_5tuple, *p_5tuple_next; int vf; PMD_INIT_FUNC_TRACE(); @@ -1631,6 +1648,18 @@ ixgbe_dev_stop(struct rte_eth_dev *dev) /* Clear recorded link status */ memset(&link, 0, sizeof(link)); rte_ixgbe_dev_atomic_write_link_status(dev, &link); + + /* Remove all ntuple filters of the device */ + for (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list); + p_5tuple != NULL; p_5tuple = p_5tuple_next) { + p_5tuple_next = TAILQ_NEXT(p_5tuple, entries); + TAILQ_REMOVE(&filter_info->fivetuple_list, + p_5tuple, entries); + rte_free(p_5tuple); + } + memset(filter_info->fivetuple_mask, 0, + sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE); + } /* @@ -3933,62 +3962,69 @@ revert_protocol_type(enum ixgbe_5tuple_protocol protocol) * - On failure, a negative value. */ static int -ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_5tuple_filter *filter, uint16_t rx_queue) +ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, + struct ixgbe_5tuple_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t ftqf, sdpqf = 0; + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + int i, idx, shift; + uint32_t ftqf, sdpqf; uint32_t l34timir = 0; uint8_t mask = 0xff; - if (hw->mac.type != ixgbe_mac_82599EB) + /* + * look for an unused 5tuple filter index, + * and insert the filter to list. + */ + for (i = 0; i < IXGBE_MAX_FTQF_FILTERS; i++) { + idx = i / UINT32_BIT; + shift = i % UINT32_BIT; + if (!(filter_info->fivetuple_mask[idx] & (1 << shift))) { + filter_info->fivetuple_mask[idx] |= 1 << shift; + filter->index = i; + TAILQ_INSERT_TAIL(&filter_info->fivetuple_list, + filter, + entries); + break; + } + } + if (i >= IXGBE_MAX_FTQF_FILTERS) { + PMD_DRV_LOG(ERR, "5tuple filters are full."); 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. */ + sdpqf = (uint32_t)(filter->filter_info.dst_port << + IXGBE_SDPQF_DSTPORT_SHIFT); + sdpqf = sdpqf | (filter->filter_info.src_port & IXGBE_SDPQF_SRCPORT); - 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) & + ftqf = (uint32_t)(filter->filter_info.proto & 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. */ + ftqf |= (uint32_t)((filter->filter_info.priority & + IXGBE_FTQF_PRIORITY_MASK) << IXGBE_FTQF_PRIORITY_SHIFT); + if (filter->filter_info.src_ip_mask == 0) /* 0 means compare. */ mask &= IXGBE_FTQF_SOURCE_ADDR_MASK; - if (filter->dst_ip_mask == 0) + if (filter->filter_info.dst_ip_mask == 0) mask &= IXGBE_FTQF_DEST_ADDR_MASK; - if (filter->src_port_mask == 0) + if (filter->filter_info.src_port_mask == 0) mask &= IXGBE_FTQF_SOURCE_PORT_MASK; - if (filter->dst_port_mask == 0) + if (filter->filter_info.dst_port_mask == 0) mask &= IXGBE_FTQF_DEST_PORT_MASK; - if (filter->protocol_mask == 0) + if (filter->filter_info.proto_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); + IXGBE_WRITE_REG(hw, IXGBE_DAQF(idx), filter->filter_info.dst_ip); + IXGBE_WRITE_REG(hw, IXGBE_SAQF(idx), filter->filter_info.src_ip); + IXGBE_WRITE_REG(hw, IXGBE_SDPQF(idx), sdpqf); + IXGBE_WRITE_REG(hw, IXGBE_FTQF(idx), 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); + l34timir |= (uint32_t)(filter->queue << + IXGBE_L34T_IMIR_QUEUE_SHIFT); + IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(i), l34timir); return 0; } @@ -3997,92 +4033,27 @@ ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, * * @param * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * - * @return - * - On success, zero. - * - On failure, a negative value. + * filter: the pointer of the filter will be removed. */ -static int +static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, - uint16_t index) + struct ixgbe_5tuple_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + uint16_t index = filter->index; - if (hw->mac.type != ixgbe_mac_82599EB) - return -ENOSYS; - - if (index >= IXGBE_MAX_FTQF_FILTERS) - return -EINVAL; /* filter index is out of range. */ + filter_info->fivetuple_mask[index / UINT32_BIT] &= + ~(1 << (index % UINT32_BIT)); + TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries); + rte_free(filter); 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, uint16_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 int @@ -4119,6 +4090,284 @@ ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) return 0; } +#define MAC_TYPE_FILTER_SUP(type) do {\ + if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540)\ + return -ENOTSUP;\ +} while (0) + +static inline struct ixgbe_5tuple_filter * +ixgbe_5tuple_filter_lookup(struct ixgbe_5tuple_filter_list *filter_list, + struct ixgbe_5tuple_filter_info *key) +{ + struct ixgbe_5tuple_filter *it; + + TAILQ_FOREACH(it, filter_list, entries) { + if (memcmp(key, &it->filter_info, + sizeof(struct ixgbe_5tuple_filter_info)) == 0) { + return it; + } + } + return NULL; +} + +/* translate elements in struct rte_eth_ntuple_filter to struct ixgbe_5tuple_filter_info*/ +static inline int +ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter, + struct ixgbe_5tuple_filter_info *filter_info) +{ + if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM || + filter->priority > IXGBE_5TUPLE_MAX_PRI || + filter->priority < IXGBE_5TUPLE_MIN_PRI) + return -EINVAL; + + switch (filter->dst_ip_mask) { + case UINT32_MAX: + filter_info->dst_ip_mask = 0; + filter_info->dst_ip = filter->dst_ip; + break; + case 0: + filter_info->dst_ip_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid dst_ip mask."); + return -EINVAL; + } + + switch (filter->src_ip_mask) { + case UINT32_MAX: + filter_info->src_ip_mask = 0; + filter_info->src_ip = filter->src_ip; + break; + case 0: + filter_info->src_ip_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid src_ip mask."); + return -EINVAL; + } + + switch (filter->dst_port_mask) { + case UINT16_MAX: + filter_info->dst_port_mask = 0; + filter_info->dst_port = filter->dst_port; + break; + case 0: + filter_info->dst_port_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid dst_port mask."); + return -EINVAL; + } + + switch (filter->src_port_mask) { + case UINT16_MAX: + filter_info->src_port_mask = 0; + filter_info->src_port = filter->src_port; + break; + case 0: + filter_info->src_port_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid src_port mask."); + return -EINVAL; + } + + switch (filter->proto_mask) { + case UINT8_MAX: + filter_info->proto_mask = 0; + filter_info->proto = + convert_protocol_type(filter->proto); + break; + case 0: + filter_info->proto_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid protocol mask."); + return -EINVAL; + } + + filter_info->priority = (uint8_t)filter->priority; + return 0; +} + +/* + * add or delete a ntuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * ntuple_filter: Pointer to struct rte_eth_ntuple_filter + * add: if true, add filter, if false, remove filter + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *ntuple_filter, + bool add) +{ + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct ixgbe_5tuple_filter_info filter_5tuple; + struct ixgbe_5tuple_filter *filter; + int ret; + + if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { + PMD_DRV_LOG(ERR, "only 5tuple is supported."); + return -EINVAL; + } + + memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info)); + ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); + if (ret < 0) + return ret; + + filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list, + &filter_5tuple); + if (filter != NULL && add) { + PMD_DRV_LOG(ERR, "filter exists."); + return -EEXIST; + } + if (filter == NULL && !add) { + PMD_DRV_LOG(ERR, "filter doesn't exist."); + return -ENOENT; + } + + if (add) { + filter = rte_zmalloc("ixgbe_5tuple_filter", + sizeof(struct ixgbe_5tuple_filter), 0); + if (filter == NULL) + return -ENOMEM; + (void)rte_memcpy(&filter->filter_info, + &filter_5tuple, + sizeof(struct ixgbe_5tuple_filter_info)); + filter->queue = ntuple_filter->queue; + ret = ixgbe_add_5tuple_filter(dev, filter); + if (ret < 0) { + rte_free(filter); + return ret; + } + } else + ixgbe_remove_5tuple_filter(dev, filter); + + return 0; +} + +/* + * get a ntuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * ntuple_filter: Pointer to struct rte_eth_ntuple_filter + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_get_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *ntuple_filter) +{ + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct ixgbe_5tuple_filter_info filter_5tuple; + struct ixgbe_5tuple_filter *filter; + int ret; + + if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { + PMD_DRV_LOG(ERR, "only 5tuple is supported."); + return -EINVAL; + } + + memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info)); + ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); + if (ret < 0) + return ret; + + filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list, + &filter_5tuple); + if (filter == NULL) { + PMD_DRV_LOG(ERR, "filter doesn't exist."); + return -ENOENT; + } + ntuple_filter->queue = filter->queue; + return 0; +} + +/* + * ixgbe_ntuple_filter_handle - Handle operations for ntuple filter. + * @dev: pointer to rte_eth_dev structure + * @filter_op:operation will be taken. + * @arg: a pointer to specific structure corresponding to the filter_op + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (filter_op == RTE_ETH_FILTER_NOP) + return 0; + + if (arg == NULL) { + PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", + filter_op); + return -EINVAL; + } + + switch (filter_op) { + case RTE_ETH_FILTER_ADD: + ret = ixgbe_add_del_ntuple_filter(dev, + (struct rte_eth_ntuple_filter *)arg, + TRUE); + break; + case RTE_ETH_FILTER_DELETE: + ret = ixgbe_add_del_ntuple_filter(dev, + (struct rte_eth_ntuple_filter *)arg, + FALSE); + break; + case RTE_ETH_FILTER_GET: + ret = ixgbe_get_ntuple_filter(dev, + (struct rte_eth_ntuple_filter *)arg); + break; + default: + PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); + ret = -EINVAL; + break; + } + return ret; +} + +static int +ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg) +{ + int ret = -EINVAL; + + switch (filter_type) { + case RTE_ETH_FILTER_NTUPLE: + ret = ixgbe_ntuple_filter_handle(dev, filter_op, arg); + break; + default: + PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", + filter_type); + break; + } + + return ret; +} + 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 ca99170..69f0326 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h @@ -162,6 +162,54 @@ struct ixgbe_vf_info { }; /* + * 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, +}; + +TAILQ_HEAD(ixgbe_5tuple_filter_list, ixgbe_5tuple_filter); + +struct ixgbe_5tuple_filter_info { + uint32_t dst_ip; + uint32_t src_ip; + uint16_t dst_port; + uint16_t src_port; + enum ixgbe_5tuple_protocol proto; /* l4 protocol. */ + uint8_t priority; /* seven levels (001b-111b), 111b is highest, + used when more than one filter matches. */ + uint8_t dst_ip_mask:1, /* if mask is 1b, do not compare dst ip. */ + src_ip_mask:1, /* if mask is 1b, do not compare src ip. */ + dst_port_mask:1, /* if mask is 1b, do not compare dst port. */ + src_port_mask:1, /* if mask is 1b, do not compare src port. */ + proto_mask:1; /* if mask is 1b, do not compare protocol. */ +}; + +/* 5tuple filter structure */ +struct ixgbe_5tuple_filter { + TAILQ_ENTRY(ixgbe_5tuple_filter) entries; + uint16_t index; /* the index of 5tuple filter */ + struct ixgbe_5tuple_filter_info filter_info; + uint16_t queue; /* rx queue assigned to */ +}; + +#define UINT32_BIT 32 +#define IXGBE_5TUPLE_ARRAY_SIZE \ + (RTE_ALIGN(IXGBE_MAX_FTQF_FILTERS, UINT32_BIT) / (UINT32_BIT)) + +/* + * Structure to store filters' info. + */ +struct ixgbe_filter_info { + /* Bit mask for every used 5tuple filter */ + uint32_t fivetuple_mask[IXGBE_5TUPLE_ARRAY_SIZE]; + struct ixgbe_5tuple_filter_list fivetuple_list; +}; + +/* * Structure to store private data for each driver instance (for each port). */ struct ixgbe_adapter { @@ -179,16 +227,7 @@ struct ixgbe_adapter { #ifdef RTE_NIC_BYPASS struct ixgbe_bypass_info bps; #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, + struct ixgbe_filter_info filter; }; #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\ @@ -224,6 +263,9 @@ enum ixgbe_5tuple_protocol { #define IXGBE_DEV_PRIVATE_TO_UTA(adapter) \ (&((struct ixgbe_adapter *)adapter)->uta_info) +#define IXGBE_DEV_PRIVATE_TO_FILTER_INFO(adapter) \ + (&((struct ixgbe_adapter *)adapter)->filter) + /* * RX/TX function prototypes */