From: Stefan Rompf <srompf@isg.de>
To: netdev@oss.sgi.com
Cc: hadi@cyberus.ca
Subject: Patch: Idea for RFC2863 conform OperStatus
Date: Sat, 12 Oct 2002 15:23:53 +0200 [thread overview]
Message-ID: <3DA82269.CBB65E89@isg.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 578 bytes --]
Hi,
coming back to Jamals idea of RFC2863 conform operative state, I've made
up a short patch on how an implementation could look like. It also takes
Tims idea of one struct workstruct per device for link state
notification (slightly modified). I know it's incomplete, it doesn't
event contain the needed fix on unregister_netdev I critised on Tim's
patch, but I want to put it to discussion early. May be it breaks the
hotplugging stuff.
If we decide to go this way, we'll also need an extension to rtnetlink
and a new ioctl to transport the information to userspace.
Stefan
[-- Attachment #2: patch-rfc2863-2.5.41 --]
[-- Type: text/plain, Size: 9362 bytes --]
diff -rNuX dontdiff linux-2.5.41/include/linux/netdevice.h linux-2.5.41-stefan/include/linux/netdevice.h
--- linux-2.5.41/include/linux/netdevice.h Tue Oct 8 22:18:50 2002
+++ linux-2.5.41-stefan/include/linux/netdevice.h Sat Oct 12 14:33:20 2002
@@ -39,6 +39,10 @@
#include <net/profile.h>
#endif
+#ifdef CONFIG_LINKWATCH
+#include <linux/workqueue.h>
+#endif
+
struct divert_blk;
struct vlan_group;
@@ -204,13 +208,25 @@
{
__LINK_STATE_XOFF=0,
__LINK_STATE_START,
- __LINK_STATE_PRESENT,
+ __LINK_STATE_PRESENT_OBSOLETE,
__LINK_STATE_SCHED,
- __LINK_STATE_NOCARRIER,
+ __LINK_STATE_NOCARRIER_OBSOLETE,
__LINK_STATE_RX_SCHED
};
+/* Device operative state as per RFC2863 */
+enum netdev_operstate_t {
+ NETDEV_OPER_UP = 1,
+ NETDEV_OPER_DOWN, /* Obsoletes LINK_STATE_NOCARRIER */
+ NETDEV_OPER_TESTING,
+ NETDEV_OPER_UNKNOWN,
+ NETDEV_OPER_DORMANT,
+ NETDEV_OPER_NOTPRESENT, /* Obsoletes !LINK_STATE_PRESENT */
+ NETDEV_OPER_LOWERDOWN
+};
+
+
/*
* This structure holds at boot time configured netdevice settings. They
* are then used in the device probing.
@@ -308,6 +324,15 @@
* which this device is member of.
*/
+ /* Operative state, semaphore and work_struct for
+ * userspace notification
+ */
+#ifdef CONFIG_LINKWATCH
+ struct work_struct linkwatch_work;
+#endif
+ rwlock_t operstate_lock;
+ unsigned short operstate;
+
/* Interface address info. */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
@@ -631,34 +656,77 @@
* who is responsible for serialization of these calls.
*/
+#ifdef CONFIG_LINKWATCH
+extern void netdev_fire_linkwatch_event(struct net_device *dev);
+#endif
+
+static inline unsigned short netif_set_operstate(struct net_device *dev, unsigned short newstate)
+{
+ unsigned long flags;
+ unsigned short oldstate;
+
+ write_lock_irqsave(&dev->operstate_lock, flags);
+ oldstate = dev->operstate;
+ dev->operstate = newstate;
+ write_unlock_irqrestore(&dev->operstate_lock, flags);
+
+#ifdef CONFIG_LINKWATCH
+ if (oldstate != newstate) netdev_fire_linkwatch_event(dev);
+#endif
+
+ return oldstate;
+}
+
+static inline unsigned short netif_get_operstate(struct net_device *dev)
+{
+ unsigned long flags;
+ unsigned short state;
+
+ read_lock_irqsave(&dev->operstate_lock, flags);
+ state = dev->operstate;
+ read_unlock_irqrestore(&dev->operstate_lock, flags);
+
+ return state;
+}
+
static inline int netif_carrier_ok(struct net_device *dev)
{
- return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
+ return netif_get_operstate(dev) == NETDEV_OPER_UP;
+}
+
+static inline int netif_operstate_to_iff_running(struct net_device *dev)
+{
+ unsigned short state = netif_get_operstate(dev);
+
+ return((1 << state) &
+ (1 << NETDEV_OPER_UP | 1 << NETDEV_OPER_TESTING |
+ 1 << NETDEV_OPER_UNKNOWN));
}
extern void __netdev_watchdog_up(struct net_device *dev);
+
static inline void netif_carrier_on(struct net_device *dev)
{
- clear_bit(__LINK_STATE_NOCARRIER, &dev->state);
+ netif_set_operstate(dev, NETDEV_OPER_UP);
if (netif_running(dev))
__netdev_watchdog_up(dev);
}
static inline void netif_carrier_off(struct net_device *dev)
{
- set_bit(__LINK_STATE_NOCARRIER, &dev->state);
+ netif_set_operstate(dev, NETDEV_OPER_DOWN);
}
/* Hot-plugging. */
static inline int netif_device_present(struct net_device *dev)
{
- return test_bit(__LINK_STATE_PRESENT, &dev->state);
+ return netif_get_operstate(dev) != NETDEV_OPER_NOTPRESENT;
}
static inline void netif_device_detach(struct net_device *dev)
{
- if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) &&
+ if (netif_set_operstate(dev, NETDEV_OPER_NOTPRESENT) != NETDEV_OPER_NOTPRESENT &&
netif_running(dev)) {
netif_stop_queue(dev);
}
@@ -666,7 +734,7 @@
static inline void netif_device_attach(struct net_device *dev)
{
- if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
+ if (netif_set_operstate(dev, NETDEV_OPER_UNKNOWN) == NETDEV_OPER_NOTPRESENT &&
netif_running(dev)) {
netif_wake_queue(dev);
__netdev_watchdog_up(dev);
diff -rNuX dontdiff linux-2.5.41/net/Config.help linux-2.5.41-stefan/net/Config.help
--- linux-2.5.41/net/Config.help Tue Oct 1 09:06:18 2002
+++ linux-2.5.41-stefan/net/Config.help Sat Oct 12 00:56:59 2002
@@ -472,6 +472,17 @@
However, do not say Y here if you did not experience any serious
problems.
+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 support this, compliant ones
+ can be found by watching the the RUNNING flag in ifconfig output
+ that should follow operative state.
+
+ If unsure, say 'N'.
+
CONFIG_NET_SCHED
When the kernel has several packets to send out over a network
device, it has to decide which ones to send first, which ones to
diff -rNuX dontdiff linux-2.5.41/net/Config.in linux-2.5.41-stefan/net/Config.in
--- linux-2.5.41/net/Config.in Tue Oct 1 09:06:24 2002
+++ linux-2.5.41-stefan/net/Config.in Tue Oct 8 22:44:07 2002
@@ -82,6 +82,7 @@
tristate 'WAN router' CONFIG_WAN_ROUTER
bool 'Fast switching (read help!)' CONFIG_NET_FASTROUTE
bool 'Forwarding between high speed interfaces' CONFIG_NET_HW_FLOWCONTROL
+ bool 'Device link state notification (EXPERIMENTAL)' CONFIG_LINKWATCH
fi
mainmenu_option next_comment
diff -rNuX dontdiff linux-2.5.41/net/core/dev.c linux-2.5.41-stefan/net/core/dev.c
--- linux-2.5.41/net/core/dev.c Tue Oct 8 22:18:51 2002
+++ linux-2.5.41-stefan/net/core/dev.c Sat Oct 12 14:54:25 2002
@@ -198,6 +198,9 @@
int netdev_fastroute_obstacles;
#endif
+#ifdef CONFIG_LINKWATCH
+static void netdev_linkwatch_event(void *data);
+#endif
/*******************************************************************************
@@ -716,6 +719,8 @@
* Set the flags.
*/
dev->flags |= IFF_UP;
+ if (netif_operstate_to_iff_running(dev))
+ dev->flags |= IFF_RUNNING;
/*
* Initialize multicasting status
@@ -2017,7 +2022,7 @@
IFF_RUNNING)) |
(dev->gflags & (IFF_PROMISC |
IFF_ALLMULTI));
- if (netif_running(dev) && netif_carrier_ok(dev))
+ if (netif_running(dev) && netif_operstate_to_iff_running(dev))
ifr->ifr_flags |= IFF_RUNNING;
return 0;
@@ -2432,6 +2437,13 @@
goto out;
#endif /* CONFIG_NET_DIVERT */
+ /* Initial operstate */
+ dev->operstate_lock = RW_LOCK_UNLOCKED;
+ dev->operstate = NETDEV_OPER_UNKNOWN;
+#ifdef CONFIG_LINKWATCH
+ INIT_WORK(&dev->linkwatch_work, netdev_linkwatch_event, dev); // FIXME
+#endif
+
dev->iflink = -1;
/* Init, if this function is available */
@@ -2457,13 +2469,6 @@
if (!dev->rebuild_header)
dev->rebuild_header = default_rebuild_header;
- /*
- * Default initial state at registry is that the
- * device is present.
- */
-
- set_bit(__LINK_STATE_PRESENT, &dev->state);
-
dev->next = NULL;
dev_init_scheduler(dev);
write_lock_bh(&dev_base_lock);
@@ -2735,6 +2740,11 @@
#ifdef CONFIG_NET_FASTROUTE
dev->fastpath_lock = RW_LOCK_UNLOCKED;
#endif
+ dev->operstate_lock = RW_LOCK_UNLOCKED;
+ dev->operstate = NETDEV_OPER_UNKNOWN;
+#ifdef CONFIG_LINKWATCH
+ INIT_WORK(&dev->linkwatch_work, netdev_linkwatch_event, dev); // FIXME
+#endif
dev->xmit_lock_owner = -1;
dev->iflink = -1;
dev_hold(dev);
@@ -2767,7 +2777,6 @@
if (!dev->rebuild_header)
dev->rebuild_header = default_rebuild_header;
dev_init_scheduler(dev);
- set_bit(__LINK_STATE_PRESENT, &dev->state);
}
}
@@ -2848,3 +2857,32 @@
return call_usermodehelper(argv [0], argv, envp);
}
#endif
+
+
+#ifdef CONFIG_LINKWATCH
+static void netdev_linkwatch_event(void *data) {
+ struct net_device *dev = data;
+ unsigned int iff_running = netif_operstate_to_iff_running(dev);
+
+ rtnl_lock();
+ if (dev->flags & IFF_RUNNING && !iff_running) {
+ write_lock(&dev_base_lock);
+ dev->flags &= ~IFF_RUNNING;
+ write_unlock(&dev_base_lock);
+ netdev_state_change(dev);
+ } else if (!(dev->flags & IFF_RUNNING)) {
+ write_lock(&dev_base_lock);
+ dev->flags |= IFF_RUNNING;
+ write_unlock(&dev_base_lock);
+ netdev_state_change(dev);
+ }
+ rtnl_unlock();
+}
+
+
+void netdev_fire_linkwatch_event(struct net_device *dev) {
+ schedule_delayed_work(&dev->linkwatch_work, HZ / 4);
+}
+
+#endif
+
diff -rNuX dontdiff linux-2.5.41/net/core/rtnetlink.c linux-2.5.41-stefan/net/core/rtnetlink.c
--- linux-2.5.41/net/core/rtnetlink.c Tue Oct 1 09:07:57 2002
+++ linux-2.5.41-stefan/net/core/rtnetlink.c Sat Oct 12 14:27:43 2002
@@ -165,7 +165,7 @@
r->ifi_flags = dev->flags;
r->ifi_change = change;
- if (!netif_running(dev) || !netif_carrier_ok(dev))
+ if (!netif_running(dev) || !netif_operstate_to_iff_running(dev))
r->ifi_flags &= ~IFF_RUNNING;
else
r->ifi_flags |= IFF_RUNNING;
diff -rNuX dontdiff linux-2.5.41/net/netsyms.c linux-2.5.41-stefan/net/netsyms.c
--- linux-2.5.41/net/netsyms.c Tue Oct 8 22:18:53 2002
+++ linux-2.5.41-stefan/net/netsyms.c Sat Oct 12 14:34:38 2002
@@ -596,4 +596,8 @@
EXPORT_SYMBOL(wireless_send_event);
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
+#ifdef CONFIG_LINKWATCH
+EXPORT_SYMBOL(netdev_fire_linkwatch_event);
+#endif
+
#endif /* CONFIG_NET */
next reply other threads:[~2002-10-12 13:23 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-10-12 13:23 Stefan Rompf [this message]
2002-10-12 13:13 ` Patch: Idea for RFC2863 conform OperStatus jamal
2002-10-13 12:48 ` Stefan Rompf
2002-10-13 14:04 ` jamal
2002-10-15 9:53 ` Stefan Rompf
2002-10-16 2:49 ` jamal
2002-10-21 21:38 ` Stefan Rompf
2002-10-12 14:09 ` jamal
2002-10-13 19:14 ` kuznet
2002-10-13 20:30 ` jamal
2002-10-13 21:00 ` kuznet
2002-10-13 21:34 ` jamal
2002-10-13 22:04 ` kuznet
2002-10-14 12:42 ` Stefan Rompf
2002-10-14 13:11 ` jamal
2002-10-14 13:38 ` jamal
2002-10-14 18:14 ` Stefan Rompf
2002-10-14 18:55 ` David Brownell
2002-10-14 19:03 ` David Brownell
2002-10-14 13:01 ` jamal
2002-10-14 10:38 ` bert hubert
2002-10-14 11:16 ` Robert Olsson
2002-10-14 11:11 ` bert hubert
2002-10-14 11:50 ` Robert Olsson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3DA82269.CBB65E89@isg.de \
--to=srompf@isg.de \
--cc=hadi@cyberus.ca \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).