diff options
author | Patrick McHardy <kaber@trash.net> | 2010-02-26 01:34:54 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-27 05:43:40 -0500 |
commit | 3729d5021257b283f7fce33d957893162ccb2c9d (patch) | |
tree | d44d5333dfb0cf11cfec8b05a8c7697b5c8d4c07 /drivers/net/veth.c | |
parent | bd38081160bb3d036db98472e537b6a7dd4da51a (diff) |
rtnetlink: support specifying device flags on device creation
commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date: Tue Feb 23 20:41:30 2010 +0100
Support specifying the initial device flags when creating a device though
rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING
in order to surpress netlink registration notifications. To complete setup,
rtnl_configure_link() must be called, which performs the device flag changes
and invokes the deferred notifiers if everything went well.
Two examples:
# add macvlan to eth0
#
$ ip link add link eth0 up allmulticast on type macvlan
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff
[ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0
[ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
[LINK]11: macvlan0@eth0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500
link/ether 26:f8:84:02:f9:2a
[ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link
valid_lft forever preferred_lft forever
[ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0
[ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0
[NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE
[ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0
[PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084
[ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic
valid_lft 86399sec preferred_lft 14399sec
# add VLAN to eth1, eth1 is down
#
$ ip link add link eth1 up type vlan id 1000
RTNETLINK answers: Network is down
<no events>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/veth.c')
-rw-r--r-- | drivers/net/veth.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 35609e64f6fd..b583d4968add 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
@@ -333,19 +333,17 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
333 | struct veth_priv *priv; | 333 | struct veth_priv *priv; |
334 | char ifname[IFNAMSIZ]; | 334 | char ifname[IFNAMSIZ]; |
335 | struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; | 335 | struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; |
336 | struct ifinfomsg *ifmp; | ||
336 | struct net *net; | 337 | struct net *net; |
337 | 338 | ||
338 | /* | 339 | /* |
339 | * create and register peer first | 340 | * create and register peer first |
340 | * | ||
341 | * struct ifinfomsg is at the head of VETH_INFO_PEER, but we | ||
342 | * skip it since no info from it is useful yet | ||
343 | */ | 341 | */ |
344 | |||
345 | if (data != NULL && data[VETH_INFO_PEER] != NULL) { | 342 | if (data != NULL && data[VETH_INFO_PEER] != NULL) { |
346 | struct nlattr *nla_peer; | 343 | struct nlattr *nla_peer; |
347 | 344 | ||
348 | nla_peer = data[VETH_INFO_PEER]; | 345 | nla_peer = data[VETH_INFO_PEER]; |
346 | ifmp = nla_data(nla_peer); | ||
349 | err = nla_parse(peer_tb, IFLA_MAX, | 347 | err = nla_parse(peer_tb, IFLA_MAX, |
350 | nla_data(nla_peer) + sizeof(struct ifinfomsg), | 348 | nla_data(nla_peer) + sizeof(struct ifinfomsg), |
351 | nla_len(nla_peer) - sizeof(struct ifinfomsg), | 349 | nla_len(nla_peer) - sizeof(struct ifinfomsg), |
@@ -358,8 +356,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
358 | return err; | 356 | return err; |
359 | 357 | ||
360 | tbp = peer_tb; | 358 | tbp = peer_tb; |
361 | } else | 359 | } else { |
360 | ifmp = NULL; | ||
362 | tbp = tb; | 361 | tbp = tb; |
362 | } | ||
363 | 363 | ||
364 | if (tbp[IFLA_IFNAME]) | 364 | if (tbp[IFLA_IFNAME]) |
365 | nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ); | 365 | nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ); |
@@ -387,6 +387,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
387 | 387 | ||
388 | netif_carrier_off(peer); | 388 | netif_carrier_off(peer); |
389 | 389 | ||
390 | err = rtnl_configure_link(peer, ifmp); | ||
391 | if (err < 0) | ||
392 | goto err_configure_peer; | ||
393 | |||
390 | /* | 394 | /* |
391 | * register dev last | 395 | * register dev last |
392 | * | 396 | * |
@@ -428,6 +432,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
428 | err_register_dev: | 432 | err_register_dev: |
429 | /* nothing to do */ | 433 | /* nothing to do */ |
430 | err_alloc_name: | 434 | err_alloc_name: |
435 | err_configure_peer: | ||
431 | unregister_netdevice(peer); | 436 | unregister_netdevice(peer); |
432 | return err; | 437 | return err; |
433 | 438 | ||