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

Reply via email to