All of lore.kernel.org
 help / color / mirror / Atom feed
* net: rtnetlink: support specifying device flags on device creation
@ 2010-02-26 16:34 Patrick McHardy
  2010-02-26 16:34 ` net 01/04: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event() Patrick McHardy
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Patrick McHardy @ 2010-02-26 16:34 UTC (permalink / raw)
  To: netdev; +Cc: Patrick McHardy

The following patches add support to specify the device flags (like UP) when
creating a new device through rtnl_link. This requires to surpress netlink
notifications until the device is fully configured in order to not confuse
userspace when changing the flags fails and registration has to be undone.
Once the device is configured, a single NEWLINK message with the full state
is sent.

The individual patch changelogs describe the necessary changes in more detail.


 drivers/net/veth.c        |   15 +++--
 include/linux/netdevice.h |    9 ++-
 include/net/rtnetlink.h   |    2 +
 net/core/dev.c            |  171 +++++++++++++++++++++++++++++----------------
 net/core/rtnetlink.c      |   59 ++++++++++++----
 5 files changed, 176 insertions(+), 80 deletions(-)

Patrick McHardy (4):
      net: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event()
      net: rtnetlink: handle rtnl_link netlink notifications manually
      net: dev: support deferring device flag change notifications
      net: rtnetlink: support specifying device flags on device creation

^ permalink raw reply	[flat|nested] 7+ messages in thread

* net 01/04: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event()
  2010-02-26 16:34 net: rtnetlink: support specifying device flags on device creation Patrick McHardy
@ 2010-02-26 16:34 ` Patrick McHardy
  2010-02-26 16:34 ` net 02/04: rtnetlink: handle rtnl_link netlink notifications manually Patrick McHardy
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Patrick McHardy @ 2010-02-26 16:34 UTC (permalink / raw)
  To: netdev; +Cc: Patrick McHardy

commit 140dcbaa692be4ce66e68624d438aed030184186
Author: Patrick McHardy <kaber@trash.net>
Date:   Tue Feb 23 20:56:39 2010 +0100

    net: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event()
    
    Commit 3b8bcfd (net: introduce pre-up netdev notifier) added a new
    notifier which is run before a device is set UP for use by cfg80211.
    
    The patch missed to add the new notifier to the ignore list in
    rtnetlink_event(), so we currently get an unnecessary netlink
    notification before a device is set UP.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4dd4c3c..b7c7dfd 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1432,6 +1432,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
 	case NETDEV_DOWN:
 		rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
 		break;
+	case NETDEV_PRE_UP:
 	case NETDEV_POST_INIT:
 	case NETDEV_REGISTER:
 	case NETDEV_CHANGE:

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* net 02/04: rtnetlink: handle rtnl_link netlink notifications manually
  2010-02-26 16:34 net: rtnetlink: support specifying device flags on device creation Patrick McHardy
  2010-02-26 16:34 ` net 01/04: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event() Patrick McHardy
@ 2010-02-26 16:34 ` Patrick McHardy
  2010-02-26 16:34 ` net 03/04: dev: support deferring device flag change notifications Patrick McHardy
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Patrick McHardy @ 2010-02-26 16:34 UTC (permalink / raw)
  To: netdev; +Cc: Patrick McHardy

