* 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

Reply via email to