* 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