commit d1a41c4805fd5850156668114d42d7a51964926a
Author: Patrick McHardy <kaber@trash.net>
Date:   Wed Feb 24 13:52:52 2010 +0100

    net: rtnetlink: handle rtnl_link netlink notifications manually
    
    In order to support specifying device flags during device creation,
    we must be able to roll back device registration in case setting the
    flags fails without sending any notifications related to the device
    to userspace.
    
    This patch changes rollback_registered_many() and register_netdevice()
    to manually send netlink notifications for devices not handled by
    rtnl_link and allows to defer notifications for devices handled by
    rtnl_link until setup is complete.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 682d025..19af5fb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -924,7 +924,12 @@ struct net_device {
 	       NETREG_UNREGISTERED,	/* completed unregister todo */
 	       NETREG_RELEASED,		/* called free_netdev */
 	       NETREG_DUMMY,		/* dummy device for NAPI poll */
-	} reg_state;
+	} reg_state:16;
+
+	enum {
+		RTNL_LINK_INITIALIZED,
+		RTNL_LINK_INITIALIZING,
+	} rtnl_link_state:16;
 
 	/* Called from unregister, can be used to call free_netdev */
 	void (*destructor)(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index eb7f1a4..75332b0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4865,6 +4865,10 @@ static void rollback_registered_many(struct list_head *head)
 		*/
 		call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
 
+		if (!dev->rtnl_link_ops ||
+		    dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
+			rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
+
 		/*
 		 *	Flush the unicast and multicast chains
 		 */
@@ -5091,7 +5095,9 @@ int register_netdevice(struct net_device *dev)
 	 *	Prevent userspace races by waiting until the network
 	 *	device is fully setup before sending notifications.
 	 */
-	rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
+	if (!dev->rtnl_link_ops ||
+	    dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
+		rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
 
 out:
 	return ret;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b7c7dfd..020e43b 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1425,9 +1425,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
 	struct net_device *dev = ptr;
 
 	switch (event) {
-	case NETDEV_UNREGISTER:
-		rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
-		break;
 	case NETDEV_UP:
 	case NETDEV_DOWN:
 		rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
@@ -1437,6 +1434,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
 	case NETDEV_REGISTER:
 	case NETDEV_CHANGE:
 	case NETDEV_GOING_DOWN:
+	case NETDEV_UNREGISTER:
 	case NETDEV_UNREGISTER_BATCH:
 		break;
 	default:

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* net 03/04: dev: support deferring device flag change notifications
  2010-02-26 16:34 net: rtnetlink: support specifying device flags on device creation Patrick McHardy
  2010-02-26 16:34 ` net 01/04: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event() Patrick McHardy
  2010-02-26 16:34 ` net 02/04: rtnetlink: handle rtnl_link netlink notifications manually Patrick McHardy
@ 2010-02-26 16:34 ` Patrick McHardy
  2010-02-26 16:34 ` net 04/04: rtnetlink: support specifying device flags on device creation Patrick McHardy
  2010-02-27 10:51 ` net: " David Miller
  4 siblings, 0 replies; 7+ messages in thread
From: Patrick McHardy @ 2010-02-26 16:34 UTC (permalink / raw)
  To: netdev; +Cc: Patrick McHardy

commit 18c626db4551a23d1f848adafad41e44388b6c2f
Author: Patrick McHardy <kaber@trash.net>
Date:   Wed Feb 24 15:51:55 2010 +0100

    net: dev: support deferring device flag change notifications
    
    Split dev_change_flags() into two functions: __dev_change_flags() to
    perform the actual changes and __dev_notify_flags() to invoke netdevice
    notifiers. This will be used by rtnl_link to defer netlink notifications
    until the device has been fully configured.
    
    This changes ordering of some operations, in particular:
    
    - netlink notifications are sent after all changes have been performed.
      As a side effect this surpresses one unnecessary netlink message when
      the IFF_UP and other flags are changed simultaneously.
    
    - The NETDEV_UP/NETDEV_DOWN and NETDEV_CHANGE notifiers are invoked
      after all changes have been performed. Their relative is unchanged.
    
    - net_dmaengine_put() is invoked before the NETDEV_DOWN notifier instead
      of afterwards. This should not make any difference since both RX and TX
      are already shut down at this point.
    
    Signed-off-by: Patrick McHardy <kaber@trash.net>

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 19af5fb..bab133d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1587,7 +1587,9 @@ extern int		dev_valid_name(const char *name);
 extern int		dev_ioctl(struct net *net, unsigned int cmd, void __user *);
 extern int		dev_ethtool(struct net *net, struct ifreq *);
 extern unsigned		dev_get_flags(const struct net_device *);
+extern int		__dev_change_flags(struct net_device *, unsigned int flags);
 extern int		dev_change_flags(struct net_device *, unsigned);
+extern void		__dev_notify_flags(struct net_device *, unsigned int old_flags);
 extern int		dev_change_name(struct net_device *, const char *);
 extern int		dev_set_alias(struct net_device *, const char *, size_t);
 extern int		dev_change_net_namespace(struct net_device *,
diff --git a/net/core/dev.c b/net/core/dev.c
index 75332b0..e5972f7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1113,19 +1113,7 @@ void dev_load(struct net *net, const char *name)
 }
 EXPORT_SYMBOL(dev_load);
 
-/**
- *	dev_open	- prepare an interface for use.
- *	@dev:	device to open
- *
- *	Takes a device from down to up state. The device's private open
- *	function is invoked and then the multicast lists are loaded. Finally
- *	the device is moved into the up state and a %NETDEV_UP message is
- *	sent to the netdev notifier chain.
- *
- *	Calling this function on an active interface is a nop. On a failure
- *	a negative errno code is returned.
- */
-int dev_open(struct net_device *dev)
+static int __dev_open(struct net_device *dev)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int ret;
@@ -1133,13 +1121,6 @@ int dev_open(struct net_device *dev)
 	ASSERT_RTNL();
 
 	/*
-	 *	Is it already up?
-	 */
-
-	if (dev->flags & IFF_UP)
-		return 0;
-
-	/*
 	 *	Is it even present?
 	 */
 	if (!netif_device_present(dev))
@@ -1187,36 +1168,57 @@ int dev_open(struct net_device *dev)
 		 *	Wakeup transmit queue engine
 		 */
 		dev_activate(dev);
-
-		/*
-		 *	... and announce new interface.
-		 */
-		call_netdevice_notifiers(NETDEV_UP, dev);
 	}
 
 	return ret;
 }
-EXPORT_SYMBOL(dev_open);
 
 /**
- *	dev_close - shutdown an interface.
- *	@dev: device to shutdown
+ *	dev_open	- prepare an interface for use.
+ *	@dev:	device to open
  *
- *	This function moves an active device into down state. A
- *	%NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device
- *	is then deactivated and finally a %NETDEV_DOWN is sent to the notifier
- *	chain.
+ *	Takes a device from down to up state. The device's private open
+ *	function is invoked and then the multicast lists are loaded. Finally
+ *	the device is moved into the up state and a %NETDEV_UP message is
+ *	sent to the netdev notifier chain.
+ *
+ *	Calling this function on an active interface is a nop. On a failure
+ *	a negative errno code is returned.
  */
-int dev_close(struct net_device *dev)
+int dev_open(struct net_device *dev)
+{
+	int ret;
+
+	/*
+	 *	Is it already up?
+	 */
+	if (dev->flags & IFF_UP)
+		return 0;
+
+	/*
+	 *	Open device
+	 */
+	ret = __dev_open(dev);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 *	... and announce new interface.
+	 */
+	rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
+	call_netdevice_notifiers(NETDEV_UP, dev);
+
+	return ret;
+}
+EXPORT_SYMBOL(dev_open);
+
+static int __dev_close(struct net_device *dev)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
-	ASSERT_RTNL();
 
+	ASSERT_RTNL();
 	might_sleep();
 
-	if (!(dev->flags & IFF_UP))
-		return 0;
-
 	/*
 	 *	Tell people we are going down, so that they can
 	 *	prepare to death, when device is still operating.
@@ -1252,14 +1254,34 @@ int dev_close(struct net_device *dev)
 	dev->flags &= ~IFF_UP;
 
 	/*
-	 * Tell people we are down
+	 *	Shutdown NET_DMA
 	 */
-	call_netdevice_notifiers(NETDEV_DOWN, dev);
+	net_dmaengine_put();
+
+	return 0;
+}
+
+/**
+ *	dev_close - shutdown an interface.
+ *	@dev: device to shutdown
+ *
+ *	This function moves an active device into down state. A
+ *	%NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device
+ *	is then deactivated and finally a %NETDEV_DOWN is sent to the notifier
+ *	chain.
+ */
+int dev_close(struct net_device *dev)
+{
+	if (!(dev->flags & IFF_UP))
+		return 0;
+
+	__dev_close(dev);
 
 	/*
-	 *	Shutdown NET_DMA
+	 * Tell people we are down
 	 */
-	net_dmaengine_put();
+	rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
+	call_netdevice_notifiers(NETDEV_DOWN, dev);
 
 	return 0;
 }
@@ -4299,18 +4321,10 @@ unsigned dev_get_flags(const struct net_device *dev)
 }
 EXPORT_SYMBOL(dev_get_flags);
 
-/**
- *	dev_change_flags - change device settings
- *	@dev: device
- *	@flags: device state flags
- *
- *	Change settings on device based state flags. The flags are
- *	in the userspace exported format.
- */
-int dev_change_flags(struct net_device *dev, unsigned flags)
+int __dev_change_flags(struct net_device *dev, unsigned int flags)
 {
-	int ret, changes;
 	int old_flags = dev->flags;
+	int ret;
 
 	ASSERT_RTNL();
 
@@ -4341,17 +4355,12 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
 
 	ret = 0;
 	if ((old_flags ^ flags) & IFF_UP) {	/* Bit is different  ? */
-		ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
+		ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev);
 
 		if (!ret)
 			dev_set_rx_mode(dev);
 	}
 
-	if (dev->flags & IFF_UP &&
-	    ((old_flags ^ dev->flags) & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
-					  IFF_VOLATILE)))
-		call_netdevice_notifiers(NETDEV_CHANGE, dev);
-
 	if ((flags ^ dev->gflags) & IFF_PROMISC) {
 		int inc = (flags & IFF_PROMISC) ? 1 : -1;
 
@@ -4370,11 +4379,47 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
 		dev_set_allmulti(dev, inc);
 	}
 
-	/* Exclude state transition flags, already notified */
-	changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING);
+	return ret;
+}
+
+void __dev_notify_flags(struct net_device *dev, unsigned int old_flags)
+{
+	unsigned int changes = dev->flags ^ old_flags;
+
+	if (changes & IFF_UP) {
+		if (dev->flags & IFF_UP)
+			call_netdevice_notifiers(NETDEV_UP, dev);
+		else
+			call_netdevice_notifiers(NETDEV_DOWN, dev);
+	}
+
+	if (dev->flags & IFF_UP &&
+	    (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE)))
+		call_netdevice_notifiers(NETDEV_CHANGE, dev);
+}
+
+/**
+ *	dev_change_flags - change device settings
+ *	@dev: device
+ *	@flags: device state flags
+ *
+ *	Change settings on device based state flags. The flags are
+ *	in the userspace exported format.
+ */
+int dev_change_flags(struct net_device *dev, unsigned flags)
+{
+	int ret, changes;
+	int old_flags = dev->flags;
+
+	ret = __dev_change_flags(dev, flags);
+	if (ret < 0)
+		return ret;
+
+	changes = old_flags ^ dev->flags;
 	if (changes)
 		rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
 
+	__dev_notify_flags(dev, old_flags);
 	return ret;
 }
 EXPORT_SYMBOL(dev_change_flags);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 020e43b..c21ec42 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1427,8 +1427,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
 	switch (event) {
 	case NETDEV_UP:
 	case NETDEV_DOWN:
-		rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
-		break;
 	case NETDEV_PRE_UP:
 	case NETDEV_POST_INIT:
 	case NETDEV_REGISTER:

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* net 04/04: rtnetlink: support specifying device flags on device creation
  2010-02-26 16:34 net: rtnetlink: support specifying device flags on device creation Patrick McHardy
                   ` (2 preceding siblings ...)
  2010-02-26 16:34 ` net 03/04: dev: support deferring device flag change notifications Patrick McHardy
@ 2010-02-26 16:34 ` Patrick McHardy
  2010-02-27 10:51 ` net: " David Miller
  4 siblings, 0 replies; 7+ messages in thread
From: Patrick McHardy @ 2010-02-26 16:34 UTC (permalink / raw)
  To: netdev; +Cc: Patrick McHardy

commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f
Author: Patrick McHardy <kaber@trash.net>
Date:   Tue Feb 23 20:41:30 2010 +0100

    net: rtnetlink: support specifying device flags on device creation
    
    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>

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 35609e6..b583d49 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;
 
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 48d3efc..af60fd0 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -87,6 +87,8 @@ extern void	rtnl_link_unregister(struct rtnl_link_ops *ops);
 extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
 extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 	char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
+extern int rtnl_configure_link(struct net_device *dev,
+			       const struct ifinfomsg *ifm);
 extern const struct nla_policy ifla_policy[IFLA_MAX+1];
 
 #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index c21ec42..d1472a4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -549,6 +549,19 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
 	}
 }
 
+static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
+					   const struct ifinfomsg *ifm)
+{
+	unsigned int flags = ifm->ifi_flags;
+
+	/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
+	if (ifm->ifi_change)
+		flags = (flags & ifm->ifi_change) |
+			(dev->flags & ~ifm->ifi_change);
+
+	return flags;
+}
+
 static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
 				 const struct net_device_stats *b)
 {
@@ -904,13 +917,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 	}
 
 	if (ifm->ifi_flags || ifm->ifi_change) {
-		unsigned int flags = ifm->ifi_flags;
-
-		/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
-		if (ifm->ifi_change)
-			flags = (flags & ifm->ifi_change) |
-				(dev->flags & ~ifm->ifi_change);
-		err = dev_change_flags(dev, flags);
+		err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
 		if (err < 0)
 			goto errout;
 	}
@@ -1053,6 +1060,26 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	return 0;
 }
 
+int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
+{
+	unsigned int old_flags;
+	int err;
+
+	old_flags = dev->flags;
+	if (ifm && (ifm->ifi_flags || ifm->ifi_change)) {
+		err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
+		if (err < 0)
+			return err;
+	}
+
+	dev->rtnl_link_state = RTNL_LINK_INITIALIZED;
+	rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
+
+	__dev_notify_flags(dev, old_flags);
+	return 0;
+}
+EXPORT_SYMBOL(rtnl_configure_link);
+
 struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 	char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[])
 {
@@ -1074,6 +1101,7 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 
 	dev_net_set(dev, net);
 	dev->rtnl_link_ops = ops;
+	dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
 	dev->real_num_tx_queues = real_num_queues;
 
 	if (strchr(dev->name, '%')) {
@@ -1203,7 +1231,7 @@ replay:
 		if (!(nlh->nlmsg_flags & NLM_F_CREATE))
 			return -ENODEV;
 
-		if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
+		if (ifm->ifi_index)
 			return -EOPNOTSUPP;
 		if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
 			return -EOPNOTSUPP;
@@ -1234,9 +1262,15 @@ replay:
 			err = ops->newlink(net, dev, tb, data);
 		else
 			err = register_netdevice(dev);
-		if (err < 0 && !IS_ERR(dev))
+		if (err < 0 && !IS_ERR(dev)) {
 			free_netdev(dev);
+			goto out;
+		}
 
+		err = rtnl_configure_link(dev, ifm);
+		if (err < 0)
+			unregister_netdevice(dev);
+out:
 		put_net(dest_net);
 		return err;
 	}

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: net: rtnetlink: support specifying device flags on device creation
  2010-02-26 16:34 net: rtnetlink: support specifying device flags on device creation Patrick McHardy
                   ` (3 preceding siblings ...)
  2010-02-26 16:34 ` net 04/04: rtnetlink: support specifying device flags on device creation Patrick McHardy
@ 2010-02-27 10:51 ` David Miller
  2010-03-01 15:24   ` Patrick McHardy
  4 siblings, 1 reply; 7+ messages in thread
From: David Miller @ 2010-02-27 10:51 UTC (permalink / raw)
  To: kaber; +Cc: netdev

From: Patrick McHardy <kaber@trash.net>
Date: Fri, 26 Feb 2010 17:34:49 +0100 (MET)

> The following patches add support to specify the device flags (like UP) when
> creating a new device through rtnl_link. This requires to surpress netlink
> notifications until the device is fully configured in order to not confuse
> userspace when changing the flags fails and registration has to be undone.
> Once the device is configured, a single NEWLINK message with the full state
> is sent.
> 
> The individual patch changelogs describe the necessary changes in more detail.

All applied, but two things:

1) This patch set was harder to review because there were no
   default initializations of the new enumeration you added
   to struct netdev.

   I know RTNL_LINK_INITIALIZED is probably zero by C enumeration
   rules, and the zeroing out of new netdev objects gives us this,
   but I only figured that out after some time.

   It deserved at least a commit message mention in patch #2.

2) I would really appreciate you forming your patch postings
   properly.  I have to edit them every single time

   You put the whole output of "git show" or "git format-patch" into
   your email body.  That doesn't work, we don't want all of those
   commit ID etc. lines in there.  It also causes every line of your
   commit messages to be indented by 4 spaces.

   Your email body should just contain the unindented commit message
   and the signoffs, then the patch itself.

   Your Subject lines are also not setup properly.  Because the
   "net X/N:" thing isn't in [] brackets, it ends up in the
   commit message header lines when I feed your emails to
   "git am".

   All of this could be avoided if you used git send-email but
   I realize that a lot of people dislike that for one reason
   or another (myself included), but if you're going to compose
   the emails by hand you ought to make it look the same (syntax
   wise) as what git send-email would have emitted.

Thanks!

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: net: rtnetlink: support specifying device flags on device creation
  2010-02-27 10:51 ` net: " David Miller
@ 2010-03-01 15:24   ` Patrick McHardy
  0 siblings, 0 replies; 7+ messages in thread
From: Patrick McHardy @ 2010-03-01 15:24 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

David Miller wrote:
> From: Patrick McHardy <kaber@trash.net>
> Date: Fri, 26 Feb 2010 17:34:49 +0100 (MET)
> 
>> The following patches add support to specify the device flags (like UP) when
>> creating a new device through rtnl_link. This requires to surpress netlink
>> notifications until the device is fully configured in order to not confuse
>> userspace when changing the flags fails and registration has to be undone.
>> Once the device is configured, a single NEWLINK message with the full state
>> is sent.
>>
>> The individual patch changelogs describe the necessary changes in more detail.
> 
> All applied, but two things:
> 
> 1) This patch set was harder to review because there were no
>    default initializations of the new enumeration you added
>    to struct netdev.
> 
>    I know RTNL_LINK_INITIALIZED is probably zero by C enumeration
>    rules, and the zeroing out of new netdev objects gives us this,
>    but I only figured that out after some time.
> 
>    It deserved at least a commit message mention in patch #2.

Agreed. The reason to use the value 0 for RTNL_LINK_INITIALIZED
was that it avoids touching drivers that can register netdevices
through non rtnl_link paths, like bonding, ifb or dummy.

> 2) I would really appreciate you forming your patch postings
>    properly.  I have to edit them every single time
> 
>    You put the whole output of "git show" or "git format-patch" into
>    your email body.  That doesn't work, we don't want all of those
>    commit ID etc. lines in there.  It also causes every line of your
>    commit messages to be indented by 4 spaces.
> 
>    Your email body should just contain the unindented commit message
>    and the signoffs, then the patch itself.
> 
>    Your Subject lines are also not setup properly.  Because the
>    "net X/N:" thing isn't in [] brackets, it ends up in the
>    commit message header lines when I feed your emails to
>    "git am".
> 
>    All of this could be avoided if you used git send-email but
>    I realize that a lot of people dislike that for one reason
>    or another (myself included), but if you're going to compose
>    the emails by hand you ought to make it look the same (syntax
>    wise) as what git send-email would have emitted.

I'll either switch to git-send-email or make sure my script
works properly with git-am.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-03-01 15:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-26 16:34 net: rtnetlink: support specifying device flags on device creation Patrick McHardy
2010-02-26 16:34 ` net 01/04: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event() Patrick McHardy
2010-02-26 16:34 ` net 02/04: rtnetlink: handle rtnl_link netlink notifications manually Patrick McHardy
2010-02-26 16:34 ` net 03/04: dev: support deferring device flag change notifications Patrick McHardy
2010-02-26 16:34 ` net 04/04: rtnetlink: support specifying device flags on device creation Patrick McHardy
2010-02-27 10:51 ` net: " David Miller
2010-03-01 15:24   ` Patrick McHardy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.