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