net/ixgbe: fix single VLAN tag to be outer VLAN tag

Previously, a single VLAN header is treated as inner VLAN,
but generally, a single VLAN header is treated as the outer
VLAN header.
The patch fixes the ether type of a single VLAN type, and
enables configuring inner and outer TPID for double VLAN.

Fixes: 19b16e2f64 ("ethdev: add vlan type when setting ether type")

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
This commit is contained in:
Beilei Xing 2016-06-23 23:11:58 +08:00 committed by Bruce Richardson
parent 5b2d37858d
commit 2b84092427
2 changed files with 40 additions and 5 deletions

View File

@ -158,6 +158,9 @@ enum ixgbevf_xcast_modes {
IXGBEVF_XCAST_MODE_ALLMULTI,
};
#define IXGBE_EXVET_VET_EXT_SHIFT 16
#define IXGBE_DMATXCTL_VT_MASK 0xFFFF0000
static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
static int ixgbe_dev_configure(struct rte_eth_dev *dev);
@ -1599,15 +1602,47 @@ ixgbe_vlan_tpid_set(struct rte_eth_dev *dev,
struct ixgbe_hw *hw =
IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
int ret = 0;
uint32_t reg;
uint32_t qinq;
qinq = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
qinq &= IXGBE_DMATXCTL_GDV;
switch (vlan_type) {
case ETH_VLAN_TYPE_INNER:
/* Only the high 16-bits is valid */
IXGBE_WRITE_REG(hw, IXGBE_EXVET, tpid << 16);
if (qinq) {
reg = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
reg = (reg & (~IXGBE_VLNCTRL_VET)) | (uint32_t)tpid;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, reg);
reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
reg = (reg & (~IXGBE_DMATXCTL_VT_MASK))
| ((uint32_t)tpid << IXGBE_DMATXCTL_VT_SHIFT);
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
} else {
ret = -ENOTSUP;
PMD_DRV_LOG(ERR, "Inner type is not supported"
" by single VLAN");
}
break;
case ETH_VLAN_TYPE_OUTER:
if (qinq) {
/* Only the high 16-bits is valid */
IXGBE_WRITE_REG(hw, IXGBE_EXVET, (uint32_t)tpid <<
IXGBE_EXVET_VET_EXT_SHIFT);
} else {
reg = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
reg = (reg & (~IXGBE_VLNCTRL_VET)) | (uint32_t)tpid;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, reg);
reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
reg = (reg & (~IXGBE_DMATXCTL_VT_MASK))
| ((uint32_t)tpid << IXGBE_DMATXCTL_VT_SHIFT);
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg);
}
break;
default:
ret = -EINVAL;
PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type);
PMD_DRV_LOG(ERR, "Unsupported VLAN type %d", vlan_type);
break;
}

View File

@ -1157,7 +1157,7 @@ typedef int (*vlan_filter_set_t)(struct rte_eth_dev *dev,
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. */
/**< @internal set the outer/inner VLAN-TPID by an Ethernet device. */
typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask);
/**< @internal set VLAN offload function by an Ethernet device. */
@ -1443,7 +1443,7 @@ struct eth_dev_ops {
/**< Get packet types supported and identified by device*/
mtu_set_t mtu_set; /**< Set MTU. */
vlan_filter_set_t vlan_filter_set; /**< Filter VLAN Setup. */
vlan_tpid_set_t vlan_tpid_set; /**< Outer VLAN TPID Setup. */
vlan_tpid_set_t vlan_tpid_set; /**< Outer/Inner VLAN TPID Setup. */
vlan_strip_queue_set_t vlan_strip_queue_set; /**< VLAN Stripping on queue. */
vlan_offload_set_t vlan_offload_set; /**< Set VLAN Offload. */
vlan_pvid_set_t vlan_pvid_set; /**< Set port based TX VLAN insertion */