@@ -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,
@@ -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
@@ -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);
@@ -125,6 +125,10 @@ This section should contain new features added in this release. Sample format:
Af_packet device can now be detached using API, like other PMD devices.
+* **Added modifying ether type of both single and double VLAN for i40e**
+
+ Versioning mechanism was introduced, to avoid any ABI issue.
+
Resolved Issues
---------------
@@ -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
~~~~~~~~~~~~~~~~~
@@ -126,7 +126,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 void 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);
@@ -2194,14 +2196,23 @@ 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)
+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;
- reg |= (tpid << 16);
- E1000_WRITE_REG(hw, E1000_VET, reg);
+ switch (vlan_type) {
+ case ETH_VLAN_TYPE_INNER:
+ reg |= (tpid << 16);
+ E1000_WRITE_REG(hw, E1000_VET, reg);
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type);
+ break;
+ }
}
static void
@@ -266,6 +266,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)
+
static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev);
static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev);
static int i40e_dev_configure(struct rte_eth_dev *dev);
@@ -292,7 +297,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 void 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,
@@ -2313,10 +2320,52 @@ i40e_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
}
static void
-i40e_vlan_tpid_set(__rte_unused struct rte_eth_dev *dev,
- __rte_unused uint16_t tpid)
+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;
+
+ switch (vlan_type) {
+ case ETH_VLAN_TYPE_OUTER:
+ reg_id = 2;
+ break;
+ case ETH_VLAN_TYPE_INNER:
+ reg_id = 3;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported vlan type %d", vlan_type);
+ return;
+ }
+ 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);
+ return;
+ }
+ 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) {
+ PMD_DRV_LOG(DEBUG, "No need to write");
+ return;
+ }
+
+ ret = i40e_aq_debug_write_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id),
+ reg_w, NULL);
+ if (ret != I40E_SUCCESS) {
+ PMD_DRV_LOG(ERR, "Fail to debug write to "
+ "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
+ return;
+ }
+ PMD_DRV_LOG(DEBUG, "Debug write 0x%08"PRIx64" to "
+ "I40E_GL_SWT_L2TAGCTRL[%d]", reg_w, reg_id);
}
static void
@@ -7332,11 +7381,17 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
static void
i40e_hw_init(struct i40e_hw *hw)
{
+ struct rte_eth_dev *dev = ((struct i40e_adapter *)(hw->back))->eth_dev;
+
/* clear the PF Queue Filter control register */
i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, 0);
/* Disable symmetric hash per port */
i40e_set_symmetric_hash_enable_per_port(hw, 0);
+
+ /* Set the global registers with default ether type value */
+ i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_OUTER, ETHER_TYPE_VLAN);
+ i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_INNER, ETHER_TYPE_VLAN);
}
enum i40e_filter_pctype
@@ -178,7 +178,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 void 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,
@@ -1543,13 +1545,22 @@ ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on)
}
static void
-ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid)
+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);
- /* Only the high 16-bits is valid */
- IXGBE_WRITE_REG(hw, IXGBE_EXVET, tpid << 16);
+ 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:
+ PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type);
+ break;
+ }
}
void
@@ -65,6 +65,7 @@
#include <rte_errno.h>
#include <rte_spinlock.h>
#include <rte_string_fns.h>
+#include <rte_compat.h>
#include "rte_ether.h"
#include "rte_ethdev.h"
@@ -1697,17 +1698,37 @@ 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_v22(uint8_t port_id, 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);
+ (*dev->dev_ops->vlan_tpid_set)(dev, ETH_VLAN_TYPE_INNER, tpid);
return 0;
}
+VERSION_SYMBOL(rte_eth_dev_set_vlan_ether_type, _v22, 2.2);
+
+int
+rte_eth_dev_set_vlan_ether_type_v1604(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, vlan_type, tpid);
+
+ return 0;
+}
+BIND_DEFAULT_SYMBOL(rte_eth_dev_set_vlan_ether_type, _v1604, 16.04);
+MAP_STATIC_SYMBOL(int rte_eth_dev_set_vlan_ether_type(uint8_t port_id,
+ enum rte_vlan_type vlan_type, uint16_t tpid),
+ rte_eth_dev_set_vlan_ether_type_v1604);
int
rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask)
@@ -351,6 +351,17 @@ struct rte_eth_rxmode {
};
/**
+ * 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.
* If not NULL, the *rss_key* pointer of the *rss_conf* structure points
@@ -1077,7 +1088,7 @@ typedef int (*vlan_filter_set_t)(struct rte_eth_dev *dev,
/**< @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);
+ 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);
@@ -2346,6 +2357,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.
+ * @vlan_type
+ * The vlan type.
* @param tag_type
* The Tag Protocol ID
* @return
@@ -2353,7 +2366,13 @@ 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);
+int rte_eth_dev_set_vlan_ether_type_v22(uint8_t port_id, uint16_t tag_type);
+int rte_eth_dev_set_vlan_ether_type_v1604(uint8_t port_id,
+ enum rte_vlan_type vlan_type,
+ uint16_t tag_type);
/**
* Set VLAN offload configuration on an Ethernet device
@@ -117,3 +117,10 @@ DPDK_2.2 {
local: *;
};
+
+DPDK_16.04 {
+ global:
+
+ rte_eth_dev_set_vlan_ether_type;
+
+} DPDK_2.2;