[Intel-wired-lan] [PATCH] [v1, next-queue] net: ixgbe: Fix deleting link filters for cls_u32 offloads
Samudrala, Sridhar
sridhar.samudrala at intel.com
Mon May 9 19:36:35 UTC 2016
On 5/6/2016 7:09 PM, Amritha Nambiar wrote:
> On deleting filters which are links to a child hash table, the filters
> in the child hash table must be cleared from the hardware if there
> is no link between the parent and child hash table.
>
> Verified with the following filters:
>
> # tc qdisc add dev enp5s0f1 ingress
> # ethtool -K enp5s0f1 hw-tc-offload on
>
> Create a child hash table:
> # tc filter add dev enp5s0f1 parent ffff: protocol ip prio 99 \
> handle 1: u32 divisor 1
>
> Link to the child hash table from parent hash table:
> # tc filter add dev enp5s0f1 protocol ip parent ffff: prio 99 \
> handle 800:0:10 u32 ht 800: link 1: \
> offset at 0 mask 0f00 shift 6 plus 0 eat \
> match ip protocol 6 ff match ip dst 15.0.0.1/32
>
> Add filters into child hash table:
> # tc filter add dev enp5s0f1 parent ffff: protocol ip \
> handle 1:0:2 u32 ht 1: \
> match tcp src 22 ffff action drop
> # tc filter add dev enp5s0f1 parent ffff: protocol ip \
> handle 1:0:3 u32 ht 1: \
> match tcp src 33 ffff action drop
>
> Delete link filter from parent hash table:
> # tc filter del dev enp5s0f1 parent ffff: prio 99 \
> handle 800:0:10 u32
>
> Signed-off-by: Amritha Nambiar <amritha.nambiar at intel.com>
Acked-by: Sridhar Samudrala <sridhar.samudrala at intel.com>
> ---
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 75 ++++++++++++++++++++++--
> drivers/net/ethernet/intel/ixgbe/ixgbe_model.h | 4 +
> 2 files changed, 72 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index 7bbf9b1..24a20ce 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -8308,14 +8308,50 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
> static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter,
> struct tc_cls_u32_offload *cls)
> {
> + u32 hdl = cls->knode.handle;
> u32 uhtid = TC_U32_USERHTID(cls->knode.handle);
> - u32 loc;
> - int err;
> + u32 loc = cls->knode.handle & 0xfffff;
> + int err = 0, i, j;
> + struct ixgbe_jump_table *jump = NULL;
> +
> + if (loc > IXGBE_MAX_HW_ENTRIES)
> + return -EINVAL;
>
> if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE))
> return -EINVAL;
>
> - loc = cls->knode.handle & 0xfffff;
> + /* Clear this filter in the link data it is associated with */
> + if (uhtid != 0x800) {
> + jump = adapter->jump_tables[uhtid];
> + if (jump)
> + clear_bit(loc - 1, jump->child_loc_map);
> + }
> +
> + /* Check if the filter being deleted is a link */
> + for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++) {
> + jump = adapter->jump_tables[i];
> + if (jump && jump->link_hdl == hdl) {
> + /* Delete filters in the hardware in the child hash
> + * table associated with this link
> + */
> + for (j = 0; j < IXGBE_MAX_HW_ENTRIES; j++) {
> + if (!test_bit(j, jump->child_loc_map))
> + continue;
> + spin_lock(&adapter->fdir_perfect_lock);
> + err = ixgbe_update_ethtool_fdir_entry(adapter,
> + NULL,
> + j + 1);
> + spin_unlock(&adapter->fdir_perfect_lock);
> + clear_bit(j, jump->child_loc_map);
> + }
> + /* Remove resources for this link */
> + kfree(jump->input);
> + kfree(jump->mask);
> + kfree(jump);
> + adapter->jump_tables[i] = NULL;
> + return err;
> + }
> + }
>
> spin_lock(&adapter->fdir_perfect_lock);
> err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc);
> @@ -8549,6 +8585,18 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
> if (!test_bit(link_uhtid - 1, &adapter->tables))
> return err;
>
> + /* Multiple filters as links to the same hash table are not
> + * supported. To add a new filter with the same next header
> + * but different match/jump conditions, create a new hash table
> + * and link to it.
> + */
> + if (adapter->jump_tables[link_uhtid] &&
> + (adapter->jump_tables[link_uhtid])->link_hdl) {
> + e_err(drv, "Link filter exists for link: %x\n",
> + link_uhtid);
> + return err;
> + }
> +
> for (i = 0; nexthdr[i].jump; i++) {
> if (nexthdr[i].o != cls->knode.sel->offoff ||
> nexthdr[i].s != cls->knode.sel->offshift ||
> @@ -8566,10 +8614,12 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
> mask = kzalloc(sizeof(*mask), GFP_KERNEL);
> if (!mask) {
> err = -ENOMEM;
> - goto free_input;
> + goto err_out;
> }
> jump->input = input;
> jump->mask = mask;
> + jump->link_hdl = cls->knode.handle;
> +
> err = ixgbe_clsu32_build_input(input, mask, cls,
> field_ptr, &nexthdr[i]);
> if (!err) {
> @@ -8587,7 +8637,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
> mask = kzalloc(sizeof(*mask), GFP_KERNEL);
> if (!mask) {
> err = -ENOMEM;
> - goto free_input;
> + goto err_out;
> }
>
> if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) {
> @@ -8628,14 +8678,25 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
> ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
> spin_unlock(&adapter->fdir_perfect_lock);
>
> + if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) {
> + struct ixgbe_jump_table *link = adapter->jump_tables[uhtid];
> +
> + if (test_bit(loc - 1, link->child_loc_map)) {
> + e_err(drv, "Filter: %x exists in hash table: %x\n",
> + loc, uhtid);
> + err = -EINVAL;
> + goto free_mask;
> + }
> + set_bit(loc - 1, link->child_loc_map);
> + }
> kfree(mask);
> return err;
> err_out_w_lock:
> spin_unlock(&adapter->fdir_perfect_lock);
> err_out:
> - kfree(mask);
> -free_input:
> kfree(input);
> +free_mask:
> + kfree(mask);
> free_jump:
> kfree(jump);
> return err;
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h
> index a8bed3d..538a1c54 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h
> @@ -42,8 +42,12 @@ struct ixgbe_jump_table {
> struct ixgbe_mat_field *mat;
> struct ixgbe_fdir_filter *input;
> union ixgbe_atr_input *mask;
> + u32 link_hdl;
> + unsigned long child_loc_map[32];
> };
>
> +#define IXGBE_MAX_HW_ENTRIES 2045
> +
> static inline int ixgbe_mat_prgm_sip(struct ixgbe_fdir_filter *input,
> union ixgbe_atr_input *mask,
> u32 val, u32 m)
>
More information about the Intel-wired-lan
mailing list