Skip to contentSkip to conversation

netconsole: Add tty driver

PATCH Superseded Struan Bartlett 3 participants 4 messages Apr 1, 2014 – Apr 2, 2014

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 netconsole: Add tty driver

Adds tty driver to netconsole module. When module is loaded, creates /dev/netcon0 device and enables support for console=netcon0 kernel cmdline option, causing /dev/console output to be sent to /dev/netcon0. This allows startup/shutdown script output from headless platforms to be logged over (secure) network.

To: Matt Mackall <[email protected]>

---

Changes since v1:
* Fixed whitespace mangled by broken mailer

drivers/net/netconsole.c +88 -1
@@ -15,6 +15,7 @@
  *               generic card hooks
  *               works non-modular
  * 2003-09-07    rewritten with netpoll api
+ * 2014-03-31    tty driver by Struan Bartlett
  */
 
 /****************************************************************
@@ -47,6 +48,7 @@
 #include <linux/netpoll.h>
 #include <linux/inet.h>
 #include <linux/configfs.h>
+#include <linux/tty.h>
 
 MODULE_AUTHOR("Maintainer: Matt Mackall <[email protected]>");
 MODULE_DESCRIPTION("Console driver for network interfaces");
@@ -728,7 +730,7 @@ static struct notifier_block netconsole_
 	.notifier_call  = netconsole_netdev_event,
 };
 
-static void write_msg(struct console *con, const char *msg, unsigned int len)
+static void _write_msg(const char *msg, unsigned int len)
 {
 	int frag, left;
 	unsigned long flags;
@@ -764,10 +766,63 @@ static void write_msg(struct console *co
 	spin_unlock_irqrestore(&target_list_lock, flags);
 }
 
+static void write_msg(struct console *con, const char *msg, unsigned int len)
+{
+	_write_msg(msg, len);
+}
+
+static int netconsole_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	return 0;
+}
+
+static void netconsole_tty_close(struct tty_struct *tty, struct file *filp)
+{
+}
+
+static int netconsole_tty_write(struct tty_struct *tty,
+				const unsigned char *buf, int count)
+{
+	_write_msg(buf, count);
+	return count;
+}
+
+static int netconsole_tty_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	char temp[2] = { ch, 0 };
+	_write_msg(temp, 1);
+	return 1;
+}
+
+static int netconsole_tty_write_room(struct tty_struct *tty)
+{
+	return MAX_PRINT_CHUNK;
+}
+
+static const struct tty_operations netconsole_tty_ops = {
+	.open		= netconsole_tty_open,
+	.close		= netconsole_tty_close,
+	.write		= netconsole_tty_write,
+	.put_char	= netconsole_tty_put_char,
+	.write_room	= netconsole_tty_write_room,
+};
+
+static struct tty_port netconsole_tty_port;
+static struct tty_driver *netconsole_tty_driver;
+
+static struct tty_driver *netconsole_device(struct console *co, int *index)
+{
+	if (!(co->flags & CON_ENABLED))
+		return NULL;
+	*index = co->index;
+	return netconsole_tty_driver;
+}
+
 static struct console netconsole = {
 	.name	= "netcon",
 	.flags	= CON_ENABLED,
 	.write	= write_msg,
+	.device = netconsole_device
 };
 
 static int __init init_netconsole(void)
@@ -802,11 +857,39 @@ static int __init init_netconsole(void)
 	if (err)
 		goto undonotifier;
 
+	netconsole_tty_driver = alloc_tty_driver(1);
+	if (!netconsole_tty_driver) {
+		err = -ENOMEM;
+		goto undonotifier;
+	}
+
+	tty_port_init(&netconsole_tty_port);
+
+	netconsole_tty_driver->driver_name = "netcon";
+	netconsole_tty_driver->name = "netcon";
+	netconsole_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	netconsole_tty_driver->subtype = SYSTEM_TYPE_TTY;
+	netconsole_tty_driver->init_termios = tty_std_termios;
+	netconsole_tty_driver->init_termios.c_iflag = 0;
+	netconsole_tty_driver->init_termios.c_oflag = 0;
+	netconsole_tty_driver->flags = TTY_DRIVER_REAL_RAW;
+
+	tty_set_operations(netconsole_tty_driver, &netconsole_tty_ops);
+	tty_port_link_device(&netconsole_tty_port, netconsole_tty_driver, 0);
+
+	err = tty_register_driver(netconsole_tty_driver);
+	if (err)
+		goto undotty;
+
 	register_console(&netconsole);
 	pr_info("network logging started\n");
 
 	return err;
 
+undotty:
+	put_tty_driver(netconsole_tty_driver);
+	tty_port_destroy(&netconsole_tty_port);
+
 undonotifier:
 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
 
@@ -830,6 +913,10 @@ static void __exit cleanup_netconsole(vo
 {
 	struct netconsole_target *nt, *tmp;
 
+	tty_unregister_driver(netconsole_tty_driver);
+	put_tty_driver(netconsole_tty_driver);
+	tty_port_destroy(&netconsole_tty_port);
+
 	unregister_console(&netconsole);
 	dynamic_netconsole_exit();
 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
maintainer
#1 lore raw

From: Struan Bartlett <[email protected]>
Date: Tue, 01 Apr 2014 23:26:27 +0200

Quoted 6 lines

Adds tty driver to netconsole module. When module is loaded, creates /dev/netcon0 device and enables support for console=netcon0 kernel cmdline option, causing /dev/console output to be sent to /dev/netcon0. This allows startup/shutdown script output from headless platforms to be logged over (secure) network.

Quoted 6 lines

To: Matt Mackall <[email protected]>

---

Changes since v1:
* Fixed whitespace mangled by broken mailer

It's still not submitted cleanly, look at what it looks like in patchwork:

http://patchwork.ozlabs.org/patch/336171/

#2 lore raw
In reply to Struan Bartlett
Quoted 5 lines · Struan Bartlett

Adds tty driver to netconsole module. When module is loaded, creates /dev/netcon0 device and enables support for console=netcon0 kernel cmdline option, causing /dev/console output to be sent to /dev/netcon0. This allows startup/shutdown script output from headless platforms to be logged over (secure) network.

Excuse me, but I think that the netconsole logging can work only during network interfaces (e.g. eth0) are up. Did this patch description assume that the network interfaces are up before the startup script is started and the shutdown script is finished before the network interfaces are down?

By the way, I uploaded a logger specialized for receiving netconsole messages to http://sourceforge.jp/projects/akari/scm/svn/tree/head/branches/udplogger/ . The shortage of netconsole approach compared to serial console approach is that the netconsole logging cannot work if the network interfaces are down. If we could log kernel messages via the netconsole module while initializing kdump kernel by adding console=netcon0 to kdump kernel's command line, we can utilize netconsole as an alternative tool for logging kernel messages in case initialization of kdump kernel fails.

#3 lore raw
Quoted 11 lines · Tetsuo Handa
Quoted 5 lines · Struan Bartlett

Adds tty driver to netconsole module. When module is loaded, creates /dev/netcon0 device and enables support for console=netcon0 kernel cmdline option, causing /dev/console output to be sent to /dev/netcon0. This allows startup/shutdown script output from headless platforms to be logged over (secure) network.

Excuse me, but I think that the netconsole logging can work only during network interfaces (e.g. eth0) are up. Did this patch description assume that the network interfaces are up before the startup script is started and the shutdown script is finished before the network interfaces are down?

Yes it did. I hope I have clarified that in the v3 patch description. In practice, at least in a Debian environment: i) the netconsole module itself is generally capable of raising the network interface when it is loaded by the initramfs init script (which precedes all /etc/init.d/* scripts); ii) very little of consequence tends to happens during shutdown after networking is stopped; iii) equally, it is not usually problematic to disable the networking shutdown script, since it runs on platforms about to be rebooted or powered off. We do this by editing the Default-Stop LSB header in /etc/init.d/networking.

Quoted 2 lines

By the way, I uploaded a logger specialized for receiving netconsole messages to http://sourceforge.jp/projects/akari/scm/svn/tree/head/branches/udplogger/ .

Thank you. I'll check it out.