Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Shannon Nelson <sln@onemain.com>
To: intel-wired-lan@osuosl.org
Subject: [Intel-wired-lan] [next PATCH S38 6/7] i40e: refactor rx filter handling
Date: Wed, 15 Jun 2016 19:28:45 -0700	[thread overview]
Message-ID: <57620EDD.2070407@onemain.com> (raw)
In-Reply-To: <1466034139-11828-7-git-send-email-bimmy.pujari@intel.com>



On 06/15/2016 04:42 PM, Bimmy Pujari wrote:
> From: Mitch Williams <mitch.a.williams@intel.com>
>
> Properly track filter adds and deletes so the driver doesn't lose filters
> during resets and up/down cycles. Add a tracking mechanism so that the
> driver knows when to enter and leave promiscuous mode.

Thanks, this was sorely needed.

>
> Implement a simple state machine so the driver can track the status of each
> filter throughout its lifecycle. Properly manage the overflow promiscuous
> state for the each VSI, and provide a way for the driver to detect when to
> exit overflow promiscuous mode.
>
> Remove all possible default MAC filters that the firmware may have set up
> so that the driver can manage these correctly, particularly when VLANs come
> into play.
>
> Finally, add the state of each filter to debugfs output so we can see what's
> going on inside the driver's pointy little head
>
> Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
> Change-ID: I97c5e366fac2254fa01eaff4f65c0af61dcf2e1f
> ---
> Testing Hints : Add many filters. Remove many filters. Reset. Change

Some concept for "many" would be useful here.  How many will it take to 
trip the thing into promiscuous mode given 1 port or 4 ports or some 
number of VFs running?

