aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authordavid decotigny <decot@googlers.com>2014-03-29 12:48:35 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-31 16:24:52 -0400
commit2d3b479df41a10e2f41f9259fcba775bd34de6e4 (patch)
tree517291066c35188a41b005e81904e69865643e76 /net
parent9c76a114bbef10b4d44bd258006721dd896695dd (diff)
net-sysfs: expose number of carrier on/off changes
This allows to monitor carrier on/off transitions and detect link flapping issues: - new /sys/class/net/X/carrier_changes - new rtnetlink IFLA_CARRIER_CHANGES (getlink) Tested: - grep . /sys/class/net/*/carrier_changes + ip link set dev X down/up + plug/unplug cable - updated iproute2: prints IFLA_CARRIER_CHANGES - iproute2 20121211-2 (debian): unchanged behavior Signed-off-by: David Decotigny <decot@googlers.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/net-sysfs.c11
-rw-r--r--net/core/rtnetlink.c6
-rw-r--r--net/sched/sch_generic.c2
3 files changed, 18 insertions, 1 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index daed9a64c6f6..462396278484 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -253,6 +253,16 @@ static ssize_t operstate_show(struct device *dev,
253} 253}
254static DEVICE_ATTR_RO(operstate); 254static DEVICE_ATTR_RO(operstate);
255 255
256static ssize_t carrier_changes_show(struct device *dev,
257 struct device_attribute *attr,
258 char *buf)
259{
260 struct net_device *netdev = to_net_dev(dev);
261 return sprintf(buf, fmt_dec,
262 atomic_read(&netdev->carrier_changes));
263}
264static DEVICE_ATTR_RO(carrier_changes);
265
256/* read-write attributes */ 266/* read-write attributes */
257 267
258static int change_mtu(struct net_device *net, unsigned long new_mtu) 268static int change_mtu(struct net_device *net, unsigned long new_mtu)
@@ -386,6 +396,7 @@ static struct attribute *net_class_attrs[] = {
386 &dev_attr_duplex.attr, 396 &dev_attr_duplex.attr,
387 &dev_attr_dormant.attr, 397 &dev_attr_dormant.attr,
388 &dev_attr_operstate.attr, 398 &dev_attr_operstate.attr,
399 &dev_attr_carrier_changes.attr,
389 &dev_attr_ifalias.attr, 400 &dev_attr_ifalias.attr,
390 &dev_attr_carrier.attr, 401 &dev_attr_carrier.attr,
391 &dev_attr_mtu.attr, 402 &dev_attr_mtu.attr,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e7c6006bc3ea..d4ff41739b0f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -822,6 +822,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
822 + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ 822 + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */
823 + nla_total_size(1) /* IFLA_OPERSTATE */ 823 + nla_total_size(1) /* IFLA_OPERSTATE */
824 + nla_total_size(1) /* IFLA_LINKMODE */ 824 + nla_total_size(1) /* IFLA_LINKMODE */
825 + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
825 + nla_total_size(ext_filter_mask 826 + nla_total_size(ext_filter_mask
826 & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ 827 & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
827 + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ 828 + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -970,7 +971,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
970 (dev->qdisc && 971 (dev->qdisc &&
971 nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || 972 nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
972 (dev->ifalias && 973 (dev->ifalias &&
973 nla_put_string(skb, IFLA_IFALIAS, dev->ifalias))) 974 nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)) ||
975 nla_put_u32(skb, IFLA_CARRIER_CHANGES,
976 atomic_read(&dev->carrier_changes)))
974 goto nla_put_failure; 977 goto nla_put_failure;
975 978
976 if (1) { 979 if (1) {
@@ -1147,6 +1150,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1147 [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, 1150 [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 },
1148 [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, 1151 [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 },
1149 [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, 1152 [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
1153 [IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */
1150}; 1154};
1151 1155
1152static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { 1156static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index e82e43b69c33..e1543b03e39d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -310,6 +310,7 @@ void netif_carrier_on(struct net_device *dev)
310 if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) { 310 if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
311 if (dev->reg_state == NETREG_UNINITIALIZED) 311 if (dev->reg_state == NETREG_UNINITIALIZED)
312 return; 312 return;
313 atomic_inc(&dev->carrier_changes);
313 linkwatch_fire_event(dev); 314 linkwatch_fire_event(dev);
314 if (netif_running(dev)) 315 if (netif_running(dev))
315 __netdev_watchdog_up(dev); 316 __netdev_watchdog_up(dev);
@@ -328,6 +329,7 @@ void netif_carrier_off(struct net_device *dev)
328 if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) { 329 if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
329 if (dev->reg_state == NETREG_UNINITIALIZED) 330 if (dev->reg_state == NETREG_UNINITIALIZED)
330 return; 331 return;
332 atomic_inc(&dev->carrier_changes);
331 linkwatch_fire_event(dev); 333 linkwatch_fire_event(dev);
332 } 334 }
333} 335}