aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorLaszlo Attila Toth <panther@balabit.hu>2008-02-13 01:42:09 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-13 01:42:09 -0500
commit45b503548210fe6f23e92b856421c2a3f05fd034 (patch)
treed4cacc5e468c2d2fa0e504c05d50f4e42d3bc6af /net/core
parent370125f0a48a2584a2506fd567d690df6d87cf2c (diff)
[RTNETLINK]: Send a single notification on device state changes.
In do_setlink() a single notification is sent at the end of the function if any modification occured. If the address has been changed, another notification is sent. Both of them is required because originally only the NETDEV_CHANGEADDR notification was sent and although device state change implies address change, some programs may expect the original notification. It remains for compatibity. If set_operstate() is called from do_setlink(), it doesn't send a notification, only if it is called from rtnl_create_link() as earlier. Signed-off-by: Laszlo Attila Toth <panther@balabit.hu> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 61ac8d06292c..ecb02afd52dc 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -504,7 +504,7 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
504 504
505EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); 505EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo);
506 506
507static void set_operstate(struct net_device *dev, unsigned char transition) 507static int set_operstate(struct net_device *dev, unsigned char transition, bool send_notification)
508{ 508{
509 unsigned char operstate = dev->operstate; 509 unsigned char operstate = dev->operstate;
510 510
@@ -527,8 +527,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
527 write_lock_bh(&dev_base_lock); 527 write_lock_bh(&dev_base_lock);
528 dev->operstate = operstate; 528 dev->operstate = operstate;
529 write_unlock_bh(&dev_base_lock); 529 write_unlock_bh(&dev_base_lock);
530 netdev_state_change(dev); 530
531 } 531 if (send_notification)
532 netdev_state_change(dev);
533 return 1;
534 } else
535 return 0;
532} 536}
533 537
534static void copy_rtnl_link_stats(struct rtnl_link_stats *a, 538static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
@@ -822,6 +826,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
822 if (tb[IFLA_BROADCAST]) { 826 if (tb[IFLA_BROADCAST]) {
823 nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); 827 nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
824 send_addr_notify = 1; 828 send_addr_notify = 1;
829 modified = 1;
825 } 830 }
826 831
827 if (ifm->ifi_flags || ifm->ifi_change) { 832 if (ifm->ifi_flags || ifm->ifi_change) {
@@ -834,16 +839,23 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
834 dev_change_flags(dev, flags); 839 dev_change_flags(dev, flags);
835 } 840 }
836 841
837 if (tb[IFLA_TXQLEN]) 842 if (tb[IFLA_TXQLEN]) {
838 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); 843 if (dev->tx_queue_len != nla_get_u32(tb[IFLA_TXQLEN])) {
844 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
845 modified = 1;
846 }
847 }
839 848
840 if (tb[IFLA_OPERSTATE]) 849 if (tb[IFLA_OPERSTATE])
841 set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); 850 modified |= set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]), false);
842 851
843 if (tb[IFLA_LINKMODE]) { 852 if (tb[IFLA_LINKMODE]) {
844 write_lock_bh(&dev_base_lock); 853 if (dev->link_mode != nla_get_u8(tb[IFLA_LINKMODE])) {
845 dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); 854 write_lock_bh(&dev_base_lock);
846 write_unlock_bh(&dev_base_lock); 855 dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
856 write_lock_bh(&dev_base_lock);
857 modified = 1;
858 }
847 } 859 }
848 860
849 err = 0; 861 err = 0;
@@ -857,6 +869,10 @@ errout:
857 869
858 if (send_addr_notify) 870 if (send_addr_notify)
859 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 871 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
872
873 if (modified)
874 netdev_state_change(dev);
875
860 return err; 876 return err;
861} 877}
862 878
@@ -974,7 +990,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
974 if (tb[IFLA_TXQLEN]) 990 if (tb[IFLA_TXQLEN])
975 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); 991 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
976 if (tb[IFLA_OPERSTATE]) 992 if (tb[IFLA_OPERSTATE])
977 set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); 993 set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]), true);
978 if (tb[IFLA_LINKMODE]) 994 if (tb[IFLA_LINKMODE])
979 dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); 995 dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
980 996