ixgbe: fix error handling in TC cls_u32 offload routines
Check for handle ids when adding/deleting hash nodes OR adding/deleting filter entries and limit them to max number of links or header nodes supported(IXGBE_MAX_LINK_HANDLE). Start from bit 0 when setting hash table bit-map.(adapter->tables) Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com> Acked-by: John Fastabend <john.r.fastabend@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
6e2a60b57a
commit
176621c964
|
@ -8192,10 +8192,17 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
|
||||||
static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter,
|
static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter,
|
||||||
struct tc_cls_u32_offload *cls)
|
struct tc_cls_u32_offload *cls)
|
||||||
{
|
{
|
||||||
|
u32 uhtid = TC_U32_USERHTID(cls->knode.handle);
|
||||||
|
u32 loc;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
loc = cls->knode.handle & 0xfffff;
|
||||||
|
|
||||||
spin_lock(&adapter->fdir_perfect_lock);
|
spin_lock(&adapter->fdir_perfect_lock);
|
||||||
err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, cls->knode.handle);
|
err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc);
|
||||||
spin_unlock(&adapter->fdir_perfect_lock);
|
spin_unlock(&adapter->fdir_perfect_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -8204,20 +8211,30 @@ static int ixgbe_configure_clsu32_add_hnode(struct ixgbe_adapter *adapter,
|
||||||
__be16 protocol,
|
__be16 protocol,
|
||||||
struct tc_cls_u32_offload *cls)
|
struct tc_cls_u32_offload *cls)
|
||||||
{
|
{
|
||||||
|
u32 uhtid = TC_U32_USERHTID(cls->hnode.handle);
|
||||||
|
|
||||||
|
if (uhtid >= IXGBE_MAX_LINK_HANDLE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* This ixgbe devices do not support hash tables at the moment
|
/* This ixgbe devices do not support hash tables at the moment
|
||||||
* so abort when given hash tables.
|
* so abort when given hash tables.
|
||||||
*/
|
*/
|
||||||
if (cls->hnode.divisor > 0)
|
if (cls->hnode.divisor > 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
set_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables);
|
set_bit(uhtid - 1, &adapter->tables);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
|
static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
|
||||||
struct tc_cls_u32_offload *cls)
|
struct tc_cls_u32_offload *cls)
|
||||||
{
|
{
|
||||||
clear_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables);
|
u32 uhtid = TC_U32_USERHTID(cls->hnode.handle);
|
||||||
|
|
||||||
|
if (uhtid >= IXGBE_MAX_LINK_HANDLE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
clear_bit(uhtid - 1, &adapter->tables);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8235,27 +8252,29 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
||||||
#endif
|
#endif
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
u8 queue;
|
u8 queue;
|
||||||
u32 handle;
|
u32 uhtid, link_uhtid;
|
||||||
|
|
||||||
memset(&mask, 0, sizeof(union ixgbe_atr_input));
|
memset(&mask, 0, sizeof(union ixgbe_atr_input));
|
||||||
handle = cls->knode.handle;
|
uhtid = TC_U32_USERHTID(cls->knode.handle);
|
||||||
|
link_uhtid = TC_U32_USERHTID(cls->knode.link_handle);
|
||||||
|
|
||||||
/* At the moment cls_u32 jumps to transport layer and skips past
|
/* At the moment cls_u32 jumps to network layer and skips past
|
||||||
* L2 headers. The canonical method to match L2 frames is to use
|
* L2 headers. The canonical method to match L2 frames is to use
|
||||||
* negative values. However this is error prone at best but really
|
* negative values. However this is error prone at best but really
|
||||||
* just broken because there is no way to "know" what sort of hdr
|
* just broken because there is no way to "know" what sort of hdr
|
||||||
* is in front of the transport layer. Fix cls_u32 to support L2
|
* is in front of the network layer. Fix cls_u32 to support L2
|
||||||
* headers when needed.
|
* headers when needed.
|
||||||
*/
|
*/
|
||||||
if (protocol != htons(ETH_P_IP))
|
if (protocol != htons(ETH_P_IP))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (cls->knode.link_handle ||
|
if (link_uhtid) {
|
||||||
cls->knode.link_handle >= IXGBE_MAX_LINK_HANDLE) {
|
|
||||||
struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps;
|
struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps;
|
||||||
u32 uhtid = TC_U32_USERHTID(cls->knode.link_handle);
|
|
||||||
|
|
||||||
if (!test_bit(uhtid, &adapter->tables))
|
if (link_uhtid >= IXGBE_MAX_LINK_HANDLE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!test_bit(link_uhtid - 1, &adapter->tables))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; nexthdr[i].jump; i++) {
|
for (i = 0; nexthdr[i].jump; i++) {
|
||||||
|
@ -8271,10 +8290,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
||||||
nexthdr->mask != cls->knode.sel->keys[0].mask)
|
nexthdr->mask != cls->knode.sel->keys[0].mask)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (uhtid >= IXGBE_MAX_LINK_HANDLE)
|
adapter->jump_tables[link_uhtid] = nexthdr->jump;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
adapter->jump_tables[uhtid] = nexthdr->jump;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8291,13 +8307,13 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
||||||
* To add support for new nodes update ixgbe_model.h parse structures
|
* To add support for new nodes update ixgbe_model.h parse structures
|
||||||
* this function _should_ be generic try not to hardcode values here.
|
* this function _should_ be generic try not to hardcode values here.
|
||||||
*/
|
*/
|
||||||
if (TC_U32_USERHTID(handle) == 0x800) {
|
if (uhtid == 0x800) {
|
||||||
field_ptr = adapter->jump_tables[0];
|
field_ptr = adapter->jump_tables[0];
|
||||||
} else {
|
} else {
|
||||||
if (TC_U32_USERHTID(handle) >= ARRAY_SIZE(adapter->jump_tables))
|
if (uhtid >= IXGBE_MAX_LINK_HANDLE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
field_ptr = adapter->jump_tables[TC_U32_USERHTID(handle)];
|
field_ptr = adapter->jump_tables[uhtid];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!field_ptr)
|
if (!field_ptr)
|
||||||
|
|
Loading…
Reference in New Issue