Skip to contentSkip to conversation

Patch: Device operative state notification against 2.4.18ac2

PATCH Stefan Rompf 1 participant 1 message Mar 28, 2002

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Hi,

attached you find a patch against Linux 2.4.18ac2 that revives the IFF_RUNNING flag in the dev->flags element. Some time ago, Alexey has replaced IFF_RUNNING by a bit in dev->state, AFAIK because of locking reasons.

When enabled, a thread is compiled into the kernel that scans the network device list on every netif_carrier_on()/_off() called by a device driver and mirrors the !LINK_STATE_NOCARRIER bit of dev->state into IFF_RUNNING. If these values differ for a device, a netlink message is broadcasted. This allows user processes to be notified about operative state changes. Actually, I've written some patches for the zebra routing daemon so that it stops using an interface while the driver thinks that it is down.

The thread worked fine for me as a once-per-second polling module for several weeks, and I hope I've found all gotchas to make it a "real" part of the kernel. There are problems left with obsolete drivers that are still playing with IFF_RUNNING directly, so I don't think this stuff is ready for the official 2.4 tree. Anyway, I'd like to have some testers and of course feedback.

Alan, please consider applying to your -ac tree.

Cheers, Stefan

Documentation/Configure.help +9 -0
diff -X dontdiff -urN linux-2.4.18ac2/Documentation/Configure.help linux-2.4.18ac2-stefan/Documentation/Configure.help
@@ -24594,6 +24594,15 @@
   information:  http://www.candelatech.com/~greear/vlan.html  If unsure,
   you can safely say 'N'.
 
+Device link state notification
+CONFIG_LINKWATCH
+  When this option is enabled, the kernel will forward changes in the
+  operative ("RUNNING") state of an interface via the netlink socket.
+  This is most useful when running linux as a router. Note that currently
+  not many drivers maintain an administrative state, a few even break this
+  option. Compliant drivers change the RUNNING flag in ifconfig output
+  depending on operative state. If unsure, say 'N'.
+
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
include/linux/netdevice.h +16 -0
diff -X dontdiff -urN linux-2.4.18ac2/include/linux/netdevice.h linux-2.4.18ac2-stefan/include/linux/netdevice.h
@@ -208,6 +208,12 @@
 	__LINK_STATE_NOCARRIER
 };
 
+/* This gets called by netif_carrier_on()/_off() whenever
+ * state of an interface changes
+ */
+#ifdef CONFIG_LINKWATCH
+extern void wake_linkwatch_thread(void);
+#endif
 
 /*
  * This structure holds at boot time configured netdevice settings. They
@@ -611,14 +617,24 @@
 
 static inline void netif_carrier_on(struct net_device *dev)
 {
+#ifdef CONFIG_LINKWATCH
+	if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
+		wake_linkwatch_thread();
+#else
 	clear_bit(__LINK_STATE_NOCARRIER, &dev->state);
+#endif
 	if (netif_running(dev))
 		__netdev_watchdog_up(dev);
 }
 
 static inline void netif_carrier_off(struct net_device *dev)
 {
+#ifdef CONFIG_LINKWATCH
+	if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
+		wake_linkwatch_thread();
+#else
 	set_bit(__LINK_STATE_NOCARRIER, &dev->state);
+#endif
 }
 
 /* Hot-plugging. */
net/Config.in +1 -0
diff -X dontdiff -urN linux-2.4.18ac2/net/Config.in linux-2.4.18ac2-stefan/net/Config.in
@@ -46,6 +46,7 @@
    fi
 
    dep_tristate '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_8021Q $CONFIG_EXPERIMENTAL
+   bool 'Device link state notification (EXPERIMENTAL)' CONFIG_LINKWATCH
 
 fi
 
net/core/dev.c +14 -2
diff -X dontdiff -urN linux-2.4.18ac2/net/core/dev.c linux-2.4.18ac2-stefan/net/core/dev.c
@@ -719,6 +719,12 @@
 		 */
 		dev->flags |= IFF_UP;
 
+		if (netif_carrier_ok(dev)) {
+			dev->flags |= IFF_RUNNING;
+		} else {
+			dev->flags &= ~IFF_RUNNING;
+		}
+
 		set_bit(__LINK_STATE_START, &dev->state);
 
 		/*
@@ -812,7 +818,7 @@
 	 *	Device is now down.
 	 */
 
-	dev->flags &= ~IFF_UP;
+	dev->flags &= ~(IFF_UP | IFF_RUNNING);
 #ifdef CONFIG_NET_FASTROUTE
 	dev_clear_fastroute(dev);
 #endif
@@ -2740,7 +2746,9 @@
 #ifdef CONFIG_NET_DIVERT
 extern void dv_init(void);
 #endif /* CONFIG_NET_DIVERT */
-
+#ifdef CONFIG_LINKWATCH
+extern void linkwatch_init(void);
+#endif /* CONFIG_LINKWATCH */
 
 /*
  *       Callers must hold the rtnl semaphore.  See the comment at the
@@ -2877,6 +2885,10 @@
 	 */
 	 
 	net_device_init();
+
+#ifdef CONFIG_LINKWATCH
+	linkwatch_init();
+#endif /* CONFIG_LINKWATCH */
 
 	return 0;
 }
net/core/link_watch.c +106 -0

106 lines not on this page · raw message

net/netsyms.c +4 -0
diff -X dontdiff -urN linux-2.4.18ac2/net/netsyms.c linux-2.4.18ac2-stefan/net/netsyms.c
@@ -588,4 +588,8 @@
 EXPORT_SYMBOL(net_call_rx_atomic);
 EXPORT_SYMBOL(softnet_data);
 
+#ifdef CONFIG_LINKWATCH
+EXPORT_SYMBOL(wake_linkwatch_thread);
+#endif
+
 #endif  /* CONFIG_NET */
net/core/Makefile +2 -0
@@ -27,4 +27,6 @@
 obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PROFILE) += profile.o
 
+obj-$(CONFIG_LINKWATCH) += link_watch.o
+
 include $(TOPDIR)/Rules.make