mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	rtnl/do_setlink(): notify when a netdev is modified
Depending on which parameters were updated, the changes were not propagated via the notifier chain and netlink. The new flag has been set only when the change did not cause a call to the notifier chain and/or to the netlink notification functions. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									90c325e3bf
								
							
						
					
					
						commit
						ba9989069f
					
				
					 1 changed files with 21 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -1482,6 +1482,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#define DO_SETLINK_MODIFIED	0x01
 | 
			
		||||
/* notify flag means notify + modified. */
 | 
			
		||||
#define DO_SETLINK_NOTIFY	0x03
 | 
			
		||||
static int do_setlink(const struct sk_buff *skb,
 | 
			
		||||
		      struct net_device *dev, struct ifinfomsg *ifm,
 | 
			
		||||
		      struct nlattr **tb, char *ifname, int status)
 | 
			
		||||
| 
						 | 
				
			
			@ -1532,7 +1534,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
		if (err < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
 | 
			
		||||
		status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
		status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tb[IFLA_ADDRESS]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1564,7 +1566,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
 | 
			
		||||
	if (tb[IFLA_GROUP]) {
 | 
			
		||||
		dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
 | 
			
		||||
		status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
		status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -1584,7 +1586,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
				    nla_len(tb[IFLA_IFALIAS]));
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
		status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tb[IFLA_BROADCAST]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1616,7 +1618,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
		unsigned long value = nla_get_u32(tb[IFLA_TXQLEN]);
 | 
			
		||||
 | 
			
		||||
		if (dev->tx_queue_len ^ value)
 | 
			
		||||
			status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
			status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
 | 
			
		||||
		dev->tx_queue_len = value;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1629,7 +1631,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
 | 
			
		||||
		write_lock_bh(&dev_base_lock);
 | 
			
		||||
		if (dev->link_mode ^ value)
 | 
			
		||||
			status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
			status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
		dev->link_mode = value;
 | 
			
		||||
		write_unlock_bh(&dev_base_lock);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1645,7 +1647,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
			err = do_setvfinfo(dev, attr);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				goto errout;
 | 
			
		||||
			status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
			status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1675,7 +1677,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
			err = ops->ndo_set_vf_port(dev, vf, port);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				goto errout;
 | 
			
		||||
			status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
			status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1693,7 +1695,7 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
			err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
		status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tb[IFLA_AF_SPEC]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1710,15 +1712,20 @@ static int do_setlink(const struct sk_buff *skb,
 | 
			
		|||
			if (err < 0)
 | 
			
		||||
				goto errout;
 | 
			
		||||
 | 
			
		||||
			status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
			status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = 0;
 | 
			
		||||
 | 
			
		||||
errout:
 | 
			
		||||
	if (err < 0 && status & DO_SETLINK_MODIFIED)
 | 
			
		||||
		net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n",
 | 
			
		||||
				     dev->name);
 | 
			
		||||
	if (status & DO_SETLINK_MODIFIED) {
 | 
			
		||||
		if (status & DO_SETLINK_NOTIFY)
 | 
			
		||||
			netdev_state_change(dev);
 | 
			
		||||
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n",
 | 
			
		||||
					     dev->name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2015,7 +2022,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 | 
			
		|||
				err = ops->changelink(dev, tb, data);
 | 
			
		||||
				if (err < 0)
 | 
			
		||||
					return err;
 | 
			
		||||
				status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
				status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2026,7 +2033,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 | 
			
		|||
							      tb, slave_data);
 | 
			
		||||
				if (err < 0)
 | 
			
		||||
					return err;
 | 
			
		||||
				status |= DO_SETLINK_MODIFIED;
 | 
			
		||||
				status |= DO_SETLINK_NOTIFY;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return do_setlink(skb, dev, ifm, tb, ifname, status);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue