[PATCH 02/10] net: split netconsole transport from stdio frontend

James Hilliard <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <20260825-submit-lwip-runtime-netconsole-v1-v1-2-0892966aa758@gmail.com>
Netconsole's environment handling, input buffer and stdio registration
do not depend on a particular network stack. Packet transmission and
polling do.

Move the existing net_loop and raw-packet code into a legacy transport
file. This leaves legacy behavior unchanged and provides a transport
interface for other network stacks.

Signed-off-by: James Hilliard <[email protected]>
---
 drivers/net/Makefile            |   5 +-
 drivers/net/netconsole-legacy.c | 156 ++++++++++++++++++++++++++++++++++
 drivers/net/netconsole.c        | 184 ++++++++--------------------------------
 drivers/net/netconsole.h        |  29 +++++++
 4 files changed, 226 insertions(+), 148 deletions(-)

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4c1f4094ab2..32bf86e14ae 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -82,7 +82,10 @@ obj-$(CONFIG_MVGBE) += mvgbe.o
 obj-$(CONFIG_MVMDIO) += mvmdio.o
 obj-$(CONFIG_MVNETA) += mvneta.o
 obj-$(CONFIG_MVPP2) += mvpp2.o
-obj-$(CONFIG_NETCONSOLE) += netconsole.o
+ifdef CONFIG_NETCONSOLE
+obj-y += netconsole.o
+obj-$(CONFIG_NET_LEGACY) += netconsole-legacy.o
+endif
 obj-$(CONFIG_NET_NPCM750) += npcm750_eth.o
 obj-$(CONFIG_NET_OCTEON) += octeon/
 obj-$(CONFIG_NET_OCTEONTX) += octeontx/
diff --git a/drivers/net/netconsole-legacy.c b/drivers/net/netconsole-legacy.c
new file mode 100644
index 00000000000..c3c69a94a21
--- /dev/null
+++ b/drivers/net/netconsole-legacy.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, [email protected].
+ */
+
+#include <log.h>
+#include <net.h>
+
+#include "netconsole.h"
+
+static int net_timeout;
+static uchar nc_ether[ARP_HLEN];
+static const char *output_packet;
+static int output_packet_len;
+
+/*
+ * Start with a default last protocol.
+ * We are only interested in NETCONS or not.
+ */
+enum proto_t net_loop_last_protocol = BOOTP;
+
+static void nc_wait_arp_handler(uchar *pkt, unsigned int dest,
+				struct in_addr sip, unsigned int src,
+				unsigned int len)
+{
+	net_set_state(NETLOOP_SUCCESS);
+}
+
+static void nc_handler(uchar *pkt, unsigned int dest, struct in_addr sip,
+		       unsigned int src, unsigned int len)
+{
+	if (nc_has_input())
+		net_set_state(NETLOOP_SUCCESS);
+}
+
+static void nc_timeout_handler(void)
+{
+	net_set_state(NETLOOP_SUCCESS);
+}
+
+static int nc_legacy_refresh_settings(void)
+{
+	int ret;
+
+	ret = nc_refresh_settings_from_env();
+	if (ret <= 0)
+		return ret;
+
+	if (nc_is_broadcast(nc_settings.ip))
+		memset(nc_ether, 0xff, sizeof(nc_ether));
+	else
+		memset(nc_ether, 0, sizeof(nc_ether));
+
+	return 0;
+}
+
+/**
+ * nc_start() - Configure the legacy network loop for netconsole
+ *
+ * Called from net_loop() before processing each packet.
+ */
+void nc_start(void)
+{
+	nc_legacy_refresh_settings();
+	if (!output_packet_len || memcmp(nc_ether, net_null_ethaddr, ARP_HLEN)) {
+		net_set_udp_handler(nc_handler);
+		net_set_timeout_handler(net_timeout, nc_timeout_handler);
+	} else {
+		uchar *pkt;
+
+		net_set_arp_handler(nc_wait_arp_handler);
+		pkt = (uchar *)net_tx_packet + net_eth_hdr_size() +
+			IP_UDP_HDR_SIZE;
+		memcpy(pkt, output_packet, output_packet_len);
+		net_send_udp_packet(nc_ether, nc_settings.ip,
+				    nc_settings.out_port, nc_settings.in_port,
+				    output_packet_len);
+	}
+}
+
+void nc_transport_send(const char *buf, int len)
+{
+	struct udevice *eth;
+	int inited = 0;
+	uchar *pkt;
+
+	debug_cond(DEBUG_DEV_PKT, "output: \"%*.*s\"\n", len, len, buf);
+
+	eth = eth_get_dev();
+	if (!eth)
+		return;
+
+	if (!memcmp(nc_ether, net_null_ethaddr, ARP_HLEN)) {
+		if (eth_is_active(eth))
+			return;
+		output_packet = buf;
+		output_packet_len = len;
+		nc_set_input_recursion(true);
+		net_loop(NETCONS);
+		nc_set_input_recursion(false);
+		output_packet_len = 0;
+		return;
+	}
+
+	if (!eth_is_active(eth)) {
+		if (eth_is_on_demand_init()) {
+			if (eth_init() < 0)
+				return;
+			eth_set_last_protocol(NETCONS);
+		} else {
+			eth_init_state_only();
+		}
+
+		inited = 1;
+	}
+
+	pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE;
+	memcpy(pkt, buf, len);
+	net_send_udp_packet(nc_ether, nc_settings.ip, nc_settings.out_port,
+			    nc_settings.in_port, len);
+
+	if (inited) {
+		if (eth_is_on_demand_init())
+			eth_halt();
+		else
+			eth_halt_state_only();
+	}
+}
+
+void nc_transport_poll(bool block)
+{
+	struct udevice *eth = eth_get_dev();
+
+	if (eth_is_active(eth))
+		return;
+
+	net_timeout = block ? 0 : 1;
+	net_loop(NETCONS);
+}
+
+int nc_transport_start(void)
+{
+	int ret;
+
+	ret = nc_legacy_refresh_settings();
+	if (ret)
+		return ret;
+
+	return net_init();
+}
+
+int nc_transport_stop(void)
+{
+	return 0;
+}
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index c2ce4a80d12..305a6cf12c6 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -4,13 +4,14 @@
  * Wolfgang Denk, DENX Software Engineering, [email protected].
  */
 
