diff options
author | Stefan Rompf <stefan@loplof.de> | 2006-03-20 20:09:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:09:11 -0500 |
commit | b00055aacdb172c05067612278ba27265fcd05ce (patch) | |
tree | 4dbbee11b02d54cc0978113dfb07c53fdce17aa8 /net/core/rtnetlink.c | |
parent | e843b9e1bec4a953d848a319da6a18ca5c667f55 (diff) |
[NET] core: add RFC2863 operstate
this patch adds a dormant flag to network devices, RFC2863 operstate derived
from these flags and possibility for userspace interaction. It allows drivers
to signal that a device is unusable for user traffic without disabling
queueing (and therefore the possibility for protocol establishment traffic to
flow) and a userspace supplicant (WPA, 802.1X) to mark a device unusable
without changes to the driver.
It is the result of our long discussion. However I must admit that it
represents what Jamal and I agreed on with compromises towards Krzysztof, but
Thomas and Krzysztof still disagree with some parts. Anyway I think it should
be applied.
Signed-off-by: Stefan Rompf <stefan@loplof.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index eca2976abb25..1c15a907066f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -179,6 +179,33 @@ rtattr_failure: | |||
179 | } | 179 | } |
180 | 180 | ||
181 | 181 | ||
182 | static void set_operstate(struct net_device *dev, unsigned char transition) | ||
183 | { | ||
184 | unsigned char operstate = dev->operstate; | ||
185 | |||
186 | switch(transition) { | ||
187 | case IF_OPER_UP: | ||
188 | if ((operstate == IF_OPER_DORMANT || | ||
189 | operstate == IF_OPER_UNKNOWN) && | ||
190 | !netif_dormant(dev)) | ||
191 | operstate = IF_OPER_UP; | ||
192 | break; | ||
193 | |||
194 | case IF_OPER_DORMANT: | ||
195 | if (operstate == IF_OPER_UP || | ||
196 | operstate == IF_OPER_UNKNOWN) | ||
197 | operstate = IF_OPER_DORMANT; | ||
198 | break; | ||
199 | }; | ||
200 | |||
201 | if (dev->operstate != operstate) { | ||
202 | write_lock_bh(&dev_base_lock); | ||
203 | dev->operstate = operstate; | ||
204 | write_unlock_bh(&dev_base_lock); | ||
205 | netdev_state_change(dev); | ||
206 | } | ||
207 | } | ||
208 | |||
182 | static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 209 | static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
183 | int type, u32 pid, u32 seq, u32 change, | 210 | int type, u32 pid, u32 seq, u32 change, |
184 | unsigned int flags) | 211 | unsigned int flags) |
@@ -209,6 +236,13 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
209 | } | 236 | } |
210 | 237 | ||
211 | if (1) { | 238 | if (1) { |
239 | u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN; | ||
240 | u8 link_mode = dev->link_mode; | ||
241 | RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); | ||
242 | RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode); | ||
243 | } | ||
244 | |||
245 | if (1) { | ||
212 | struct rtnl_link_ifmap map = { | 246 | struct rtnl_link_ifmap map = { |
213 | .mem_start = dev->mem_start, | 247 | .mem_start = dev->mem_start, |
214 | .mem_end = dev->mem_end, | 248 | .mem_end = dev->mem_end, |
@@ -399,6 +433,22 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
399 | dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); | 433 | dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); |
400 | } | 434 | } |
401 | 435 | ||
436 | if (ida[IFLA_OPERSTATE - 1]) { | ||
437 | if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) | ||
438 | goto out; | ||
439 | |||
440 | set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1]))); | ||
441 | } | ||
442 | |||
443 | if (ida[IFLA_LINKMODE - 1]) { | ||
444 | if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) | ||
445 | goto out; | ||
446 | |||
447 | write_lock_bh(&dev_base_lock); | ||
448 | dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1])); | ||
449 | write_unlock_bh(&dev_base_lock); | ||
450 | } | ||
451 | |||
402 | if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { | 452 | if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { |
403 | char ifname[IFNAMSIZ]; | 453 | char ifname[IFNAMSIZ]; |
404 | 454 | ||