From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lb0-f177.google.com (mail-lb0-f177.google.com [209.85.217.177]) by dpdk.org (Postfix) with ESMTP id B7EED688F for ; Wed, 4 Jun 2014 17:19:51 +0200 (CEST) Received: by mail-lb0-f177.google.com with SMTP id s7so4410259lbd.36 for ; Wed, 04 Jun 2014 08:20:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=53IGDfDZQMED2X0BoiolQOd4xy9fe1FCMdxJ2TA7kwQ=; b=TRBpWc5S7clJ5PyzsjviSgFjN1custTlAuveM2AkGLcCDKbyNpKz8/Ny2KdYsSfX2H Mqgvfh7TeWWuUuJlnv0LlbA9uoMq+31OZupviNigBTwILAC6umxOtBlnpIEVv/NQXVvD ATo5aVufV512Rxx9YBnsBwpglBTjK3NzGjup56j/dgxg69C8H4ci1JxXcq2uVFzVJV74 mpokSqU/X25ZLrdXpYxwmVvVBlE2ZJt+LiMovb3zqcdphsOFt+FtJz8wwEVCMIuwdn6R osfAV1qltlXcxMIUX/2sl6d4MB/FSw5b6rbbMR5xRETdCzzc2UHnHpJgc9M5HcMhRd7e 9sbw== X-Received: by 10.152.19.195 with SMTP id h3mr15499456lae.47.1401895204502; Wed, 04 Jun 2014 08:20:04 -0700 (PDT) Received: from hst119.rambler.ru (offcarp-nat.rambler.ru. [81.19.64.46]) by mx.google.com with ESMTPSA id b6sm2419863laa.20.2014.06.04.08.20.03 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 04 Jun 2014 08:20:03 -0700 (PDT) From: Vladimir Medvedkin To: dev@dpdk.org Date: Wed, 4 Jun 2014 11:18:40 -0400 Message-Id: <1401895122-7895-2-git-send-email-medvedkinv@gmail.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1401895122-7895-1-git-send-email-medvedkinv@gmail.com> References: <1401895122-7895-1-git-send-email-medvedkinv@gmail.com> Subject: [dpdk-dev] [PATCH v2 1/3] ixgbe: Add L2 ethertype filter for ixgbe 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: Wed, 04 Jun 2014 15:19:52 -0000 This patch adds ability to route packets according to ethertype, priority and pool to certain queue specified in rx_queue field. Signed-off-by: Vladimir Medvedkin --- 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 | 103 ++++++++++++++++++++++++++++++++ 4 files changed, 268 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index a5727dd..ad19817 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..2db6fe5 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,99 @@ 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