aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/veth.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-26 06:34:54 +0000
committerDavid S. Miller <davem@davemloft.net>2010-02-27 02:43:40 -0800
commit3729d5021257b283f7fce33d957893162ccb2c9d (patch)
treed44d5333dfb0cf11cfec8b05a8c7697b5c8d4c07 /drivers/net/veth.c
parentdev: support deferring device flag change notifications (diff)
downloadlinux-dev-3729d5021257b283f7fce33d957893162ccb2c9d.tar.xz
linux-dev-3729d5021257b283f7fce33d957893162ccb2c9d.zip
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.c15
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,
struct veth_priv *priv;
char ifname[IFNAMSIZ];
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
+ struct ifinfomsg *ifmp;
struct net *net;
/*
* create and register peer first
- *
- * struct ifinfomsg is at the head of VETH_INFO_PEER, but we
- * skip it since no info from it is useful yet
*/
-
if (data != NULL && data[VETH_INFO_PEER] != NULL) {
struct nlattr *nla_peer;
nla_peer = data[VETH_INFO_PEER];
+ ifmp = nla_data(nla_peer);
err = nla_parse(peer_tb, IFLA_MAX,
nla_data(nla_peer) + sizeof(struct ifinfomsg),
nla_len(nla_peer) - sizeof(struct ifinfomsg),
@@ -358,8 +356,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
return err;
tbp = peer_tb;
- } else
+ } else {
+ ifmp = NULL;
tbp = tb;
+ }
if (tbp[IFLA_IFNAME])
nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
@@ -387,6 +387,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
netif_carrier_off(peer);
+ err = rtnl_configure_link(peer, ifmp);
+ if (err < 0)
+ goto err_configure_peer;
+
/*
* register dev last
*
@@ -428,6 +432,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
err_register_dev:
/* nothing to do */
err_alloc_name:
+err_configure_peer:
unregister_netdevice(peer);
return err;