From 748198ae82c5202679c274f0d136caed3b229e1b Mon Sep 17 00:00:00 2001 From: Jingjing Wu Date: Mon, 12 Jan 2015 15:16:10 +0800 Subject: [PATCH] ixgbe: use generic filter control for ethertype filter This patch removes old functions which deal with ethertype filter in ixgbe driver. It also defines ixgbe_dev_filter_ctrl which is binding to filter_ctrl API, and ethertype filter can be dealt with through this new entrance. Signed-off-by: Jingjing Wu Acked-by: Helin Zhang --- lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 354 ++++++++++++++++++---------- lib/librte_pmd_ixgbe/ixgbe_ethdev.h | 13 + 2 files changed, 239 insertions(+), 128 deletions(-) diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index 3fc3738459..b58ec45e92 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -231,12 +231,6 @@ static int ixgbe_add_syn_filter(struct rte_eth_dev *dev, static int ixgbe_remove_syn_filter(struct rte_eth_dev *dev); static int ixgbe_get_syn_filter(struct rte_eth_dev *dev, struct rte_syn_filter *filter, uint16_t *rx_queue); -static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_ethertype_filter *filter, uint16_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, 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, @@ -245,6 +239,18 @@ 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 ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); +static int ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_filter *filter, + bool add); +static int ixgbe_ethertype_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg); +static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_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); /* * Define VF Stats MACRO for Non "cleared on read" register @@ -380,12 +386,10 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { .add_syn_filter = ixgbe_add_syn_filter, .remove_syn_filter = ixgbe_remove_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, + .filter_ctrl = ixgbe_dev_filter_ctrl, }; /* @@ -3774,125 +3778,6 @@ ixgbe_get_syn_filter(struct rte_eth_dev *dev, return -ENOENT; } -/* - * 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, - uint16_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; -} - -/* - * get 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, - uint16_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) { @@ -4119,6 +4004,219 @@ 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 &&\ + (type) != ixgbe_mac_X550)\ + return -ENOTSUP;\ +} while (0) + +static inline int +ixgbe_ethertype_filter_lookup(struct ixgbe_filter_info *filter_info, + uint16_t ethertype) +{ + int i; + + for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) { + if (filter_info->ethertype_filters[i] == ethertype && + (filter_info->ethertype_mask & (1 << i))) + return i; + } + return -1; +} + +static inline int +ixgbe_ethertype_filter_insert(struct ixgbe_filter_info *filter_info, + uint16_t ethertype) +{ + int i; + + for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) { + if (!(filter_info->ethertype_mask & (1 << i))) { + filter_info->ethertype_mask |= 1 << i; + filter_info->ethertype_filters[i] = ethertype; + return i; + } + } + return -1; +} + +static inline int +ixgbe_ethertype_filter_remove(struct ixgbe_filter_info *filter_info, + uint8_t idx) +{ + if (idx >= IXGBE_MAX_ETQF_FILTERS) + return -1; + filter_info->ethertype_mask &= ~(1 << idx); + filter_info->ethertype_filters[idx] = 0; + return idx; +} + +static int +ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_filter *filter, + bool add) +{ + 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); + uint32_t etqf = 0; + uint32_t etqs = 0; + int ret; + + if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM) + return -EINVAL; + + if (filter->ether_type == ETHER_TYPE_IPv4 || + filter->ether_type == ETHER_TYPE_IPv6) { + PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in" + " ethertype filter.", filter->ether_type); + return -EINVAL; + } + + if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { + PMD_DRV_LOG(ERR, "mac compare is unsupported."); + return -EINVAL; + } + if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { + PMD_DRV_LOG(ERR, "drop option is unsupported."); + return -EINVAL; + } + + ret = ixgbe_ethertype_filter_lookup(filter_info, filter->ether_type); + if (ret >= 0 && add) { + PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.", + filter->ether_type); + return -EEXIST; + } + if (ret < 0 && !add) { + PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", + filter->ether_type); + return -ENOENT; + } + + if (add) { + ret = ixgbe_ethertype_filter_insert(filter_info, + filter->ether_type); + if (ret < 0) { + PMD_DRV_LOG(ERR, "ethertype filters are full."); + return -ENOSYS; + } + etqf = IXGBE_ETQF_FILTER_EN; + etqf |= (uint32_t)filter->ether_type; + etqs |= (uint32_t)((filter->queue << + IXGBE_ETQS_RX_QUEUE_SHIFT) & + IXGBE_ETQS_RX_QUEUE); + etqs |= IXGBE_ETQS_QUEUE_EN; + } else { + ret = ixgbe_ethertype_filter_remove(filter_info, (uint8_t)ret); + if (ret < 0) + return -ENOSYS; + } + IXGBE_WRITE_REG(hw, IXGBE_ETQF(ret), etqf); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(ret), etqs); + IXGBE_WRITE_FLUSH(hw); + + return 0; +} + +static int +ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, + struct rte_eth_ethertype_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); + uint32_t etqf, etqs; + int ret; + + ret = ixgbe_ethertype_filter_lookup(filter_info, filter->ether_type); + if (ret < 0) { + PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", + filter->ether_type); + return -ENOENT; + } + + etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(ret)); + if (etqf & IXGBE_ETQF_FILTER_EN) { + etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(ret)); + filter->ether_type = etqf & IXGBE_ETQF_ETHERTYPE; + filter->flags = 0; + filter->queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> + IXGBE_ETQS_RX_QUEUE_SHIFT; + return 0; + } + return -ENOENT; +} + +/* + * ixgbe_ethertype_filter_handle - Handle operations for ethertype 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 + */ +static int +ixgbe_ethertype_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_ethertype_filter(dev, + (struct rte_eth_ethertype_filter *)arg, + TRUE); + break; + case RTE_ETH_FILTER_DELETE: + ret = ixgbe_add_del_ethertype_filter(dev, + (struct rte_eth_ethertype_filter *)arg, + FALSE); + break; + case RTE_ETH_FILTER_GET: + ret = ixgbe_get_ethertype_filter(dev, + (struct rte_eth_ethertype_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_ETHERTYPE: + ret = ixgbe_ethertype_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 730098da07..677c2570c5 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h @@ -162,6 +162,15 @@ struct ixgbe_vf_info { uint8_t api_version; }; +/* + * Structure to store filters' info. + */ +struct ixgbe_filter_info { + uint8_t ethertype_mask; /* Bit mask for every used ethertype filter */ + /* store used ethertype filters*/ + uint16_t ethertype_filters[IXGBE_MAX_ETQF_FILTERS]; +}; + /* * Structure to store private data for each driver instance (for each port). */ @@ -180,6 +189,7 @@ struct ixgbe_adapter { #ifdef RTE_NIC_BYPASS struct ixgbe_bypass_info bps; #endif /* RTE_NIC_BYPASS */ + struct ixgbe_filter_info filter; }; /* @@ -225,6 +235,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 */ -- 2.20.1