[PATCH net-next v2] netconsole: Enable live renaming for network interfaces used by netconsole

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch enables support for live renaming of network interfaces
initialized by netconsole.

This resolves an issue seen when netconsole is configured to boot as a
built-in kernel module with a kernel boot argument. As stated in the
kernel man page - As a built-in, netconsole initializes immediately
after NIC cards and will bring up the specified interface as soon as
possible. Consequently, the renaming of specified interfaces will fail
and return EBUSY. This is because by default, the kernel disallows live
renaming unless the device explicitly sets a priv_flags bit
(e.g: IFF_LIVE_RENAME_OK or IFF_LIVE_ADDR_CHANGE), and so renaming after
a network interface is up returns EBUSY.

The changes to the kernel are as of following:

- Addition of a iface_live_renaming boolean flag to the netpoll struct,
used to enable/disable interface live renaming. False by default
- Changes to check for the aforementioned flag in network and ethernet
driver interface renaming code
- Adds a new optional "*" parameter to the netconsole configuration
string that enables interface live renaming when included
(e.g. netconsole=+*....). When this optional parameter is included,
"iface_live_renaming" is set to true

Signed-off-by: Andy Ren <andy.ren@xxxxxxxxxxxxx>
---
 Documentation/networking/netconsole.rst |  7 ++++---
 drivers/net/netconsole.c                |  5 +++++
 include/linux/netpoll.h                 |  3 +++
 net/core/dev.c                          |  3 ++-
 net/core/netpoll.c                      | 15 +++++++++++++++
 net/ethernet/eth.c                      |  5 ++++-
 6 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/Documentation/networking/netconsole.rst b/Documentation/networking/netconsole.rst
index 1f5c4a04027c..01a45f38ce3f 100644
--- a/Documentation/networking/netconsole.rst
+++ b/Documentation/networking/netconsole.rst
@@ -34,10 +34,11 @@ Sender and receiver configuration:
 It takes a string configuration parameter "netconsole" in the
 following format::
 
- netconsole=[+][src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]
+ netconsole=[+][*][src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]
 
    where
 	+             if present, enable extended console support
+	*             if present, allow runtime network interface renaming
 	src-port      source for UDP packets (defaults to 6665)
 	src-ip        source IP to use (interface address)
 	dev           network interface (eth0)
@@ -47,7 +48,7 @@ following format::
 
 Examples::
 
- linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
+ linux netconsole=*4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
 
 or::
 
@@ -158,7 +159,7 @@ If '+' is prefixed to the configuration line or "extended" config file
 is set to 1, extended console support is enabled. An example boot
 param follows::
 
- linux netconsole=+4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
+ linux netconsole=+*4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
 
 Log messages are transmitted with extended metadata header in the
 following format which is the same as /dev/kmsg::
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index bdff9ac5056d..dea5b783744f 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -188,6 +188,11 @@ static struct netconsole_target *alloc_param_target(char *target_config)
 		target_config++;
 	}
 
+	if (*target_config == '*') {
+		nt->np.iface_live_renaming = true;
+		target_config++;
+	}
+
 	/* Parse parameters and setup netpoll */
 	err = netpoll_parse_options(&nt->np, target_config);
 	if (err)
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index bd19c4b91e31..f2ebdabf0959 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -32,6 +32,7 @@ struct netpoll {
 	bool ipv6;
 	u16 local_port, remote_port;
 	u8 remote_mac[ETH_ALEN];
+	bool iface_live_renaming;
 };
 
 struct netpoll_info {
@@ -51,9 +52,11 @@ struct netpoll_info {
 void netpoll_poll_dev(struct net_device *dev);
 void netpoll_poll_disable(struct net_device *dev);
 void netpoll_poll_enable(struct net_device *dev);
+bool netpoll_live_renaming_enabled(struct net_device *dev);
 #else
 static inline void netpoll_poll_disable(struct net_device *dev) { return; }
 static inline void netpoll_poll_enable(struct net_device *dev) { return; }
+static inline bool netpoll_live_renaming_enabled(struct net_device *dev) { return false; }
 #endif
 
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
diff --git a/net/core/dev.c b/net/core/dev.c
index 2e4f1c97b59e..90e6870d38d0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1176,7 +1176,8 @@ int dev_change_name(struct net_device *dev, const char *newname)
 	 * directly.
 	 */
 	if (dev->flags & IFF_UP &&
-	    likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK)))
+	    likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK) &&
+		   !netpoll_live_renaming_enabled(dev)))
 		return -EBUSY;
 
 	down_write(&devnet_rename_sem);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9be762e1d042..a22319676667 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -224,6 +224,21 @@ void netpoll_poll_enable(struct net_device *dev)
 }
 EXPORT_SYMBOL(netpoll_poll_enable);
 
+bool netpoll_live_renaming_enabled(struct net_device *dev)
+{
+	struct netpoll_info *ni;
+	bool live_renaming_enabled = false;
+
+	rcu_read_lock();
+	ni = rcu_dereference(dev->npinfo);
+	if (ni && ni->netpoll->iface_live_renaming)
+		live_renaming_enabled = true;
+	rcu_read_unlock();
+
+	return live_renaming_enabled;
+}
+EXPORT_SYMBOL(netpoll_live_renaming_enabled);
+
 static void refill_skbs(void)
 {
 	struct sk_buff *skb;
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index e02daa74e833..bb341acfcf05 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -62,6 +62,7 @@
 #include <net/gro.h>
 #include <linux/uaccess.h>
 #include <net/pkt_sched.h>
+#include <linux/netpoll.h>
 
 /**
  * eth_header - create the Ethernet header
@@ -288,8 +289,10 @@ int eth_prepare_mac_addr_change(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
 
-	if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev))
+	if (!(dev->priv_flags & IFF_LIVE_ADDR_CHANGE) && netif_running(dev) &&
+	    !netpoll_live_renaming_enabled(dev))
 		return -EBUSY;
+
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 	return 0;
-- 
2.38.1




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux