* Stefan Rompf <[EMAIL PROTECTED]> 2005-11-07 00:42 > -userspace interaction, including userspace supplicant + locking of > operstate_useroverride > -migrate VLAN + BONDING to use OPER_LOWERLAYERDOWN
I think that bonding should check on the administrative status of its slaves as well. Why not check for OPER_UP? > I'd leave making IPV4 not consider routes when interface is <OPER_DORMANTL3UP > for 2.6.16. > Unfortunately, me and Krzysztof have totally different opinions if this > complexity is needed. I think yes, as it will make it possible to use a > userspace supplicant for connection completion (WPA), layer 3 protocols not > considering down interfaces for routing decisions (imporant for quagga), dial > on demand interfaces, clear state forwarding for stacked interfaces. This is > stuff required now, not in a distant future, and if we touch these flags > anyway, let's do it right. I still don't see the point in OPER_DORMANTL3DOWN vs. OPER_DORMANTL3UP. Can't we put the driver, stacked interface, etc. in charge for dropping packets which shouldn't be let through yet? I would favour this and have the dormant state limited to link layer responsibilities. > This is not yet for applying, just compilation tested, comments welcome. Is > my > wmb() to avoid 4 byte atomic_t the right idea? char access is not guaranteed to be atomic, just use int for the states. Here is how I see things, it's not complete and lacks proper locking but enough to get the point. Index: linux-2.6/include/linux/if.h =================================================================== --- linux-2.6.orig/include/linux/if.h +++ linux-2.6/include/linux/if.h @@ -42,8 +42,11 @@ #define IFF_SLAVE 0x800 /* slave of a load balancer */ #define IFF_MULTICAST 0x1000 /* Supports multicast */ +#define IFF_LINK_UP 0x2000 /* lower link up */ +#define IFF_DORMANT 0x4000 /* waiting for external event */ +#define IFF_WAIT 0x8000 /* auto. enter dormant state */ -#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING) +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_LINK_UP|IFF_DORMANT|IFF_RUNNING) #define IFF_PORTSEL 0x2000 /* can set media type */ #define IFF_AUTOMEDIA 0x4000 /* auto media select active */ @@ -80,6 +83,16 @@ #define IF_PROTO_FR_ETH_PVC 0x200B #define IF_PROTO_RAW 0x200C /* RAW Socket */ +/* RFC 2863 operational status */ +enum { + IF_OPER_UNKNOWN, + IF_OPER_NOTPRESENT, + IF_OPER_DOWN, + IF_OPER_LOWERLAYERDOWN, + IF_OPER_TESTING, + IF_OPER_DORMANT, + IF_OPER_UP, +}; /* * Device mapping structure. I'd just gone off and designed a Index: linux-2.6/include/linux/netdevice.h =================================================================== --- linux-2.6.orig/include/linux/netdevice.h +++ linux-2.6/include/linux/netdevice.h @@ -230,7 +230,8 @@ enum netdev_state_t __LINK_STATE_SCHED, __LINK_STATE_NOCARRIER, __LINK_STATE_RX_SCHED, - __LINK_STATE_LINKWATCH_PENDING + __LINK_STATE_LINKWATCH_PENDING, + __LINK_STATE_DORMANT, }; @@ -751,6 +752,23 @@ static inline void netif_device_attach(s } } +static inline void netif_dormant_on(struct net_device *dev) +{ + if (!test_and_set_bit(__LINK_STATE_DORMANT, &dev->state)) + linkwatch_fire_event(dev); +} + +static inline void netif_dormant_off(struct net_device *dev) +{ + if (test_and_clear_bit(__LINK_STATE_DORMANT, &dev->state)) + linkwatch_fire_event(dev); +} + +static inline int netif_dormant(struct net_device *dev) +{ + return test_bit(__LINK_STATE_DORMANT, &dev->state); +} + /* * Network interface message level settings */ @@ -926,6 +944,7 @@ extern void dev_mcast_init(void); extern int netdev_max_backlog; extern int weight_p; extern int netdev_set_master(struct net_device *dev, struct net_device *master); +extern int dev_oper_state(struct net_device *dev); extern int skb_checksum_help(struct sk_buff *skb, int inward); /* rx skb timestamps */ extern void net_enable_timestamp(void); Index: linux-2.6/net/core/dev.c =================================================================== --- linux-2.6.orig/net/core/dev.c +++ linux-2.6/net/core/dev.c @@ -994,6 +994,23 @@ int call_netdevice_notifiers(unsigned lo return notifier_call_chain(&netdev_chain, val, v); } +int dev_oper_state(struct net_device *dev) +{ + if (!netif_device_present(dev)) + return IF_OPER_NOTPRESENT; + + if (!netif_running(dev)) + return IF_OPER_DOWN; + + if (!netif_carrier_ok(dev)) + return IF_OPER_LOWERLAYERDOWN; + + if (netif_dormant(dev)) + return IF_OPER_DORMANT; + + return IF_OPER_UP; +} + /* When > 0 there are consumers of rx skb time stamps */ static atomic_t netstamp_needed = ATOMIC_INIT(0); @@ -2145,8 +2162,13 @@ unsigned dev_get_flags(const struct net_ (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); - if (netif_running(dev) && netif_carrier_ok(dev)) - flags |= IFF_RUNNING; + if (netif_running(dev) && netif_carrier_ok(dev)) { + flags |= IFF_LINK_OK; + if (netif_dormant()) + flags |= IFF_DORMANT; + else + flags |= IFF_RUNNING; + } return flags; } @@ -2162,7 +2184,7 @@ int dev_change_flags(struct net_device * dev->flags = (flags & (IFF_DEBUG | IFF_NOTRAILERS | IFF_NOARP | IFF_DYNAMIC | IFF_MULTICAST | IFF_PORTSEL | - IFF_AUTOMEDIA)) | + IFF_AUTOMEDIA | IFF_WAIT)) | (dev->flags & (IFF_UP | IFF_VOLATILE | IFF_PROMISC | IFF_ALLMULTI)); @@ -2191,6 +2213,9 @@ int dev_change_flags(struct net_device * IFF_VOLATILE))) notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); + if (netif_dormant() && !(flags & IFF_DORMANT)) + netif_dormant_off(dev); + if ((flags ^ dev->gflags) & IFF_PROMISC) { int inc = (flags & IFF_PROMISC) ? +1 : -1; dev->gflags ^= IFF_PROMISC; @@ -3272,6 +3297,7 @@ EXPORT_SYMBOL(dev_set_promiscuity); EXPORT_SYMBOL(dev_change_flags); EXPORT_SYMBOL(dev_set_mtu); EXPORT_SYMBOL(dev_set_mac_address); +EXPORT_SYMBOL(dev_oper_state); EXPORT_SYMBOL(free_netdev); EXPORT_SYMBOL(netdev_boot_setup_check); EXPORT_SYMBOL(netdev_set_master); Index: linux-2.6/net/sched/sch_generic.c =================================================================== --- linux-2.6.orig/net/sched/sch_generic.c +++ linux-2.6/net/sched/sch_generic.c @@ -240,9 +240,14 @@ static void dev_watchdog_down(struct net void netif_carrier_on(struct net_device *dev) { + if ((dev->flags & IFF_WAIT) && + test_bit(__LINK_STATE_NOCARRIER, &dev->state)) + netif_dormant_on(dev); + if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) linkwatch_fire_event(dev); - if (netif_running(dev)) + + if (netif_running(dev) && !netif_dormant(dev)); __netdev_watchdog_up(dev); } - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html