> My suggestion is at this point to ignore any L3 issues and have people > post their patches. RFC 2863 states MUST be taken into consideration. > Proper naming must be taken into account.
Split up in 3 patches, not implementing the bits allowing userspace to trigger leaving dormant state. [NET]: Support dormant interface state Adds a new link state "dormant" which may be used to have a link wait for an external event before it reaches opertional up state. The notification to userspace is extended: - IFF_LOWER_UP is set for all links with a working underlying layer, this can be a carrier or a set of child interfaces. - IFF_DORMANT is set for links in dormant state. Based on a patch by Krzysztof Halasa <[EMAIL PROTECTED]> Index: net-2.6/include/linux/netdevice.h =================================================================== --- net-2.6.orig/include/linux/netdevice.h +++ net-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, }; @@ -713,6 +714,10 @@ static inline void dev_put(struct net_de /* Carrier loss detection, dial on demand. The functions netif_carrier_on * and _off may be called from IRQ context, but it is caller * who is responsible for serialization of these calls. + * + * The name carrier is inappropriate, these functions should really be + * called netif_lowerlayer_*() because they represent the state of any + * kind of lower layer not just hardware media. */ extern void linkwatch_fire_event(struct net_device *dev); @@ -751,6 +756,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(const struct net_device *dev) +{ + return test_bit(__LINK_STATE_DORMANT, &dev->state); +} + /* * Network interface message level settings */ Index: net-2.6/net/core/dev.c =================================================================== --- net-2.6.orig/net/core/dev.c +++ net-2.6/net/core/dev.c @@ -2157,8 +2157,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_LOWER_UP; + if (netif_dormant(dev)) + flags |= IFF_DORMANT; + else + flags |= IFF_RUNNING; + } return flags; } Index: net-2.6/include/linux/if.h =================================================================== --- net-2.6.orig/include/linux/if.h +++ net-2.6/include/linux/if.h @@ -42,8 +42,12 @@ #define IFF_SLAVE 0x800 /* slave of a load balancer */ #define IFF_MULTICAST 0x1000 /* Supports multicast */ +#define IFF_LOWER_UP 0x2000 /* lower layer is up & running */ +#define IFF_DORMANT 0x4000 /* waiting for external event */ -#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_RUNNING | IFF_LOWER_UP | \ + IFF_DORMANT) #define IFF_PORTSEL 0x2000 /* can set media type */ #define IFF_AUTOMEDIA 0x4000 /* auto media select active */ [NET]: Provide operational state as per rfc2863 Provides the operational state as defined in rfc2863 via the function dev_oper_state() derived from the actual link states. Complex devices may implement the state via the new device callback dev->oper_state(). Index: net-2.6/include/linux/if.h =================================================================== --- net-2.6.orig/include/linux/if.h +++ net-2.6/include/linux/if.h @@ -84,6 +84,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: net-2.6/include/linux/netdevice.h =================================================================== --- net-2.6.orig/include/linux/netdevice.h +++ net-2.6/include/linux/netdevice.h @@ -493,6 +493,8 @@ struct net_device void (*poll_controller)(struct net_device *dev); #endif + int (*oper_state)(struct net_device *dev); + /* bridge stuff */ struct net_bridge_port *br_port; @@ -948,6 +950,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); #ifdef CONFIG_BUG extern void netdev_rx_csum_fault(struct net_device *dev); Index: net-2.6/net/core/dev.c =================================================================== --- net-2.6.orig/net/core/dev.c +++ net-2.6/net/core/dev.c @@ -994,6 +994,31 @@ 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 (dev->oper_state) + return dev->oper_state(dev); + + /* RFC2863 specifices LOWERLAYERDOWN to describe the state of + * underlying interfaces not including the carrier state. Since + * it really is a refinement of the down state we can use it to + * describe the carrier state as well. + */ + 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); @@ -3289,6 +3314,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); [NET]: Implement auto wait interfaces Adds a new flag IFF_WAIT which if set causes an interface going down to automatically enter dormant state before it is mared opertional again. Index: net-2.6/net/core/dev.c =================================================================== --- net-2.6.orig/net/core/dev.c +++ net-2.6/net/core/dev.c @@ -2204,7 +2204,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)); Index: net-2.6/include/linux/if.h =================================================================== --- net-2.6.orig/include/linux/if.h +++ net-2.6/include/linux/if.h @@ -44,6 +44,7 @@ #define IFF_MULTICAST 0x1000 /* Supports multicast */ #define IFF_LOWER_UP 0x2000 /* lower layer is up & running */ #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 | IFF_LOWER_UP | \ Index: net-2.6/net/sched/sch_generic.c =================================================================== --- net-2.6.orig/net/sched/sch_generic.c +++ net-2.6/net/sched/sch_generic.c @@ -240,6 +240,10 @@ 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)) - 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