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 <helin.zhang@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
This commit is contained in:
Helin Zhang 2016-03-12 00:50:57 +08:00 committed by Thomas Monjalon
parent e2366e74e0
commit 19b16e2f64
11 changed files with 173 additions and 45 deletions

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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
~~~~~~~~~~~~~~~~~

View File

@ -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;
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:
ret = -EINVAL;
PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type);
break;
}
return ret;
}
static void

View File

@ -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),
&reg_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

View File

@ -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;
/* 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:
ret = -EINVAL;
PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type);
break;
}
return ret;
}
void

View File

@ -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

View File

@ -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

View File

@ -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;