Message ID | 20170512133428.18767-1-kleber.souza@canonical.com |
---|---|
State | New |
Headers | show |
On Fri, May 12, 2017 at 03:34:28PM +0200, Kleber Sacilotto de Souza wrote: > From: Mike Manning <mmanning@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@brocade.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > (cherry picked from commit 308453aa9156a3b8ee382c0949befb507a32b0c1) > Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> Clean cherry pick, positive testing. Acked-by: Seth Forshee <seth.forshee@canonical.com>
On 12/05/17 14:34, Kleber Sacilotto de Souza wrote: > From: Mike Manning <mmanning@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@brocade.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > (cherry picked from commit 308453aa9156a3b8ee382c0949befb507a32b0c1) > Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@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@canonical.com>
Applied to xenial master-next branch. Thanks. Cascardo.
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);