On 06/17/2017 12:35 AM, Girish Moodalbail wrote:
> Sorry, it took sometime to wrap around this patch series since they all 
> change one file
> and at times the same function :).
> 
> 
> On 6/16/17 6:36 AM, Vladislav Yasevich wrote:
>> Passthru macvlans directly change the mac address of the lower
>> level device.  That's OK, but after the macvlan is deleted,
>> the lower device is left with changed address and one needs to
>> reboot to bring back the origina HW addresses.
> 
> s/origina/original/
> 
>>
>> This scenario is actually quite common with passthru macvtap devices.
>>
>> This patch attempts to solve this, by storing the mac address
>> of the lower device in macvlan_port structure and keeping track of
>> it through the changes.
>>
>> After this patch, any changes to the lower device mac address
>> done trough the macvlan device, will be reverted back.  Any
>> changes done directly to the lower device mac address will be kept.
>>
>> Signed-off-by: Vladislav Yasevich <vyase...@redhat.com>
>> ---
>>  drivers/net/macvlan.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
>>  1 file changed, 44 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
>> index eb956ff..c551165 100644
>> --- a/drivers/net/macvlan.c
>> +++ b/drivers/net/macvlan.c
>> @@ -40,6 +40,7 @@
>>  #define MACVLAN_BC_QUEUE_LEN    1000
>>
>>  #define MACVLAN_F_PASSTHRU    1
>> +#define MACVLAN_F_ADDRCHANGE    2
>>
>>  struct macvlan_port {
>>      struct net_device    *dev;
>> @@ -51,6 +52,7 @@ struct macvlan_port {
>>      int            count;
>>      struct hlist_head    vlan_source_hash[MACVLAN_HASH_SIZE];
>>      DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
>> +    unsigned char           perm_addr[ETH_ALEN];
>>  };
>>
>>  struct macvlan_source_entry {
>> @@ -78,6 +80,21 @@ static inline void macvlan_set_passthru(struct 
>> macvlan_port *port)
>>      port->flags |= MACVLAN_F_PASSTHRU;
>>  }
>>
>> +static inline bool macvlan_addr_change(const struct macvlan_port *port)
>> +{
>> +    return port->flags & MACVLAN_F_ADDRCHANGE;
>> +}
>> +
>> +static inline void macvlan_set_addr_change(struct macvlan_port *port)
>> +{
>> +    port->flags |= MACVLAN_F_ADDRCHANGE;
>> +}
>> +
>> +static inline void macvlan_clear_addr_change(struct macvlan_port *port)
>> +{
>> +    port->flags &= ~MACVLAN_F_ADDRCHANGE;
>> +}
>> +
>>  /* Hash Ethernet address */
>>  static u32 macvlan_eth_hash(const unsigned char *addr)
>>  {
>> @@ -193,11 +210,11 @@ static void macvlan_hash_change_addr(struct 
>> macvlan_dev *vlan,
>>  static bool macvlan_addr_busy(const struct macvlan_port *port,
>>                    const unsigned char *addr)
>>  {
>> -    /* Test to see if the specified multicast address is
>> +    /* Test to see if the specified address is
>>       * currently in use by the underlying device or
>>       * another macvlan.
>>       */
>> -    if (!macvlan_passthru(port) &&
>> +    if (!macvlan_passthru(port) && !macvlan_addr_change(port) &&
>>          ether_addr_equal_64bits(port->dev->dev_addr, addr))
>>          return true;
>>
>> @@ -685,6 +702,7 @@ static int macvlan_sync_address(struct net_device *dev, 
>> unsigned
>> char *addr)
>>  {
>>      struct macvlan_dev *vlan = netdev_priv(dev);
>>      struct net_device *lowerdev = vlan->lowerdev;
>> +    struct macvlan_port *port = vlan->port;
>>      int err;
>>
>>      if (!(dev->flags & IFF_UP)) {
>> @@ -695,7 +713,7 @@ static int macvlan_sync_address(struct net_device *dev, 
>> unsigned
>> char *addr)
>>          if (macvlan_addr_busy(vlan->port, addr))
>>              return -EBUSY;
>>
>> -        if (!macvlan_passthru(vlan->port)) {
>> +        if (!macvlan_passthru(port)) {
>>              err = dev_uc_add(lowerdev, addr);
>>              if (err)
>>                  return err;
>> @@ -705,6 +723,15 @@ static int macvlan_sync_address(struct net_device *dev, 
>> unsigned
>> char *addr)
>>
>>          macvlan_hash_change_addr(vlan, addr);
>>      }
>> +    if (macvlan_passthru(port) && !macvlan_addr_change(port)) {
>> +        /* Since addr_change isn't set, we are here due to lower
>> +         * device change.  Save the lower-dev address so we can
>> +         * restore it later.
>> +         */
>> +        ether_addr_copy(vlan->port->perm_addr,
>> +                dev->dev_addr);
> 
> Did you meant to copy `addr' here? Since dev->dev_addr is that of the macvlan 
> device
> whilst `addr' is from the lower parent device.
> 

At this point, it doesn't really matter since dev_addr has already been set in
hash_change_addr().  However, I see your point, and the intent would be 
clarified
if I used lower_dev->addr.

Thanks
-vlad
> 
> Thanks,
> ~Girish
> 
> 

Reply via email to