net: lwip: fix initialization sequence before a command
authorJerome Forissier <jerome.forissier@linaro.org>
Tue, 15 Apr 2025 21:17:36 +0000 (23:17 +0200)
committerJerome Forissier <jerome.forissier@linaro.org>
Wed, 23 Apr 2025 08:02:49 +0000 (10:02 +0200)
The things that are done prior to executing a network command with
NET_LWIP are not consistent with what is done with NET. It impacts the
selection of the current device, and more precisely if the active device
is invalid NET would return an error while NET_LWIP would try to pick a
new device. This incorrect behavior was detected thanks to the eth_rotate
sandbox test (dm_test_eth_rotate()).

Fix it by re-using a sequence similar to what NET has in net_loop().
This piece of code is inserted in a function called net_lwip_eth_start()
renamed from net_lwip_eth_set_current().

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
include/net-lwip.h
net/lwip/dhcp.c
net/lwip/dns.c
net/lwip/net-lwip.c
net/lwip/ping.c
net/lwip/tftp.c
net/lwip/wget.c

index 64e5c72..0d3bb8a 100644 (file)
@@ -10,7 +10,14 @@ enum proto_t {
        TFTPGET
 };
 
-void net_lwip_set_current(void);
+static inline int eth_is_on_demand_init(void)
+{
+       return 1;
+}
+
+int eth_init_state_only(void); /* Set active state */
+
+int net_lwip_eth_start(void);
 struct netif *net_lwip_new_netif(struct udevice *udev);
 struct netif *net_lwip_new_netif_noip(struct udevice *udev);
 void net_lwip_remove_netif(struct netif *netif);
index 3b7e470..92bd706 100644 (file)
@@ -115,7 +115,8 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        int ret;
        struct udevice *dev;
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0)
+               return CMD_RET_FAILURE;
 
        dev = eth_get_dev();
        if (!dev) {
index 149bdb7..19172ac 100644 (file)
@@ -121,7 +121,8 @@ int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        if (argc == 3)
                var = argv[2];
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0)
+               return CMD_RET_FAILURE;
 
        return dns_loop(eth_get_dev(), name, var);
 }
index 6b7b696..6748008 100644 (file)
@@ -134,18 +134,27 @@ static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
        return 0;
 }
 
-/* Initialize the lwIP stack and the ethernet devices and set current device  */
-void net_lwip_set_current(void)
+/*
+ * Initialize the network stack if needed and start the current device if valid
+ */
+int net_lwip_eth_start(void)
 {
-       static bool init_done;
-
-       if (!init_done) {
-               eth_init_rings();
-               eth_init();
-               lwip_init();
-               init_done = true;
+       int ret;
+
+       net_init();
+       if (eth_is_on_demand_init()) {
+               eth_halt();
+               eth_set_current();
+               ret = eth_init();
+               if (ret < 0) {
+                       eth_halt();
+                       return ret;
+               }
+       } else {
+               eth_init_state_only();
        }
-       eth_set_current();
+
+       return 0;
 }
 
 static struct netif *new_netif(struct udevice *udev, bool with_ip)
@@ -224,11 +233,20 @@ void net_lwip_remove_netif(struct netif *netif)
        free(netif);
 }
 
+/*
+ * Initialize the network buffers, an ethernet device, and the lwIP stack
+ * (once).
+ */
 int net_init(void)
 {
-       eth_set_current();
+       static bool init_done;
 
-       net_lwip_new_netif(eth_get_dev());
+       if (!init_done) {
+               eth_init_rings();
+               eth_init();
+               lwip_init();
+               init_done = true;
+       }
 
        return 0;
 }
index c586a96..542ef2c 100644 (file)
@@ -168,7 +168,8 @@ int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
        if (!ipaddr_aton(argv[1], &addr))
                return CMD_RET_USAGE;
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0)
+               return CMD_RET_FAILURE;
 
        if (ping_loop(eth_get_dev(), &addr) < 0)
                return CMD_RET_FAILURE;
index 123d66b..4f9b204 100644 (file)
@@ -280,7 +280,10 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
                goto out;
        }
 
-       net_lwip_set_current();
+       if (net_lwip_eth_start() < 0) {
+               ret = CMD_RET_FAILURE;
+               goto out;
+       }
 
        if (tftp_loop(eth_get_dev(), laddr, fname, srvip, port) < 0)
                ret = CMD_RET_FAILURE;
index ec09814..a3b8290 100644 (file)
@@ -471,7 +471,11 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
 
 int wget_do_request(ulong dst_addr, char *uri)
 {
-       net_lwip_set_current();
+       int ret;
+
+       ret = net_lwip_eth_start();
+       if (ret < 0)
+               return ret;
 
        if (!wget_info)
                wget_info = &default_wget_info;