-#include <command.h>
 #include <env.h>
 #include <log.h>
 #include <stdio_dev.h>
 #include <net.h>
 #include <vsprintf.h>
 
+#include "netconsole.h"
+
 #ifndef CFG_NETCONSOLE_BUFFER_SIZE
 #define CFG_NETCONSOLE_BUFFER_SIZE 512
 #endif
@@ -20,39 +21,9 @@ static int input_size; /* char count in input buffer */
 static int input_offset; /* offset to valid chars in input buffer */
 static int input_recursion;
 static int output_recursion;
-static int net_timeout;
-static uchar nc_ether[6]; /* server enet address */
-static struct in_addr nc_ip; /* server ip */
-static short nc_out_port; /* target output port */
-static short nc_in_port; /* source input port */
-static const char *output_packet; /* used by first send udp */
-static int output_packet_len;
-/*
- * Start with a default last protocol.
- * We are only interested in NETCONS or not.
- */
-enum proto_t net_loop_last_protocol = BOOTP;
-
-static void nc_wait_arp_handler(uchar *pkt, unsigned dest,
-				 struct in_addr sip, unsigned src,
-				 unsigned len)
-{
-	net_set_state(NETLOOP_SUCCESS); /* got arp reply - quit net loop */
-}
+struct nc_settings nc_settings;
 
-static void nc_handler(uchar *pkt, unsigned dest, struct in_addr sip,
-		       unsigned src, unsigned len)
-{
-	if (input_size)
-		net_set_state(NETLOOP_SUCCESS); /* got input - quit net loop */
-}
-
-static void nc_timeout_handler(void)
-{
-	net_set_state(NETLOOP_SUCCESS);
-}
-
-static int is_broadcast(struct in_addr ip)
+bool nc_is_broadcast(struct in_addr ip)
 {
 	static struct in_addr netmask;
 	static struct in_addr our_ip;
@@ -73,7 +44,7 @@ static int is_broadcast(struct in_addr ip)
 		 (netmask.s_addr | ip.s_addr) == ~0)); /* bcast to our net */
 }
 
