ACK: [PATCH][Xenial] vlan: Propagate MAC address to VLANs

Colin Ian King colin.king at canonical.com
Thu May 18 09:55:32 UTC 2017


On 12/05/17 14:34, Kleber Sacilotto de Souza wrote:
> From: Mike Manning <mmanning at brocade.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1682871
> 
> The MAC address of the physical interface is only copied to the VLAN
> when it is first created, resulting in an inconsistency after MAC
> address changes of only newly created VLANs having an up-to-date MAC.
> 
> The VLANs should continue inheriting the MAC address of the physical
> interface until the VLAN MAC address is explicitly set to any value.
> This allows IPv6 EUI64 addresses for the VLAN to reflect any changes
> to the MAC of the physical interface and thus for DAD to behave as
> expected.
> 
> Signed-off-by: Mike Manning <mmanning at brocade.com>
> Signed-off-by: David S. Miller <davem at davemloft.net>
> (cherry picked from commit 308453aa9156a3b8ee382c0949befb507a32b0c1)
> Signed-off-by: Kleber Sacilotto de Souza <kleber.souza at canonical.com>
> ---
>  net/8021q/vlan.c     |  5 +++++
>  net/8021q/vlan.h     |  2 ++
>  net/8021q/vlan_dev.c | 20 +++++++++++++++++---
>  3 files changed, 24 insertions(+), 3 deletions(-)
> 
> diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
> index ad8d6e6b87ca..44cdfff853f4 100644
> --- a/net/8021q/vlan.c
> +++ b/net/8021q/vlan.c
> @@ -291,6 +291,10 @@ static void vlan_sync_address(struct net_device *dev,
>  	if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
>  		return;
>  
> +	/* vlan continues to inherit address of lower device */
> +	if (vlan_dev_inherit_address(vlandev, dev))
> +		goto out;
> +
>  	/* vlan address was different from the old address and is equal to
>  	 * the new address */
>  	if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
> @@ -303,6 +307,7 @@ static void vlan_sync_address(struct net_device *dev,
>  	    !ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
>  		dev_uc_add(dev, vlandev->dev_addr);
>  
> +out:
>  	ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
>  }
>  
> diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
> index 9d010a09ab98..cc1557978066 100644
> --- a/net/8021q/vlan.h
> +++ b/net/8021q/vlan.h
> @@ -109,6 +109,8 @@ int vlan_check_real_dev(struct net_device *real_dev,
>  void vlan_setup(struct net_device *dev);
>  int register_vlan_dev(struct net_device *dev);
>  void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
> +bool vlan_dev_inherit_address(struct net_device *dev,
> +			      struct net_device *real_dev);
>  
>  static inline u32 vlan_get_ingress_priority(struct net_device *dev,
>  					    u16 vlan_tci)
> diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
> index c2bf37fa19cf..f4d0aa3accad 100644
> --- a/net/8021q/vlan_dev.c
> +++ b/net/8021q/vlan_dev.c
> @@ -244,6 +244,17 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
>  	strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23);
>  }
>  
> +bool vlan_dev_inherit_address(struct net_device *dev,
> +			      struct net_device *real_dev)
> +{
> +	if (dev->addr_assign_type != NET_ADDR_STOLEN)
> +		return false;
> +
> +	ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
> +	call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
> +	return true;
> +}
> +
>  static int vlan_dev_open(struct net_device *dev)
>  {
>  	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
> @@ -254,7 +265,8 @@ static int vlan_dev_open(struct net_device *dev)
>  	    !(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
>  		return -ENETDOWN;
>  
> -	if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) {
> +	if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) &&
> +	    !vlan_dev_inherit_address(dev, real_dev)) {
>  		err = dev_uc_add(real_dev, dev->dev_addr);
>  		if (err < 0)
>  			goto out;
> @@ -558,8 +570,10 @@ static int vlan_dev_init(struct net_device *dev)
>  	/* ipv6 shared card related stuff */
>  	dev->dev_id = real_dev->dev_id;
>  
> -	if (is_zero_ether_addr(dev->dev_addr))
> -		eth_hw_addr_inherit(dev, real_dev);
> +	if (is_zero_ether_addr(dev->dev_addr)) {
> +		ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
> +		dev->addr_assign_type = NET_ADDR_STOLEN;
> +	}
>  	if (is_zero_ether_addr(dev->broadcast))
>  		memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
>  
> 
Upstream cherry pick and SRU has good test results.

Acked-by: Colin Ian King <colin.king at canonical.com>




More information about the kernel-team mailing list