[PATCH] net/netconsole: Support VLAN for netconsole

From: Libing Zhou
Date: Thu Dec 10 2020 - 05:09:37 EST


During kernel startup phase, current netconsole doesn’t support VLAN
since there is no VLAN interface setup already.

This patch provides VLAN ID and PCP as optional boot/module parameters
to support VLAN environment, thus kernel startup log can be retrieved
via VLAN.

Signed-off-by: Libing Zhou <libing.zhou@xxxxxxxxxxxxxxx>
---
Documentation/networking/netconsole.rst | 10 ++++-
drivers/net/netconsole.c | 3 +-
include/linux/netpoll.h | 3 ++
net/core/netpoll.c | 58 ++++++++++++++++++++++++-
4 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/Documentation/networking/netconsole.rst b/Documentation/networking/netconsole.rst
index 1f5c4a04027c..a08387fcc3f0 100644
--- a/Documentation/networking/netconsole.rst
+++ b/Documentation/networking/netconsole.rst
@@ -13,6 +13,8 @@ IPv6 support by Cong Wang <xiyou.wangcong@xxxxxxxxx>, Jan 1 2013

Extended console support by Tejun Heo <tj@xxxxxxxxxx>, May 1 2015

+VLAN support by Libing Zhou <libing.zhou@xxxxxxxxxxxxxxx>, Dec 8 2020
+
Please send bug reports to Matt Mackall <mpm@xxxxxxxxxxx>
Satyam Sharma <satyam.sharma@xxxxxxxxx>, and Cong Wang <xiyou.wangcong@xxxxxxxxx>

@@ -34,7 +36,7 @@ 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][-V<vid:pcp>]

where
+ if present, enable extended console support
@@ -44,11 +46,17 @@ following format::
tgt-port port for logging agent (6666)
tgt-ip IP address for logging agent
tgt-macaddr ethernet MAC address for logging agent (broadcast)
+ -V if present, enable VLAN support
+ vid:pcp VLAN identifier and priority code point

Examples::

linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc

+or using VLAN::
+
+ linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc-V100:1
+
or::

insmod netconsole netconsole=@/,@10.0.0.2/
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 92001f7af380..f0690cd6a744 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -36,7 +36,6 @@
#include <linux/inet.h>
#include <linux/configfs.h>
#include <linux/etherdevice.h>
-
MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@xxxxxxxxxxx>");
MODULE_DESCRIPTION("Console driver for network interfaces");
MODULE_LICENSE("GPL");
@@ -46,7 +45,7 @@ MODULE_LICENSE("GPL");

static char config[MAX_PARAM_LENGTH];
module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
-MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
+MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr][-V<vid:pcp>]");

static bool oops_only = false;
module_param(oops_only, bool, 0600);
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index e6a2d72e0dc7..8ab3f25cadae 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -31,6 +31,9 @@ struct netpoll {
bool ipv6;
u16 local_port, remote_port;
u8 remote_mac[ETH_ALEN];
+ bool vlan_present;
+ u16 vlan_id;
+ u8 pcp;
};

struct netpoll_info {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 2338753e936b..077a7aec51ae 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -478,6 +478,14 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)

skb->dev = np->dev;

+ if (np->vlan_present) {
+ skb->vlan_proto = htons(ETH_P_8021Q);
+
+ /* htons for tci is done in __vlan_insert_inner_tag, not here */
+ skb->vlan_tci = (np->pcp << VLAN_PRIO_SHIFT) + (np->vlan_id & VLAN_VID_MASK);
+ skb->vlan_present = 1;
+ }
+
netpoll_send_skb(np, skb);
}
EXPORT_SYMBOL(netpoll_send_udp);
@@ -496,6 +504,11 @@ void netpoll_print_options(struct netpoll *np)
else
np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
np_info(np, "remote ethernet address %pM\n", np->remote_mac);
+
+ if (np->vlan_present) {
+ np_info(np, "vlan id %d\n", np->vlan_id);
+ np_info(np, "pcp %d\n", np->pcp);
+ }
}
EXPORT_SYMBOL(netpoll_print_options);

@@ -587,10 +600,46 @@ int netpoll_parse_options(struct netpoll *np, char *opt)

if (*cur != 0) {
/* MAC address */
- if (!mac_pton(cur, np->remote_mac))
+ delim = strchr(cur, '-');
+ if (delim)
+ *delim = 0;
+ if (*cur != 0) {
+ if (!mac_pton(cur, np->remote_mac))
+ goto parse_failed;
+ }
+ if (!delim)
+ goto parse_done;
+ }
+
+ cur = delim + 1;
+ if (*cur == 'V') {
+ /* vlan id */
+ cur++;
+ delim = strchr(cur, ':');
+ if (!delim)
+ goto parse_failed;
+ np->vlan_present = 1;
+ *delim = 0;
+ if (kstrtou16(cur, 10, &np->vlan_id))
goto parse_failed;
+ if (np->vlan_id > 4094) {
+ np_info(np, "error: set vlan id: %d is illegal, allowed range 0-4094\n",
+ np->vlan_id);
+ return -1;
+ }
+ cur = delim + 1;
+
+ /* vlan pcp */
+ if (kstrtou8(cur, 10, &np->pcp))
+ goto parse_failed;
+ if (np->pcp > 7) {
+ np_info(np, "error: set pcp value: %d is illegal, allowed range 0-7\n",
+ np->pcp);
+ return -1;
+ }
}

+ parse_done:
netpoll_print_options(np);

return 0;
@@ -671,6 +720,13 @@ int netpoll_setup(struct netpoll *np)
err = -ENODEV;
goto unlock;
}
+ if (is_vlan_dev(ndev) && np->vlan_present) {
+ np_err(np, "%s is vlan interface already, can't support with extra vlan parameter\n",
+ np->dev_name);
+ err = -ENODEV;
+ goto unlock;
+ }
+
dev_hold(ndev);

if (netdev_master_upper_dev_get(ndev)) {
--
2.25.1