From 19b16e2f64420b183cb51639544679eabfca3087 Mon Sep 17 00:00:00 2001 From: Helin Zhang Date: Sat, 12 Mar 2016 00:50:57 +0800 Subject: [PATCH] ethdev: add vlan type when setting ether type In order to set ether type of VLAN for single VLAN, inner and outer VLAN, the VLAN type as an input parameter is added to 'rte_eth_dev_set_vlan_ether_type()'. In addition, corresponding changes in e1000, ixgbe and i40e are also added. It is an ABI break but ethdev library is already bumped for 16.04. Signed-off-by: Helin Zhang Acked-by: Wenzhuo Lu --- app/test-pmd/cmdline.c | 30 +++++--- app/test-pmd/config.c | 9 +-- app/test-pmd/testpmd.h | 3 +- doc/guides/rel_notes/release_16_04.rst | 5 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 11 +-- drivers/net/e1000/igb_ethdev.c | 27 +++++-- drivers/net/i40e/i40e_ethdev.c | 79 +++++++++++++++++++-- drivers/net/ixgbe/ixgbe_ethdev.c | 25 +++++-- lib/librte_ether/rte_ethdev.c | 7 +- lib/librte_ether/rte_ethdev.h | 21 +++++- lib/librte_ether/rte_ether_version.map | 1 + 11 files changed, 173 insertions(+), 45 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 81ba2bdb6f..9bd2fd94ce 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -277,8 +277,8 @@ static void cmd_help_long_parsed(void *parsed_result, " Set the VLAN QinQ (extended queue in queue)" " on a port.\n\n" - "vlan set tpid (value) (port_id)\n" - " Set the outer VLAN TPID for Packet Filtering on" + "vlan set (inner|outer) tpid (value) (port_id)\n" + " Set the VLAN TPID for Packet Filtering on" " a port\n\n" "rx_vlan add (vlan_id|all) (port_id)\n" @@ -297,10 +297,6 @@ static void cmd_help_long_parsed(void *parsed_result, " Remove a vlan_id, to the set of VLAN identifiers" "filtered for VF(s) from port_id.\n\n" - "rx_vlan set tpid (value) (port_id)\n" - " Set the outer VLAN TPID for Packet Filtering on" - " a port\n\n" - "tunnel_filter add (port_id) (outer_mac) (inner_mac) (ip_addr) " "(inner_vlan) (vxlan|nvgre) (filter_type) (tenant_id) (queue_id)\n" " add a tunnel filter of a port.\n\n" @@ -2747,6 +2743,7 @@ cmdline_parse_inst_t cmd_rx_vlan_filter_all = { struct cmd_vlan_offload_result { cmdline_fixed_string_t vlan; cmdline_fixed_string_t set; + cmdline_fixed_string_t vlan_type; cmdline_fixed_string_t what; cmdline_fixed_string_t on; cmdline_fixed_string_t port_id; @@ -2847,6 +2844,7 @@ cmdline_parse_inst_t cmd_vlan_offload = { struct cmd_vlan_tpid_result { cmdline_fixed_string_t vlan; cmdline_fixed_string_t set; + cmdline_fixed_string_t vlan_type; cmdline_fixed_string_t what; uint16_t tp_id; uint8_t port_id; @@ -2858,8 +2856,17 @@ cmd_vlan_tpid_parsed(void *parsed_result, __attribute__((unused)) void *data) { struct cmd_vlan_tpid_result *res = parsed_result; - vlan_tpid_set(res->port_id, res->tp_id); - return; + enum rte_vlan_type vlan_type; + + if (!strcmp(res->vlan_type, "inner")) + vlan_type = ETH_VLAN_TYPE_INNER; + else if (!strcmp(res->vlan_type, "outer")) + vlan_type = ETH_VLAN_TYPE_OUTER; + else { + printf("Unknown vlan type\n"); + return; + } + vlan_tpid_set(res->port_id, vlan_type, res->tp_id); } cmdline_parse_token_string_t cmd_vlan_tpid_vlan = @@ -2868,6 +2875,9 @@ cmdline_parse_token_string_t cmd_vlan_tpid_vlan = cmdline_parse_token_string_t cmd_vlan_tpid_set = TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, set, "set"); +cmdline_parse_token_string_t cmd_vlan_type = + TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, + vlan_type, "inner#outer"); cmdline_parse_token_string_t cmd_vlan_tpid_what = TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, what, "tpid"); @@ -2881,10 +2891,12 @@ cmdline_parse_token_num_t cmd_vlan_tpid_portid = cmdline_parse_inst_t cmd_vlan_tpid = { .f = cmd_vlan_tpid_parsed, .data = NULL, - .help_str = "set tpid tp_id port_id, set the Outer VLAN Ether type", + .help_str = "set inner|outer tpid tp_id port_id, set the VLAN " + "Ether type", .tokens = { (void *)&cmd_vlan_tpid_vlan, (void *)&cmd_vlan_tpid_set, + (void *)&cmd_vlan_type, (void *)&cmd_vlan_tpid_what, (void *)&cmd_vlan_tpid_tpid, (void *)&cmd_vlan_tpid_portid, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 2970f34157..b1bbec6dc5 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1821,19 +1821,20 @@ rx_vlan_all_filter_set(portid_t port_id, int on) } void -vlan_tpid_set(portid_t port_id, uint16_t tp_id) +vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, uint16_t tp_id) { int diag; + if (port_id_is_invalid(port_id, ENABLED_WARN)) return; - diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id); + diag = rte_eth_dev_set_vlan_ether_type(port_id, vlan_type, tp_id); if (diag == 0) return; - printf("tx_vlan_tpid_set(port_pi=%d, tpid=%d) failed " + printf("tx_vlan_tpid_set(port_pi=%d, vlan_type=%d, tpid=%d) failed " "diag=%d\n", - port_id, tp_id, diag); + port_id, vlan_type, tp_id, diag); } void diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index b6189987ee..0f72ca1fa9 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -508,7 +508,8 @@ void rx_vlan_filter_set(portid_t port_id, int on); void rx_vlan_all_filter_set(portid_t port_id, int on); int rx_vft_set(portid_t port_id, uint16_t vlan_id, int on); void vlan_extend_set(portid_t port_id, int on); -void vlan_tpid_set(portid_t port_id, uint16_t tp_id); +void vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, + uint16_t tp_id); void tx_vlan_set(portid_t port_id, uint16_t vlan_id); void tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer); void tx_vlan_reset(portid_t port_id); diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst index c3fb18aa33..6e44b8b87b 100644 --- a/doc/guides/rel_notes/release_16_04.rst +++ b/doc/guides/rel_notes/release_16_04.rst @@ -70,6 +70,8 @@ This section should contain new features added in this release. Sample format: space bytes, to boost the performance. In the meanwhile, it deprecated the legacy way via reading/writing sysfile supported by kernel module igb_uio. +* **Supported ether type setting of single and double VLAN for i40e** + * **Increased number of next hops for LPM IPv4 to 2^24.** The next_hop field is extended from 8 bits to 24 bits for IPv4. @@ -178,6 +180,9 @@ This section should contain API changes. Sample format: * The fields in ethdev structure ``rte_eth_fdir_masks`` were changed to be in big endian. +* A parameter ``vlan_type`` has been added to the function + ``rte_eth_dev_set_vlan_ether_type``. + * The LPM ``next_hop`` field is extended from 8 bits to 24 bits for IPv4 while keeping ABI compatibility. diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index a520cc509c..e2b2224db6 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -498,9 +498,9 @@ Set the VLAN QinQ (extended queue in queue) on for a port:: vlan set tpid ~~~~~~~~~~~~~ -Set the outer VLAN TPID for packet filtering on a port:: +Set the inner or outer VLAN TPID for packet filtering on a port:: - testpmd> vlan set tpid (value) (port_id) + testpmd> vlan set (inner|outer) tpid (value) (port_id) .. note:: @@ -540,13 +540,6 @@ Remove a VLAN ID, from the set of VLAN identifiers filtered for VF(s) for port I testpmd> rx_vlan rm (vlan_id) port (port_id) vf (vf_mask) -rx_vlan set tpid -~~~~~~~~~~~~~~~~ - -Set the outer VLAN TPID for packet filtering on a port:: - - testpmd> rx_vlan set tpid (value) (port_id) - tunnel_filter add ~~~~~~~~~~~~~~~~~ diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index 4ed5e95b0b..2581995dae 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -125,7 +125,9 @@ static int eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); -static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id); +static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid_id); static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev); @@ -2184,15 +2186,28 @@ eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return 0; } -static void -eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid) +static int +eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t reg = ETHER_TYPE_VLAN ; + uint32_t reg = ETHER_TYPE_VLAN; + int ret = 0; + + switch (vlan_type) { + case ETH_VLAN_TYPE_INNER: + reg |= (tpid << 16); + E1000_WRITE_REG(hw, E1000_VET, reg); + break; + default: + ret = -EINVAL; + PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type); + break; + } - reg |= (tpid << 16); - E1000_WRITE_REG(hw, E1000_VET, reg); + return ret; } static void diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 7e68c61669..a2efcfb1bf 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -273,6 +273,11 @@ #define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL #define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL +#define I40E_GL_SWT_L2TAGCTRL(_i) (0x001C0A70 + ((_i) * 4)) +#define I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT 16 +#define I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK \ + I40E_MASK(0xFFFF, I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT) + /* PCI offset for querying capability */ #define PCI_DEV_CAP_REG 0xA4 /* PCI offset for enabling/disabling Extended Tag */ @@ -310,7 +315,9 @@ static void i40e_dev_info_get(struct rte_eth_dev *dev, static int i40e_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); -static void i40e_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid); +static int i40e_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid); static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, @@ -883,6 +890,20 @@ eth_i40e_dev_init(struct rte_eth_dev *dev) hw->fc.requested_mode = I40E_FC_NONE; i40e_set_fc(hw, &aq_fail, TRUE); + /* Set the global registers with default ether type value */ + ret = i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_OUTER, ETHER_TYPE_VLAN); + if (ret != I40E_SUCCESS) { + PMD_INIT_LOG(ERR, "Failed to set the default outer " + "VLAN ether type"); + goto err_setup_pf_switch; + } + ret = i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_INNER, ETHER_TYPE_VLAN); + if (ret != I40E_SUCCESS) { + PMD_INIT_LOG(ERR, "Failed to set the default outer " + "VLAN ether type"); + goto err_setup_pf_switch; + } + /* PF setup, which includes VSI setup */ ret = i40e_pf_setup(pf); if (ret) { @@ -2330,11 +2351,59 @@ i40e_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return i40e_vsi_delete_vlan(vsi, vlan_id); } -static void -i40e_vlan_tpid_set(__rte_unused struct rte_eth_dev *dev, - __rte_unused uint16_t tpid) +static int +i40e_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid) { - PMD_INIT_FUNC_TRACE(); + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint64_t reg_r = 0, reg_w = 0; + uint16_t reg_id = 0; + int ret = 0; + + switch (vlan_type) { + case ETH_VLAN_TYPE_OUTER: + reg_id = 2; + break; + case ETH_VLAN_TYPE_INNER: + reg_id = 3; + break; + default: + ret = -EINVAL; + PMD_DRV_LOG(ERR, "Unsupported vlan type %d", vlan_type); + return ret; + } + ret = i40e_aq_debug_read_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id), + ®_r, NULL); + if (ret != I40E_SUCCESS) { + PMD_DRV_LOG(ERR, "Fail to debug read from " + "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id); + ret = -EIO; + return ret; + } + PMD_DRV_LOG(DEBUG, "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: " + "0x%08"PRIx64"", reg_id, reg_r); + + reg_w = reg_r & (~(I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK)); + reg_w |= ((uint64_t)tpid << I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT); + if (reg_r == reg_w) { + ret = 0; + PMD_DRV_LOG(DEBUG, "No need to write"); + return ret; + } + + ret = i40e_aq_debug_write_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id), + reg_w, NULL); + if (ret != I40E_SUCCESS) { + ret = -EIO; + PMD_DRV_LOG(ERR, "Fail to debug write to " + "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id); + return ret; + } + PMD_DRV_LOG(DEBUG, "Debug write 0x%08"PRIx64" to " + "I40E_GL_SWT_L2TAGCTRL[%d]", reg_w, reg_id); + + return ret; } static void diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 3e6fe86dc0..dbcb5b52e6 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -172,7 +172,9 @@ static int ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int ixgbe_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); -static void ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id); +static int ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid_id); static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on); static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, @@ -1516,14 +1518,27 @@ ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) ixgbe_vlan_hw_strip_disable(dev, queue); } -static void -ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid) +static int +ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret = 0; + + switch (vlan_type) { + case ETH_VLAN_TYPE_INNER: + /* Only the high 16-bits is valid */ + IXGBE_WRITE_REG(hw, IXGBE_EXVET, tpid << 16); + break; + default: + ret = -EINVAL; + PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type); + break; + } - /* Only the high 16-bits is valid */ - IXGBE_WRITE_REG(hw, IXGBE_EXVET, tpid << 16); + return ret; } void diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 98587e155f..82e06c3d0e 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1703,16 +1703,17 @@ rte_eth_dev_set_vlan_strip_on_queue(uint8_t port_id, uint16_t rx_queue_id, int o } int -rte_eth_dev_set_vlan_ether_type(uint8_t port_id, uint16_t tpid) +rte_eth_dev_set_vlan_ether_type(uint8_t port_id, + enum rte_vlan_type vlan_type, + uint16_t tpid) { struct rte_eth_dev *dev; RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_tpid_set, -ENOTSUP); - (*dev->dev_ops->vlan_tpid_set)(dev, tpid); - return 0; + return (*dev->dev_ops->vlan_tpid_set)(dev, vlan_type, tpid); } int diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 3dab287d17..9a3a202ae5 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -350,6 +350,17 @@ struct rte_eth_rxmode { enable_lro : 1; /**< Enable LRO */ }; +/** + * VLAN types to indicate if it is for single VLAN, inner VLAN or outer VLAN. + * Note that single VLAN is treated the same as inner VLAN. + */ +enum rte_vlan_type { + ETH_VLAN_TYPE_UNKNOWN = 0, + ETH_VLAN_TYPE_INNER, /**< Single VLAN, or inner VLAN. */ + ETH_VLAN_TYPE_OUTER, /**< Outer VLAN. */ + ETH_VLAN_TYPE_MAX, +}; + /** * A structure used to configure the Receive Side Scaling (RSS) feature * of an Ethernet port. @@ -1076,8 +1087,8 @@ typedef int (*vlan_filter_set_t)(struct rte_eth_dev *dev, int on); /**< @internal filtering of a VLAN Tag Identifier by an Ethernet device. */ -typedef void (*vlan_tpid_set_t)(struct rte_eth_dev *dev, - uint16_t tpid); +typedef int (*vlan_tpid_set_t)(struct rte_eth_dev *dev, + enum rte_vlan_type type, uint16_t tpid); /**< @internal set the outer VLAN-TPID by an Ethernet device. */ typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask); @@ -2344,6 +2355,8 @@ int rte_eth_dev_set_vlan_strip_on_queue(uint8_t port_id, uint16_t rx_queue_id, * * @param port_id * The port identifier of the Ethernet device. + * @param vlan_type + * The vlan type. * @param tag_type * The Tag Protocol ID * @return @@ -2351,7 +2364,9 @@ int rte_eth_dev_set_vlan_strip_on_queue(uint8_t port_id, uint16_t rx_queue_id, * - (-ENOSUP) if hardware-assisted VLAN TPID setup is not supported. * - (-ENODEV) if *port_id* invalid. */ -int rte_eth_dev_set_vlan_ether_type(uint8_t port_id, uint16_t tag_type); +int rte_eth_dev_set_vlan_ether_type(uint8_t port_id, + enum rte_vlan_type vlan_type, + uint16_t tag_type); /** * Set VLAN offload configuration on an Ethernet device diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index 4ad934c190..2f4762cbb1 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -121,6 +121,7 @@ DPDK_2.2 { DPDK_16.04 { global: + rte_eth_dev_set_vlan_ether_type; rte_eth_tx_buffer_count_callback; rte_eth_tx_buffer_drop_callback; rte_eth_tx_buffer_init; -- 2.20.1