This patch adds ability to route packets according to ethertype, priority and pool to certain queue specified in rx_queue field. --- lib/librte_ether/rte_ethdev.c | 81 +++++++++++++++++++++++++ lib/librte_ether/rte_ethdev.h | 78 ++++++++++++++++++++++++ lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h | 6 ++ lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 104 ++++++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index a5727dd..5cd0148 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1194,6 +1194,87 @@ rte_eth_dev_get_vlan_offload(uint8_t port_id) return ret; } +int +rte_eth_dev_l2_etype_add_filter(uint8_t port_id, uint8_t filter_id, struct rte_eth_l2etype_filter *filter) +{ + struct rte_eth_dev *dev; + struct rte_eth_dev_info info; + + rte_eth_dev_info_get(port_id, &info); + + if (port_id >= nb_ports) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return (-ENODEV); + } + + dev = &rte_eth_devices[port_id]; + + if (filter == NULL) { + PMD_DEBUG_TRACE("Invalid filter pointer\n"); + return (-EINVAL); + } + + if(filter->rx_queue >= info.max_rx_queues) { + PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", filter->rx_queue); + return (-EINVAL); + } + + if (filter->etype == ETHER_TYPE_IPv4 || filter->etype == ETHER_TYPE_IPv6){ + PMD_DEBUG_TRACE("IP and IPv6 are not supported in ethertype filter\n"); + return (-EINVAL); + } + + if(filter->flags & ETH_L2ETYPE_POOL_EN) { + if(dev->data->dev_conf.rxmode.mq_mode < ETH_MQ_RX_VMDQ_ONLY) { + PMD_DEBUG_TRACE("Port %d is in non-VT mode\n", port_id); + return (-EINVAL); + } + if(filter->pool >= dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf.nb_queue_pools) { + PMD_DEBUG_TRACE("Invalid pool number %d\n", filter->pool); + return (-EINVAL); + } + } + + FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_etype_add_filter, -ENOTSUP); + return (*dev->dev_ops->l2_etype_add_filter)(dev, filter_id, filter); +} + +int +rte_eth_dev_l2_etype_get_filter(uint8_t port_id, uint8_t filter_id, struct rte_eth_l2etype_filter *filter) +{ + struct rte_eth_dev *dev; + + if (port_id >= nb_ports) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return (-ENODEV); + } + + dev = &rte_eth_devices[port_id]; + + if (filter == NULL) { + PMD_DEBUG_TRACE("Invalid filter pointer\n"); + return (-EINVAL); + } + + FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_etype_add_filter, -ENOTSUP); + return (*dev->dev_ops->l2_etype_get_filter)(dev, filter_id, filter); +} + +int +rte_eth_dev_l2_etype_del_filter(uint8_t port_id, uint8_t filter_id) +{ + struct rte_eth_dev *dev; + + if (port_id >= nb_ports) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return (-ENODEV); + } + + dev = &rte_eth_devices[port_id]; + + FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_etype_add_filter, -ENOTSUP); + return (*dev->dev_ops->l2_etype_del_filter)(dev, filter_id); +} int rte_eth_dev_fdir_add_signature_filter(uint8_t port_id, diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index dea7471..0e6326e 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -363,6 +363,10 @@ struct rte_eth_rss_conf { /* Definitions used for unicast hash */ #define ETH_VMDQ_NUM_UC_HASH_ARRAY 128 /**< Maximum nb. of UC hash array. */ +/* Definitions used for L2 Ether type filters */ +#define ETH_L2ETYPE_UP_EN 0x1 +#define ETH_L2ETYPE_POOL_EN 0x2 + /* Definitions used for VMDQ pool rx mode setting */ #define ETH_VMDQ_ACCEPT_UNTAG 0x0001 /**< accept untagged packets. */ #define ETH_VMDQ_ACCEPT_HASH_MC 0x0002 /**< accept packets in multicast table . */ @@ -558,6 +562,17 @@ struct rte_eth_pfc_conf { }; /** + * A structure used to configure L2 Ethertype Filters + */ +struct rte_eth_l2etype_filter { + uint16_t etype; + uint8_t priority; /**< VLAN User Priority. */ + uint8_t pool; + uint8_t flags; /**< Flags byte. */ + uint8_t rx_queue; +}; + +/** * Flow Director setting modes: none (default), signature or perfect. */ enum rte_fdir_mode { @@ -911,6 +926,15 @@ typedef uint16_t (*eth_tx_burst_t)(void *txq, uint16_t nb_pkts); /**< @internal Send output packets on a transmit queue of an Ethernet device. */ +typedef int (*l2_etype_add_filter_t)(struct rte_eth_dev *dev, uint8_t filter_id, struct rte_eth_l2etype_filter *filter); +/**< @internal Setup a new L2 Ethertype filter */ + +typedef int (*l2_etype_get_filter_t)(struct rte_eth_dev *dev, uint8_t filter_id, struct rte_eth_l2etype_filter *filter); +/**< @internal Get L2 Ethertype filter */ + +typedef int (*l2_etype_del_filter_t)(struct rte_eth_dev *dev, uint8_t filter_id); +/**< @internal Delete L2 Ethertype filter */ + typedef int (*fdir_add_signature_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr, uint8_t rx_queue); @@ -1120,6 +1144,12 @@ struct eth_dev_ops { eth_set_vf_tx_t set_vf_tx; /**< enable/disable a VF transmit */ eth_set_vf_vlan_filter_t set_vf_vlan_filter; /**< Set VF VLAN filter */ + /** Setup a L2 Ethertype filter. */ + l2_etype_add_filter_t l2_etype_add_filter; + /** Get a L2 Ethertype filter. */ + l2_etype_get_filter_t l2_etype_get_filter; + /** Delete a L2 Ethertype filter. */ + l2_etype_del_filter_t l2_etype_del_filter; /** Add a signature filter. */ fdir_add_signature_filter_t fdir_add_signature_filter; /** Update a signature filter. */ @@ -2109,6 +2139,54 @@ rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, #endif /** + * Setup L2 Ethertype queue filter + * @param port_id + * The port identifier of the Ethernet device. + * @param filter_id + * The index of filter rule. Must be in [0..7] range + * @param filter + * The pointer to the l2 ethertype structure. + * @return + * - (0) if successful. + * - (-ENOTSUP) if hardware doesn't support l2 ether type filters. + * - (-ENODEV) if *port_id* invalid. + * - (-EINVAL) if *filter* invalid + * - (-ENOENT) if *filter_id* invalid +*/ +int rte_eth_dev_l2_etype_add_filter(uint8_t port_id, uint8_t filter_id, struct rte_eth_l2etype_filter *filter); + +/** + * Get L2 Ethertype queue filter + * @param port_id + * The port identifier of the Ethernet device. + * @param filter_id + * The index of filter rule. Must be in [0..7] range + * @param filter + * The pointer to the l2 ethertype structure. + * @return + * - (0) if successful. + * - (-ENOTSUP) if hardware doesn't support l2 ether type filters. + * - (-ENODEV) if *port_id* invalid. + * - (-ENOENT) if *filter_id* rule inactive + * - (-EINVAL) if *filter* pointer is NULL or *filter_id* invalid +*/ +int rte_eth_dev_l2_etype_get_filter(uint8_t port_id, uint8_t filter_id, struct rte_eth_l2etype_filter *filter); + +/** + * Delete L2 Ethertype queue filter + * @param port_id + * The port identifier of the Ethernet device. + * @param filter_id + * The index of filter rule. Must be in [0..7] range + * @return + * - (0) if successful. + * - (-ENOTSUP) if hardware doesn't support l2 ether type filters. + * - (-ENODEV) if *port_id* invalid. + * - (-ENOENT) if *filter_id* invalid +*/ +int rte_eth_dev_l2_etype_del_filter(uint8_t port_id, uint8_t filter_id); + +/** * Setup a new signature filter rule on an Ethernet device * * @param port_id diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h index f03046f..28653d5 100644 --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h @@ -1537,6 +1537,12 @@ enum { #define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */ #define IXGBE_ETQF_POOL_ENABLE (1 << 26) /* bit 26 */ #define IXGBE_ETQF_POOL_SHIFT 20 +#define IXGBE_ETQF_POOL_MASK 0x03F00000 /* bits 25:20 */ +#define IXGBE_ETQF_UP_ENABLE (1 << 19) /* bit 19 */ +#define IXGBE_ETQF_UP_SHIFT 16 +#define IXGBE_ETQF_UP_MASK 0x00070000 /* bits 18:16 */ +#define IXGBE_ETQF_UP_NUMBER 8 +#define IXGBE_ETQF_ETYPE 0x0000FFFF /* bits 15:0 */ #define IXGBE_ETQS_RX_QUEUE 0x007F0000 /* bits 22:16 */ #define IXGBE_ETQS_RX_QUEUE_SHIFT 16 diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index e78c208..e1604e5 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -147,6 +147,10 @@ static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr, static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index); static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_config); +static int ixgbe_l2_etype_add_filter(struct rte_eth_dev *dev, uint8_t filter_id, struct rte_eth_l2etype_filter *filter); +static int ixgbe_l2_etype_get_filter(struct rte_eth_dev *dev, uint8_t filter_id, struct rte_eth_l2etype_filter *filter); +static int ixgbe_l2_etype_del_filter(struct rte_eth_dev *dev, uint8_t filter_id); + /* For Virtual Function support */ static int eth_ixgbevf_dev_init(struct eth_driver *eth_drv, struct rte_eth_dev *eth_dev); @@ -279,6 +283,9 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { .set_vf_rx = ixgbe_set_pool_rx, .set_vf_tx = ixgbe_set_pool_tx, .set_vf_vlan_filter = ixgbe_set_pool_vlan_filter, + .l2_etype_add_filter = ixgbe_l2_etype_add_filter, + .l2_etype_get_filter = ixgbe_l2_etype_get_filter, + .l2_etype_del_filter = ixgbe_l2_etype_del_filter, .fdir_add_signature_filter = ixgbe_fdir_add_signature_filter, .fdir_update_signature_filter = ixgbe_fdir_update_signature_filter, .fdir_remove_signature_filter = ixgbe_fdir_remove_signature_filter, @@ -3060,3 +3067,100 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id) return 0; } + +static int +ixgbe_l2_etype_add_filter(struct rte_eth_dev *dev, uint8_t filter_id, struct rte_eth_l2etype_filter *filter) +{ + 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(filter_id >= IXGBE_MAX_ETQF_FILTERS) + return (-ENOENT); + + etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(filter_id)); + if (etqf & IXGBE_ETQF_FILTER_EN) + return (-EINVAL); + + etqf = 0; + + if((filter->flags & ETH_L2ETYPE_UP_EN) && (filter->priority >= IXGBE_ETQF_UP_NUMBER)) + return (-EINVAL); + + etqf = filter->etype; + if (filter->flags & ETH_L2ETYPE_UP_EN) { + etqf |= IXGBE_ETQF_UP_ENABLE; + etqf |= filter->priority << IXGBE_ETQF_UP_SHIFT; + } + if (filter->flags & ETH_L2ETYPE_POOL_EN) { + if (ixgbe_vmdq_mode_check(hw) < 0) + return (-ENOTSUP); + etqf |= IXGBE_ETQF_POOL_ENABLE; + etqf |= filter->pool << IXGBE_ETQF_POOL_SHIFT; + } + etqf |= IXGBE_ETQF_FILTER_EN; + + etqs = filter->rx_queue << IXGBE_ETQS_RX_QUEUE_SHIFT; + etqs |= IXGBE_ETQS_QUEUE_EN; + + IXGBE_WRITE_REG(hw, IXGBE_ETQF(filter_id), etqf); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(filter_id), etqs); + + return 0; +} + +static int +ixgbe_l2_etype_get_filter(struct rte_eth_dev *dev, uint8_t filter_id, struct rte_eth_l2etype_filter *filter) +{ + 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(filter_id >= IXGBE_MAX_ETQF_FILTERS) + return (-EINVAL); + + etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(filter_id)); + etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(filter_id)); + + if(!(etqf & IXGBE_ETQF_FILTER_EN) | !(etqs & IXGBE_ETQS_QUEUE_EN)) + return (-ENOENT); + + filter->etype = etqf & IXGBE_ETQF_ETYPE; + filter->flags = 0; + + if (etqf & IXGBE_ETQF_UP_ENABLE) { + filter->flags = ETH_L2ETYPE_UP_EN; + filter->priority = (etqf & IXGBE_ETQF_UP_MASK) >> IXGBE_ETQF_UP_SHIFT; + } + + if (etqf & IXGBE_ETQF_POOL_ENABLE) { + filter->flags |= ETH_L2ETYPE_POOL_EN; + filter->pool = (etqf & IXGBE_ETQF_POOL_MASK) >> IXGBE_ETQF_POOL_SHIFT; + } + + filter->rx_queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT; + + return 0; +} + +static int +ixgbe_l2_etype_del_filter(struct rte_eth_dev *dev, uint8_t filter_id) +{ + struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + if (hw->mac.type != ixgbe_mac_82599EB) + return (-ENOSYS); + + if (filter_id >= IXGBE_MAX_ETQF_FILTERS) + return (-ENOENT); + + IXGBE_WRITE_REG(hw, IXGBE_ETQF(filter_id), 0); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(filter_id), 0); + + return 0; +} + -- 1.8.3.2