-static int refresh_settings_from_env(void)
+int nc_refresh_settings_from_env(void)
 {
 	const char *p;
 	static int env_changed_id;
@@ -82,56 +53,41 @@ static int refresh_settings_from_env(void)
 	/* update only when the environment has changed */
 	if (env_changed_id != env_id) {
 		char *tmp = env_get("ncip");
+
 		if (tmp) {
-			nc_ip = string_to_ip(tmp);
-			if (!nc_ip.s_addr)
+			nc_settings.ip = string_to_ip(tmp);
+			if (!nc_settings.ip.s_addr)
 				return -1;	/* ncip is 0.0.0.0 */
 			p = strchr(tmp, ':');
 			if (p != NULL) {
-				nc_out_port = dectoul(p + 1, NULL);
-				nc_in_port = nc_out_port;
+				nc_settings.out_port = dectoul(p + 1, NULL);
+				nc_settings.in_port = nc_settings.out_port;
 			}
 		} else {
-			nc_ip.s_addr = ~0; /* ncip is not set, so broadcast */
+			nc_settings.ip.s_addr = ~0;
 		}
 
 		p = env_get("ncoutport");
 		if (p != NULL)
-			nc_out_port = dectoul(p, NULL);
+			nc_settings.out_port = dectoul(p, NULL);
 		p = env_get("ncinport");
 		if (p != NULL)
-			nc_in_port = dectoul(p, NULL);
-
-		if (is_broadcast(nc_ip))
-			/* broadcast MAC address */
-			memset(nc_ether, 0xff, sizeof(nc_ether));
-		else
-			/* force arp request */
-			memset(nc_ether, 0, sizeof(nc_ether));
+			nc_settings.in_port = dectoul(p, NULL);
+
+		return 1;
 	}
+
 	return 0;
 }
 
-/**
- * Called from net_loop in net/net.c before each packet
- */
-void nc_start(void)
+bool nc_has_input(void)
 {
-	refresh_settings_from_env();
-	if (!output_packet_len || memcmp(nc_ether, net_null_ethaddr, 6)) {
-		/* going to check for input packet */
-		net_set_udp_handler(nc_handler);
-		net_set_timeout_handler(net_timeout, nc_timeout_handler);
-	} else {
-		/* send arp request */
-		uchar *pkt;
-		net_set_arp_handler(nc_wait_arp_handler);
-		pkt = (uchar *)net_tx_packet + net_eth_hdr_size() +
-			IP_UDP_HDR_SIZE;
-		memcpy(pkt, output_packet, output_packet_len);
-		net_send_udp_packet(nc_ether, nc_ip, nc_out_port, nc_in_port,
-				    output_packet_len);
-	}
+	return input_size != 0;
+}
+
+void nc_set_input_recursion(bool enable)
+{
+	input_recursion = enable;
 }
 
 int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
@@ -139,10 +95,11 @@ int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
 {
 	int end, chunk;
 
-	if (dest_port != nc_in_port || !len)
+	if (dest_port != nc_settings.in_port || !len)
 		return 0; /* not for us */
 
-	if (src_ip.s_addr != nc_ip.s_addr && !is_broadcast(nc_ip))
+	if (src_ip.s_addr != nc_settings.ip.s_addr &&
+	    !nc_is_broadcast(nc_settings.ip))
 		return 0; /* not from our client */
 
 	debug_cond(DEBUG_DEV_PKT, "input: \"%*.*s\"\n", len, len, pkt);
@@ -171,75 +128,17 @@ int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
 	return 1;
 }
 
-static void nc_send_packet(const char *buf, int len)
+static int nc_stdio_start(struct stdio_dev *dev)
 {
-	struct udevice *eth;
-	int inited = 0;
-	uchar *pkt;
-	uchar *ether;
-	struct in_addr ip;
-
-	debug_cond(DEBUG_DEV_PKT, "output: \"%*.*s\"\n", len, len, buf);
-
-	eth = eth_get_dev();
-	if (eth == NULL)
-		return;
+	nc_settings.out_port = 6666;
+	nc_settings.in_port = nc_settings.out_port;
 
-	if (!memcmp(nc_ether, net_null_ethaddr, 6)) {
-		if (eth_is_active(eth))
-			return;	/* inside net loop */
-		output_packet = buf;
-		output_packet_len = len;
-		input_recursion = 1;
-		net_loop(NETCONS); /* wait for arp reply and send packet */
-		input_recursion = 0;
-		output_packet_len = 0;
-		return;
-	}
-
-	if (!eth_is_active(eth)) {
-		if (eth_is_on_demand_init()) {
-			if (eth_init() < 0)
-				return;
-			eth_set_last_protocol(NETCONS);
-		} else {
-			eth_init_state_only();
-		}
-
-		inited = 1;
-	}
-	pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE;
-	memcpy(pkt, buf, len);
-	ether = nc_ether;
-	ip = nc_ip;
-	net_send_udp_packet(ether, ip, nc_out_port, nc_in_port, len);
-
-	if (inited) {
-		if (eth_is_on_demand_init())
-			eth_halt();
-		else
-			eth_halt_state_only();
-	}
+	return nc_transport_start();
 }
 