> MAC address. Reset some more. Do VLANish stuff Check debugfs to make
> sure filter count and state are as expected.
>
>   drivers/net/ethernet/intel/i40e/i40e.h         |  14 +-
>   drivers/net/ethernet/intel/i40e/i40e_debugfs.c |  16 +-
>   drivers/net/ethernet/intel/i40e/i40e_main.c    | 513 +++++++++++--------------
>   3 files changed, 257 insertions(+), 286 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
> index e83fc8a..2a88291 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e.h
> +++ b/drivers/net/ethernet/intel/i40e/i40e.h
> @@ -448,6 +448,14 @@ struct i40e_pf {
>   	u16 phy_led_val;
>   };
>   
> +enum i40e_filter_state {
> +	I40E_FILTER_INVALID = 0,	/* Invalid state */
> +	I40E_FILTER_NEW,		/* New, not sent to FW yet */
> +	I40E_FILTER_ACTIVE,		/* Added to switch by FW */
> +	I40E_FILTER_FAILED,		/* Rejected by FW */
> +	I40E_FILTER_REMOVE,		/* To be removed */
> +/* There is no 'removed' state; the filter struct is freed */
> +};
>   struct i40e_mac_filter {
>   	struct list_head list;
>   	u8 macaddr[ETH_ALEN];
> @@ -456,8 +464,7 @@ struct i40e_mac_filter {
>   	u8 counter;		/* number of instances of this filter */
>   	bool is_vf;		/* filter belongs to a VF */
>   	bool is_netdev;		/* filter belongs to a netdev */
> -	bool changed;		/* filter needs to be sync'd to the HW */
> -	bool is_laa;		/* filter is a Locally Administered Address */

So you're dumping LAA support?  Or is this extra work no longer needed?  
I would have expected some discussion of this in the commit notes.

> +	enum i40e_filter_state state;
>   };
>   
>   struct i40e_veb {
> @@ -523,6 +530,9 @@ struct i40e_vsi {
>   	struct i40e_ring **rx_rings;
>   	struct i40e_ring **tx_rings;
>   
> +	u32  active_filters;
> +	u32  promisc_threshold;
> +
>   	u16 work_limit;
>   	u16 int_rate_limit;  /* value in usecs */
>   
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
> index e6af8c8..05cf9a7 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
> @@ -116,6 +116,14 @@ static ssize_t i40e_dbg_command_read(struct file *filp, char __user *buffer,
>   	return len;
>   }
>   
> +static char *i40e_filter_state_string[] = {
> +	"INVALID",
> +	"NEW",
> +	"ACTIVE",
> +	"FAILED",
> +	"REMOVE",
> +};
> +
>   /**
>    * i40e_dbg_dump_vsi_seid - handles dump vsi seid write into command datum
>    * @pf: the i40e_pf created in command write
> @@ -160,10 +168,14 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
>   			 pf->hw.mac.port_addr);
>   	list_for_each_entry(f, &vsi->mac_filter_list, list) {
>   		dev_info(&pf->pdev->dev,
> -			 "    mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d\n",
> +			 "    mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d, state %s\n",
>   			 f->macaddr, f->vlan, f->is_netdev, f->is_vf,
> -			 f->counter);
> +			 f->counter, i40e_filter_state_string[f->state]);
>   	}
> +	dev_info(&pf->pdev->dev, "    active_filters %d, promisc_threshold %d, overflow promisc %s\n",
> +		 vsi->active_filters, vsi->promisc_threshold,
> +		 (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?
> +		  "ON" : "OFF"));
>   	nstat = i40e_get_vsi_stats_struct(vsi);
>   	dev_info(&pf->pdev->dev,
>   		 "    net_stats: rx_packets = %lu, rx_bytes = %lu, rx_errors = %lu, rx_dropped = %lu\n",
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index 0898c9d..fe4aa9c 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -1279,8 +1279,9 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
>   		    (is_vf == f->is_vf) &&
>   		    (is_netdev == f->is_netdev)) {
>   			f->counter--;
> -			f->changed = true;
>   			changed = 1;
> +			if (f->counter == 0)
> +				f->state = I40E_FILTER_REMOVE;
>   		}
>   	}
>   	if (changed) {
> @@ -1296,29 +1297,32 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
>    * @vsi: the PF Main VSI - inappropriate for any other VSI
>    * @macaddr: the MAC address
>    *
> - * Some older firmware configurations set up a default promiscuous VLAN
> - * filter that needs to be removed.
> + * Remove whatever filter the firmware set up so the driver can manage
> + * its own filtering intelligently.
>    **/
> -static int i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
> +static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
>   {
>   	struct i40e_aqc_remove_macvlan_element_data element;
>   	struct i40e_pf *pf = vsi->back;
> -	i40e_status ret;
>   
>   	/* Only appropriate for the PF main VSI */
>   	if (vsi->type != I40E_VSI_MAIN)
> -		return -EINVAL;
> +		return;
>   
>   	memset(&element, 0, sizeof(element));
>   	ether_addr_copy(element.mac_addr, macaddr);
>   	element.vlan_tag = 0;
> -	element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
> -			I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
> -	ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
> -	if (ret)
> -		return -ENOENT;
> +	/* Ignore error returns, some firmware does it this way... */
> +	element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
> +	i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
>   
> -	return 0;
> +	memset(&element, 0, sizeof(element));
> +	ether_addr_copy(element.mac_addr, macaddr);
> +	element.vlan_tag = 0;
> +	/* ...and some firmware does it this way. */
> +	element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
> +			I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
> +	i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
>   }
>   
>   /**
> @@ -1339,6 +1343,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
>   					bool is_vf, bool is_netdev)
>   {
>   	struct i40e_mac_filter *f;
> +	int changed = false;
>   
>   	if (!vsi || !macaddr)
>   		return NULL;
> @@ -1358,8 +1363,15 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
>   
>   		ether_addr_copy(f->macaddr, macaddr);
>   		f->vlan = vlan;
> -		f->changed = true;
> -
> +		/* If we're in overflow promisc mode, set the state directly
> +		 * to failed, so we don't bother to try sending the filter
> +		 * to the hardware.
> +		 */
> +		if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state))
> +			f->state = I40E_FILTER_FAILED;
> +		else
> +			f->state = I40E_FILTER_NEW;
> +		changed = true;
>   		INIT_LIST_HEAD(&f->list);
>   		list_add_tail(&f->list, &vsi->mac_filter_list);
>   	}
> @@ -1379,10 +1391,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
>   		f->counter++;
>   	}
>   
> -	/* changed tells sync_filters_subtask to
> -	 * push the filter down to the firmware
> -	 */
> -	if (f->changed) {
> +	if (changed) {
>   		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
>   		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
>   	}
> @@ -1401,6 +1410,9 @@ add_filter_out:
>    *
>    * NOTE: This function is expected to be called with mac_filter_list_lock
>    * being held.
> + * ANOTHER NOTE: This function MUST be called from within the context of
> + * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
> + * instead of list_for_each_entry().
>    **/
>   void i40e_del_filter(struct i40e_vsi *vsi,
>   		     u8 *macaddr, s16 vlan,
> @@ -1440,9 +1452,18 @@ void i40e_del_filter(struct i40e_vsi *vsi,
>   	 * remove the filter from the firmware's list
>   	 */
>   	if (f->counter == 0) {
> -		f->changed = true;
> -		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
> -		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
> +		if ((f->state == I40E_FILTER_FAILED) ||
> +		    (f->state == I40E_FILTER_NEW)) {
> +			/* this one never got added by the FW. Just remove it,
> +			 * no need to sync anything.
> +			 */
> +			list_del(&f->list);
> +			kfree(f);
> +		} else {
> +			f->state = I40E_FILTER_REMOVE;
> +			vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
> +			vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
> +		}
>   	}
>   }
>   
> @@ -1464,7 +1485,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
>   	struct i40e_pf *pf = vsi->back;
>   	struct i40e_hw *hw = &pf->hw;
>   	struct sockaddr *addr = p;
> -	struct i40e_mac_filter *f;
>   
>   	if (!is_valid_ether_addr(addr->sa_data))
>   		return -EADDRNOTAVAIL;
> @@ -1485,50 +1505,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
>   	else
>   		netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
>   
> -	if (vsi->type == I40E_VSI_MAIN) {
> -		i40e_status ret;
> -
> -		ret = i40e_aq_mac_address_write(&vsi->back->hw,
> -						I40E_AQC_WRITE_TYPE_LAA_WOL,
> -						addr->sa_data, NULL);
> -		if (ret) {
> -			netdev_info(netdev,
> -				    "Addr change for Main VSI failed: %d\n",
> -				    ret);
> -			return -EADDRNOTAVAIL;
> -		}
> -	}
> -
> -	if (ether_addr_equal(netdev->dev_addr, hw->mac.addr)) {
> -		struct i40e_aqc_remove_macvlan_element_data element;
> -
> -		memset(&element, 0, sizeof(element));
> -		ether_addr_copy(element.mac_addr, netdev->dev_addr);
> -		element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
> -		i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
> -	} else {
> -		spin_lock_bh(&vsi->mac_filter_list_lock);
> -		i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
> -				false, false);
> -		spin_unlock_bh(&vsi->mac_filter_list_lock);
> -	}
> -
> -	if (ether_addr_equal(addr->sa_data, hw->mac.addr)) {
> -		struct i40e_aqc_add_macvlan_element_data element;
> -
> -		memset(&element, 0, sizeof(element));
> -		ether_addr_copy(element.mac_addr, hw->mac.addr);
> -		element.flags = cpu_to_le16(I40E_AQC_MACVLAN_ADD_PERFECT_MATCH);
> -		i40e_aq_add_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
> -	} else {
> -		spin_lock_bh(&vsi->mac_filter_list_lock);
> -		f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY,
> -				    false, false);
> -		if (f)
> -			f->is_laa = true;
> -		spin_unlock_bh(&vsi->mac_filter_list_lock);
> -	}
> -
> +	spin_lock_bh(&vsi->mac_filter_list_lock);
> +	i40e_del_mac_all_vlan(vsi, netdev->dev_addr, false, true);
> +	i40e_put_mac_in_vlan(vsi, addr->sa_data, false, true);
> +	spin_unlock_bh(&vsi->mac_filter_list_lock);
>   	ether_addr_copy(netdev->dev_addr, addr->sa_data);
>   
>   	/* schedule our worker thread which will take care of
> @@ -1761,28 +1741,6 @@ bottom_of_search_loop:
>   }
>   
>   /**
> - * i40e_mac_filter_entry_clone - Clones a MAC filter entry
> - * @src: source MAC filter entry to be clones
> - *
> - * Returns the pointer to newly cloned MAC filter entry or NULL
> - * in case of error
> - **/
> -static struct i40e_mac_filter *i40e_mac_filter_entry_clone(
> -					struct i40e_mac_filter *src)
> -{
> -	struct i40e_mac_filter *f;
> -
> -	f = kzalloc(sizeof(*f), GFP_ATOMIC);
> -	if (!f)
> -		return NULL;
> -	*f = *src;
> -
> -	INIT_LIST_HEAD(&f->list);
> -
> -	return f;
> -}
> -
> -/**
>    * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries
>    * @vsi: pointer to vsi struct
>    * @from: Pointer to list which contains MAC filter entries - changes to
> @@ -1796,41 +1754,61 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
>   	struct i40e_mac_filter *f, *ftmp;
>   
>   	list_for_each_entry_safe(f, ftmp, from, list) {
> -		f->changed = true;
>   		/* Move the element back into MAC filter list*/
>   		list_move_tail(&f->list, &vsi->mac_filter_list);
>   	}
>   }
>   
>   /**
> - * i40e_undo_add_filter_entries - Undo the changes made to MAC filter entries
> - * @vsi: pointer to vsi struct
> + * i40e_update_filter_state - Update filter state based on return data
> + * from firmware

The description should be a single line.

sln


  reply	other threads:[~2016-06-16  2:28 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-15 23:42 [Intel-wired-lan] [next PATCH S38 0/7] i40e/i40evf updates Bimmy Pujari
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 1/7] i40e: Fix to show correct Advertised Link Modes when link is down Bimmy Pujari
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 2/7] i40e: enable VSI broadcast promiscuous mode instead of adding broadcast filter Bimmy Pujari
2016-06-16  2:07   ` Shannon Nelson
2016-06-16  4:15     ` Patil, Kiran
2016-06-16 23:09       ` Pujari, Bimmy
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 3/7] i40e/i40evf: remove useless initializer Bimmy Pujari
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 4/7] i40e: Remove device ID 0x37D4 Bimmy Pujari
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 5/7] i40evf: add hyperv dev ids Bimmy Pujari
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 6/7] i40e: refactor rx filter handling Bimmy Pujari
2016-06-16  2:28   ` Shannon Nelson [this message]
2016-06-17 15:53     ` Williams, Mitch A
2016-06-17 19:02       ` Shannon Nelson
2016-06-15 23:42 ` [Intel-wired-lan] [next PATCH S38 7/7] i40e/i40evf-bump version to 1.6.11 Bimmy Pujari

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57620EDD.2070407@onemain.com \
    --to=sln@onemain.com \
    --cc=intel-wired-lan@osuosl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox