net/ixgbe: restore ether type filter

Add support for restoring ether type filter in SW.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Wei Dai <wei.dai@intel.com>
This commit is contained in:
Wei Zhao 2017-01-13 16:12:59 +08:00 committed by Ferruh Yigit
parent e6a410c268
commit a51f64eda3
3 changed files with 104 additions and 57 deletions

View File

@ -6473,47 +6473,6 @@ ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev,
return ret;
}
static inline int
ixgbe_ethertype_filter_lookup(struct ixgbe_filter_info *filter_info,
uint16_t ethertype)
{
int i;
for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
if (filter_info->ethertype_filters[i] == ethertype &&
(filter_info->ethertype_mask & (1 << i)))
return i;
}
return -1;
}
static inline int
ixgbe_ethertype_filter_insert(struct ixgbe_filter_info *filter_info,
uint16_t ethertype)
{
int i;
for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
if (!(filter_info->ethertype_mask & (1 << i))) {
filter_info->ethertype_mask |= 1 << i;
filter_info->ethertype_filters[i] = ethertype;
return i;
}
}
return -1;
}
static inline int
ixgbe_ethertype_filter_remove(struct ixgbe_filter_info *filter_info,
uint8_t idx)
{
if (idx >= IXGBE_MAX_ETQF_FILTERS)
return -1;
filter_info->ethertype_mask &= ~(1 << idx);
filter_info->ethertype_filters[idx] = 0;
return idx;
}
static int
ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
struct rte_eth_ethertype_filter *filter,
@ -6525,6 +6484,7 @@ ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
uint32_t etqf = 0;
uint32_t etqs = 0;
int ret;
struct ixgbe_ethertype_filter ethertype_filter;
if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM)
return -EINVAL;
@ -6558,18 +6518,22 @@ ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
}
if (add) {
ret = ixgbe_ethertype_filter_insert(filter_info,
filter->ether_type);
if (ret < 0) {
PMD_DRV_LOG(ERR, "ethertype filters are full.");
return -ENOSYS;
}
etqf = IXGBE_ETQF_FILTER_EN;
etqf |= (uint32_t)filter->ether_type;
etqs |= (uint32_t)((filter->queue <<
IXGBE_ETQS_RX_QUEUE_SHIFT) &
IXGBE_ETQS_RX_QUEUE);
etqs |= IXGBE_ETQS_QUEUE_EN;
ethertype_filter.ethertype = filter->ether_type;
ethertype_filter.etqf = etqf;
ethertype_filter.etqs = etqs;
ret = ixgbe_ethertype_filter_insert(filter_info,
&ethertype_filter);
if (ret < 0) {
PMD_DRV_LOG(ERR, "ethertype filters are full.");
return -ENOSPC;
}
} else {
ret = ixgbe_ethertype_filter_remove(filter_info, (uint8_t)ret);
if (ret < 0)
@ -8499,10 +8463,31 @@ ixgbe_ntuple_filter_restore(struct rte_eth_dev *dev)
}
}
/* restore ethernet type filter */
static inline void
ixgbe_ethertype_filter_restore(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ixgbe_filter_info *filter_info =
IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
int i;
for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
if (filter_info->ethertype_mask & (1 << i)) {
IXGBE_WRITE_REG(hw, IXGBE_ETQF(i),
filter_info->ethertype_filters[i].etqf);
IXGBE_WRITE_REG(hw, IXGBE_ETQS(i),
filter_info->ethertype_filters[i].etqs);
IXGBE_WRITE_FLUSH(hw);
}
}
}
static int
ixgbe_filter_restore(struct rte_eth_dev *dev)
{
ixgbe_ntuple_filter_restore(dev);
ixgbe_ethertype_filter_restore(dev);
return 0;
}

View File

@ -275,13 +275,19 @@ struct ixgbe_5tuple_filter {
(RTE_ALIGN(IXGBE_MAX_FTQF_FILTERS, (sizeof(uint32_t) * NBBY)) / \
(sizeof(uint32_t) * NBBY))
struct ixgbe_ethertype_filter {
uint16_t ethertype;
uint32_t etqf;
uint32_t etqs;
};
/*
* Structure to store filters' info.
*/
struct ixgbe_filter_info {
uint8_t ethertype_mask; /* Bit mask for every used ethertype filter */
/* store used ethertype filters*/
uint16_t ethertype_filters[IXGBE_MAX_ETQF_FILTERS];
struct ixgbe_ethertype_filter ethertype_filters[IXGBE_MAX_ETQF_FILTERS];
/* Bit mask for every used 5tuple filter */
uint32_t fivetuple_mask[IXGBE_5TUPLE_ARRAY_SIZE];
struct ixgbe_5tuple_filter_list fivetuple_list;
@ -536,4 +542,53 @@ int ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev,
int ixgbe_disable_sec_tx_path_generic(struct ixgbe_hw *hw);
int ixgbe_enable_sec_tx_path_generic(struct ixgbe_hw *hw);
static inline int
ixgbe_ethertype_filter_lookup(struct ixgbe_filter_info *filter_info,
uint16_t ethertype)
{
int i;
for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
if (filter_info->ethertype_filters[i].ethertype == ethertype &&
(filter_info->ethertype_mask & (1 << i)))
return i;
}
return -1;
}
static inline int
ixgbe_ethertype_filter_insert(struct ixgbe_filter_info *filter_info,
struct ixgbe_ethertype_filter *ethertype_filter)
{
int i;
for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
if (!(filter_info->ethertype_mask & (1 << i))) {
filter_info->ethertype_mask |= 1 << i;
filter_info->ethertype_filters[i].ethertype =
ethertype_filter->ethertype;
filter_info->ethertype_filters[i].etqf =
ethertype_filter->etqf;
filter_info->ethertype_filters[i].etqs =
ethertype_filter->etqs;
return i;
}
}
return -1;
}
static inline int
ixgbe_ethertype_filter_remove(struct ixgbe_filter_info *filter_info,
uint8_t idx)
{
if (idx >= IXGBE_MAX_ETQF_FILTERS)
return -1;
filter_info->ethertype_mask &= ~(1 << idx);
filter_info->ethertype_filters[idx].ethertype = 0;
filter_info->ethertype_filters[idx].etqf = 0;
filter_info->ethertype_filters[idx].etqs = 0;
return idx;
}
#endif /* _IXGBE_ETHDEV_H_ */

View File

@ -178,6 +178,7 @@ ixgbe_add_tx_flow_control_drop_filter(struct rte_eth_dev *eth_dev)
IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);
uint16_t vf_num;
int i;
struct ixgbe_ethertype_filter ethertype_filter;
if (!hw->mac.ops.set_ethertype_anti_spoofing) {
RTE_LOG(INFO, PMD, "ether type anti-spoofing is not"
@ -185,16 +186,22 @@ ixgbe_add_tx_flow_control_drop_filter(struct rte_eth_dev *eth_dev)
return;
}
/* occupy an entity of ether type filter */
for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
if (!(filter_info->ethertype_mask & (1 << i))) {
filter_info->ethertype_mask |= 1 << i;
filter_info->ethertype_filters[i] =
IXGBE_ETHERTYPE_FLOW_CTRL;
break;
}
i = ixgbe_ethertype_filter_lookup(filter_info,
IXGBE_ETHERTYPE_FLOW_CTRL);
if (i >= 0) {
RTE_LOG(ERR, PMD, "A ether type filter"
" entity for flow control already exists!\n");
return;
}
if (i == IXGBE_MAX_ETQF_FILTERS) {
ethertype_filter.ethertype = IXGBE_ETHERTYPE_FLOW_CTRL;
ethertype_filter.etqf = IXGBE_ETQF_FILTER_EN |
IXGBE_ETQF_TX_ANTISPOOF |
IXGBE_ETHERTYPE_FLOW_CTRL;
ethertype_filter.etqs = 0;
i = ixgbe_ethertype_filter_insert(filter_info,
&ethertype_filter);
if (i < 0) {
RTE_LOG(ERR, PMD, "Cannot find an unused ether type filter"
" entity for flow control.\n");
return;