-static int nc_stdio_start(struct stdio_dev *dev)
+static int nc_stdio_stop(struct stdio_dev *dev)
 {
-	int retval;
-
-	nc_out_port = 6666; /* default port */
-	nc_in_port = nc_out_port;
-
-	retval = refresh_settings_from_env();
-	if (retval != 0)
-		return retval;
-
-	/*
-	 * Initialize the static IP settings and buffer pointers
-	 * incase we call net_send_udp_packet before net_loop
-	 */
-	net_init();
-
-	return 0;
+	return nc_transport_stop();
 }
 
 static void nc_stdio_putc(struct stdio_dev *dev, char c)
@@ -248,7 +147,7 @@ static void nc_stdio_putc(struct stdio_dev *dev, char c)
 		return;
 	output_recursion = 1;
 
-	nc_send_packet(&c, 1);
+	nc_transport_send(&c, 1);
 
 	output_recursion = 0;
 }
@@ -264,7 +163,7 @@ static void nc_stdio_puts(struct stdio_dev *dev, const char *s)
 	len = strlen(s);
 	while (len) {
 		int send_len = min(len, (int)sizeof(input_buffer));
-		nc_send_packet(s, send_len);
+		nc_transport_send(s, send_len);
 		len -= send_len;
 		s += send_len;
 	}
@@ -278,9 +177,8 @@ static int nc_stdio_getc(struct stdio_dev *dev)
 
 	input_recursion = 1;
 
-	net_timeout = 0;	/* no timeout */
 	while (!input_size)
-		net_loop(NETCONS);
+		nc_transport_poll(true);
 
 	input_recursion = 0;
 
@@ -295,23 +193,14 @@ static int nc_stdio_getc(struct stdio_dev *dev)
 
 static int nc_stdio_tstc(struct stdio_dev *dev)
 {
-	struct udevice *eth;
-
 	if (input_recursion)
 		return 0;
 
 	if (input_size)
 		return 1;
 
-	eth = eth_get_dev();
-	if (eth_is_active(eth))
-		return 0;	/* inside net loop */
-
 	input_recursion = 1;
-
-	net_timeout = 1;
-	net_loop(NETCONS);	/* kind of poll */
-
+	nc_transport_poll(false);
 	input_recursion = 0;
 
 	return input_size != 0;
@@ -327,6 +216,7 @@ int drv_nc_init(void)
 	strcpy(dev.name, "nc");
 	dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
 	dev.start = nc_stdio_start;
+	dev.stop = nc_stdio_stop;
 	dev.putc = nc_stdio_putc;
 	dev.puts = nc_stdio_puts;
 	dev.getc = nc_stdio_getc;
diff --git a/drivers/net/netconsole.h b/drivers/net/netconsole.h
new file mode 100644
index 00000000000..b2c3ecee6dd
--- /dev/null
+++ b/drivers/net/netconsole.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __NETCONSOLE_INTERNAL_H
+#define __NETCONSOLE_INTERNAL_H
+
+#include <linux/types.h>
+#include <net-common.h>
+
+struct nc_settings {
+	struct in_addr ip;
+	short out_port;
+	short in_port;
+};
+
+extern struct nc_settings nc_settings;
+
+bool nc_has_input(void);
+bool nc_is_broadcast(struct in_addr ip);
+int nc_refresh_settings_from_env(void);
+int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned int dest_port,
+		    unsigned int src_port, unsigned int len);
+void nc_set_input_recursion(bool enable);
+
+int nc_transport_start(void);
+int nc_transport_stop(void);
+void nc_transport_send(const char *buf, int len);
+void nc_transport_poll(bool block);
+
+#endif /* __NETCONSOLE_INTERNAL_H */

-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.