diff options
author | Sridhar Samudrala <sridhar.samudrala@intel.com> | 2016-03-07 12:41:47 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2016-03-30 02:05:51 -0400 |
commit | 176621c964e9279c42c6b641688360e5cd0baedf (patch) | |
tree | 3c8ebadaf5d5fb3c79d544a83e63269678856600 | |
parent | 6e2a60b57a83ea134c06c5226aaff20e7e9ce221 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index f5736a3b252e..ca9c54341784 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -8192,10 +8192,17 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) | |||
8192 | static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter, | 8192 | static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter, |
8193 | struct tc_cls_u32_offload *cls) | 8193 | struct tc_cls_u32_offload *cls) |
8194 | { | 8194 | { |
8195 | u32 uhtid = TC_U32_USERHTID(cls->knode.handle); | ||
8196 | u32 loc; | ||
8195 | int err; | 8197 | int err; |
8196 | 8198 | ||
8199 | if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE)) | ||
8200 | return -EINVAL; | ||
8201 | |||
8202 | loc = cls->knode.handle & 0xfffff; | ||
8203 | |||
8197 | spin_lock(&adapter->fdir_perfect_lock); | 8204 | spin_lock(&adapter->fdir_perfect_lock); |
8198 | err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, cls->knode.handle); | 8205 | err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc); |
8199 | spin_unlock(&adapter->fdir_perfect_lock); | 8206 | spin_unlock(&adapter->fdir_perfect_lock); |
8200 | return err; | 8207 | return err; |
8201 | } | 8208 | } |
@@ -8204,20 +8211,30 @@ static int ixgbe_configure_clsu32_add_hnode(struct ixgbe_adapter *adapter, | |||
8204 | __be16 protocol, | 8211 | __be16 protocol, |
8205 | struct tc_cls_u32_offload *cls) | 8212 | struct tc_cls_u32_offload *cls) |
8206 | { | 8213 | { |
8214 | u32 uhtid = TC_U32_USERHTID(cls->hnode.handle); | ||
8215 | |||
8216 | if (uhtid >= IXGBE_MAX_LINK_HANDLE) | ||
8217 | return -EINVAL; | ||
8218 | |||
8207 | /* This ixgbe devices do not support hash tables at the moment | 8219 | /* This ixgbe devices do not support hash tables at the moment |
8208 | * so abort when given hash tables. | 8220 | * so abort when given hash tables. |
8209 | */ | 8221 | */ |
8210 | if (cls->hnode.divisor > 0) | 8222 | if (cls->hnode.divisor > 0) |
8211 | return -EINVAL; | 8223 | return -EINVAL; |
8212 | 8224 | ||
8213 | set_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables); | 8225 | set_bit(uhtid - 1, &adapter->tables); |
8214 | return 0; | 8226 | return 0; |
8215 | } | 8227 | } |
8216 | 8228 | ||
8217 | static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter, | 8229 | static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter, |
8218 | struct tc_cls_u32_offload *cls) | 8230 | struct tc_cls_u32_offload *cls) |
8219 | { | 8231 | { |
8220 | clear_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables); | 8232 | u32 uhtid = TC_U32_USERHTID(cls->hnode.handle); |
8233 | |||
8234 | if (uhtid >= IXGBE_MAX_LINK_HANDLE) | ||
8235 | return -EINVAL; | ||
8236 | |||
8237 | clear_bit(uhtid - 1, &adapter->tables); | ||
8221 | return 0; | 8238 | return 0; |
8222 | } | 8239 | } |
8223 | 8240 | ||
@@ -8235,27 +8252,29 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, | |||
8235 | #endif | 8252 | #endif |
8236 | int i, err = 0; | 8253 | int i, err = 0; |
8237 | u8 queue; | 8254 | u8 queue; |
8238 | u32 handle; | 8255 | u32 uhtid, link_uhtid; |
8239 | 8256 | ||
8240 | memset(&mask, 0, sizeof(union ixgbe_atr_input)); | 8257 | memset(&mask, 0, sizeof(union ixgbe_atr_input)); |
8241 | handle = cls->knode.handle; | 8258 | uhtid = TC_U32_USERHTID(cls->knode.handle); |
8259 | link_uhtid = TC_U32_USERHTID(cls->knode.link_handle); | ||
8242 | 8260 | ||
8243 | /* At the moment cls_u32 jumps to transport layer and skips past | 8261 | /* At the moment cls_u32 jumps to network layer and skips past |
8244 | * L2 headers. The canonical method to match L2 frames is to use | 8262 | * L2 headers. The canonical method to match L2 frames is to use |
8245 | * negative values. However this is error prone at best but really | 8263 | * negative values. However this is error prone at best but really |
8246 | * just broken because there is no way to "know" what sort of hdr | 8264 | * just broken because there is no way to "know" what sort of hdr |
8247 | * is in front of the transport layer. Fix cls_u32 to support L2 | 8265 | * is in front of the network layer. Fix cls_u32 to support L2 |
8248 | * headers when needed. | 8266 | * headers when needed. |
8249 | */ | 8267 | */ |
8250 | if (protocol != htons(ETH_P_IP)) | 8268 | if (protocol != htons(ETH_P_IP)) |
8251 | return -EINVAL; | 8269 | return -EINVAL; |
8252 | 8270 | ||
8253 | if (cls->knode.link_handle || | 8271 | if (link_uhtid) { |
8254 | cls->knode.link_handle >= IXGBE_MAX_LINK_HANDLE) { | ||
8255 | struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps; | 8272 | struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps; |
8256 | u32 uhtid = TC_U32_USERHTID(cls->knode.link_handle); | ||
8257 | 8273 | ||
8258 | if (!test_bit(uhtid, &adapter->tables)) | 8274 | if (link_uhtid >= IXGBE_MAX_LINK_HANDLE) |
8275 | return -EINVAL; | ||
8276 | |||
8277 | if (!test_bit(link_uhtid - 1, &adapter->tables)) | ||
8259 | return -EINVAL; | 8278 | return -EINVAL; |
8260 | 8279 | ||
8261 | for (i = 0; nexthdr[i].jump; i++) { | 8280 | for (i = 0; nexthdr[i].jump; i++) { |
@@ -8271,10 +8290,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, | |||
8271 | nexthdr->mask != cls->knode.sel->keys[0].mask) | 8290 | nexthdr->mask != cls->knode.sel->keys[0].mask) |
8272 | return -EINVAL; | 8291 | return -EINVAL; |
8273 | 8292 | ||
8274 | if (uhtid >= IXGBE_MAX_LINK_HANDLE) | 8293 | adapter->jump_tables[link_uhtid] = nexthdr->jump; |
8275 | return -EINVAL; | ||
8276 | |||
8277 | adapter->jump_tables[uhtid] = nexthdr->jump; | ||
8278 | } | 8294 | } |
8279 | return 0; | 8295 | return 0; |
8280 | } | 8296 | } |
@@ -8291,13 +8307,13 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, | |||
8291 | * To add support for new nodes update ixgbe_model.h parse structures | 8307 | * To add support for new nodes update ixgbe_model.h parse structures |
8292 | * this function _should_ be generic try not to hardcode values here. | 8308 | * this function _should_ be generic try not to hardcode values here. |
8293 | */ | 8309 | */ |
8294 | if (TC_U32_USERHTID(handle) == 0x800) { | 8310 | if (uhtid == 0x800) { |
8295 | field_ptr = adapter->jump_tables[0]; | 8311 | field_ptr = adapter->jump_tables[0]; |
8296 | } else { | 8312 | } else { |
8297 | if (TC_U32_USERHTID(handle) >= ARRAY_SIZE(adapter->jump_tables)) | 8313 | if (uhtid >= IXGBE_MAX_LINK_HANDLE) |
8298 | return -EINVAL; | 8314 | return -EINVAL; |
8299 | 8315 | ||
8300 | field_ptr = adapter->jump_tables[TC_U32_USERHTID(handle)]; | 8316 | field_ptr = adapter->jump_tables[uhtid]; |
8301 | } | 8317 | } |
8302 | 8318 | ||
8303 | if (!field_ptr) | 8319 | if (!field_ptr) |