U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/12] Introduce the lwIP network stack
@ 2024-06-06 13:35 Jerome Forissier
  2024-06-06 13:35 ` [PATCH v3 01/12] net: introduce alternative implementation as net-lwip/ Jerome Forissier
                   ` (12 more replies)
  0 siblings, 13 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:35 UTC (permalink / raw)
  To: u-boot; +Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier

This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
stack [2] [3] as an alternative to the current implementation in net/,
selectable with Kconfig, and ultimately keep only lwIP if possible. Some
reasons for doing so are:
- Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
has some additional lwIP and Mbed TLS patches to do so. With that it
becomes possible to fetch and launch a distro installer such as Debian
etc. using a secure, authenticated connection directly from the U-Boot
shell. Several use cases:
  * Authentication: prevent MITM attack (third party replacing the
binary with a different one)
  * Confidentiality: prevent third parties from grabbing a copy of the
image as it is being downloaded
  * Allow connection to servers that do not support plain HTTP anymore
(this is becoming more and more common on the Internet these days)
- Possibly benefit from additional features implemented in lwIP
- Less code to maintain in U-Boot

Prior to applying this series, the lwIP stack needs to be added as a
Git subtree with the following command:

 $  git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE

The first patch introduces a new Kconfig symbol: NET_LWIP, which selects
the lwIP implementation instead of the current one (NET). Contrary to the
approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
simultaneously. The rationale is we want to start from a clean state and
not pull potentially duplicated functionality from both stacks. Note
however that a few files are still built in net/, they are the ones
related to ethernet device management and the ethernet bootflow.

The second patch introduces the Makefile to build lwIP when NET_LWIP is
enabled.

The subsequent patches implement various network-oriented commands and
features: dhcp, dns, ping, tftpboot, wget.

NET_LWIP is not enabled by default because it lacks functionality compared
to NET and many CI tests would fail to run or even build.

Some tests (dm dsa/eth) are disabled when NET_LWIP is selected because
they make strong assumptions on how the network stack is implemented and
how the packet flow occurs. For example, an ARP exchange is expected
when an ICMP packet goes out, but with lwIP no exchange will occur if the
host IP is already in the the ARP cache.

Due to the above and in order to provide some level of testing, a new QEMU
configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
as qemu_arm64_lwip_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
Tests are added to test/py/tests/test_net.py for that configuration.

Changes in v3:

- Make NET_LWIP a Kconfig choice in patch "net: introduce alternative
implementation as net-lwip/" (Tom R.)
- Drop the patch introducing lwIP as a Git subtree and document the git
command in the cover letter instead (Tom R.)
- "net-lwip: add TFTP support and tftpboot command": use the same
"Bytes transferred =" message as in the legacy implementation (Tom R.,
Maxim U.)
- Drop "test/py: net: add _lwip variants of dhcp, ping and tftpboot
tests" which is not needed anymore.
- Add missing kfree() calls in cmd/net-common.c and fix the parsing of
decimal address in net-lwip/wget.c (patch "net-lwip: add wget command")
(Maxim U.)
- "net-lwip: add ping command": drop the ICMP payload (Ilias A.). Set
the sequence number to zero when entering ping_loop().

Changes in v2:

** Address comments from Ilias A.

- "net-lwip: add wget command"
Implement the wget_with_dns() function to do most of the wget work and
call it from do_wget(). This allows to simplify patch "net-lwip: add
support for EFI_HTTP_BOOT".

- "net-lwip: import net command from cmd/net.c"
Move a few functions from cmd/net.c to a new file cmd/net-common.c
rather than duplicating then in cmd/net-lwip.c.

- "net-lwip: add support for EFI_HTTP_BOOT"
Since wget_with_dns() is now implemented in "net-lwip: add wget command",
just enable the wget command when the lwIP stack is enabled and
EFI_HTTP_BOOT is requested.

** Address comments from Tom R.

- "net-lwip: add DHCP support and dhcp commmand",
  "net-lwip: add TFTP support and tftpboot command",
  "net-lwip: add ping command",
  "net-lwip: add dns command",
  "net-lwip: add wget command"
Do not introduce new CMD_XXX_LWIP symbols and use existing CMD_XXX
instead.

- "configs: add qemu_arm64_lwip_defconfig"
Use #include <configs/qemu_arm64_defconfig>.

- "net-lwip: import lwIP library under lib/lwip"
Patch removed and replaced by the introduction of a Git subtree:
"Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c3".

Note that I have not yet addressed your comments on "test: dm: dsa,
eth: disable tests when CONFIG_NET_LWIP=y"). I need some more time
for that and I think running CI on this v2 will help better understand
what is needed for v3.

** Miscellaneous improvements

- "net: introduce alternative implementation as net-lwip/":

* Make DFU_OVER_TFTP not DFU_TFTP incompatible with NET_LWIP. It seems
quite natural to supplement "depends on NET" with "&& !NET_LWIP".
* Make PROT_*_LWIP not visible by removing the Kconfig prompt.

[1] https://lore.kernel.org/all/20231127125726.3735-1-maxim.uvarov@linaro.org/
[2] https://www.nongnu.org/lwip/
[3] https://en.wikipedia.org/wiki/LwIP

CC: Javier Tia <javier.tia@linaro.org>

Jerome Forissier (12):
  net: introduce alternative implementation as net-lwip/
  net-lwip: build lwIP
  net-lwip: add DHCP support and dhcp commmand
  net-lwip: add TFTP support and tftpboot command
  net-lwip: add ping command
  net-lwip: add dns command
  net-lwip: add wget command
  test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y
  cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
  configs: add qemu_arm64_lwip_defconfig
  MAINTAINERS: net-lwip: add myself as a maintainer
  CI: add qemu_arm64_lwip to the test matrix

 .azure-pipelines.yml              |   7 +
 Kconfig                           |  40 ++++++
 MAINTAINERS                       |  11 ++
 Makefile                          |   3 +-
 boot/Kconfig                      |   5 +-
 cmd/Kconfig                       |  44 ++++++
 cmd/Makefile                      |   7 +
 cmd/bdinfo.c                      |   5 +-
 cmd/efidebug.c                    |   8 +-
 cmd/net-common.c                  | 115 +++++++++++++++
 cmd/net-lwip.c                    |  49 +++++++
 cmd/net.c                         | 115 ---------------
 common/Kconfig                    |   2 +-
 common/board_r.c                  |   4 +-
 common/spl/Kconfig                |   1 +
 configs/qemu_arm64_lwip_defconfig |   3 +
 drivers/dfu/Kconfig               |   2 +-
 drivers/fastboot/Kconfig          |   4 +-
 drivers/net/Kconfig               |   2 +-
 drivers/net/phy/Kconfig           |   2 +-
 drivers/usb/gadget/Kconfig        |   2 +-
 include/net-lwip.h                | 140 +++++++++++++++++++
 include/net.h                     |   2 +-
 lib/Makefile                      |   2 +
 lib/lwip/Makefile                 |  57 ++++++++
 lib/lwip/u-boot/arch/cc.h         |  43 ++++++
 lib/lwip/u-boot/arch/sys_arch.h   |   0
 lib/lwip/u-boot/limits.h          |   0
 lib/lwip/u-boot/lwipopts.h        | 197 ++++++++++++++++++++++++++
 net-lwip/Kconfig                  |  37 +++++
 net-lwip/Makefile                 |  18 +++
 net-lwip/dhcp.c                   | 114 +++++++++++++++
 net-lwip/dns.c                    | 107 ++++++++++++++
 net-lwip/eth_internal.h           |  35 +++++
 net-lwip/net-lwip.c               | 224 ++++++++++++++++++++++++++++++
 net-lwip/ping.c                   | 163 ++++++++++++++++++++++
 net-lwip/tftp.c                   | 209 ++++++++++++++++++++++++++++
 net-lwip/wget.c                   | 180 ++++++++++++++++++++++++
 net/Kconfig                       |  14 --
 test/dm/dsa.c                     |   2 +
 test/dm/eth.c                     |   4 +
 41 files changed, 1832 insertions(+), 147 deletions(-)
 create mode 100644 cmd/net-common.c
 create mode 100644 cmd/net-lwip.c
 create mode 100644 configs/qemu_arm64_lwip_defconfig
 create mode 100644 include/net-lwip.h
 create mode 100644 lib/lwip/Makefile
 create mode 100644 lib/lwip/u-boot/arch/cc.h
 create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
 create mode 100644 lib/lwip/u-boot/limits.h
 create mode 100644 lib/lwip/u-boot/lwipopts.h
 create mode 100644 net-lwip/Kconfig
 create mode 100644 net-lwip/Makefile
 create mode 100644 net-lwip/dhcp.c
 create mode 100644 net-lwip/dns.c
 create mode 100644 net-lwip/eth_internal.h
 create mode 100644 net-lwip/net-lwip.c
 create mode 100644 net-lwip/ping.c
 create mode 100644 net-lwip/tftp.c
 create mode 100644 net-lwip/wget.c

-- 
2.40.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 01/12] net: introduce alternative implementation as net-lwip/
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
@ 2024-06-06 13:35 ` Jerome Forissier
  2024-06-06 13:35 ` [PATCH v3 02/12] net-lwip: build lwIP Jerome Forissier
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:35 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Lukasz Majewski, Mattijs Korpershoek, Joe Hershberger,
	Ramon Fried, Marek Vasut, Simon Glass, Nathan Barrett-Morrison,
	Shengyu Qu, Jesse Taube, Greg Malysa, Heinrich Schuchardt,
	Sumit Garg, Andrew Davis, Bryan Brattlof, Leon M. Busch-George,
	Samuel Dionne-Riel, Ying Sun, Jagan Teki, Bin Meng,
	Rasmus Villemoes, Joshua Watt, Sean Anderson, Andre Przywara,
	Mayuresh Chitale, Samuel Holland, Oleksandr Suvorov,
	Patrice Chotard, Ashok Reddy Soma, Patrick Delaunay,
	Jaehoon Chung, Svyatoslav Ryhel, Quentin Schulz, Alexey Romanov,
	Ion Agorria, Nicolas Frattaroli, Yanhong Wang, Miquel Raynal,
	Jonas Karlman, Baruch Siach

Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
adding a new net-lwip/ directory and the NET_LWIP symbol. Network
support is either NO_NET, NET (legacy stack) or NET_LWIP. Subsequent
commits will introduce the lwIP code, re-work the NETDEVICE integration
and port some of the NET commands and features to lwIP.

SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
that are part of NET (such as arp_init(), arp_timeout_check(),
arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
added later.

Similarly, DFU_TFTP is not compatible with NET_LWIP because it depends
on net_loop(), tftp_timeout_ms, tftp_timeout_count_max. Let's add a
dependency of DFU_OVER_TFTP on !NET_LWIP for now.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 Kconfig                    | 40 ++++++++++++++++++++++++++++++++++++++
 Makefile                   |  2 +-
 common/Kconfig             |  2 +-
 common/spl/Kconfig         |  1 +
 drivers/dfu/Kconfig        |  2 +-
 drivers/fastboot/Kconfig   |  4 ++--
 drivers/net/phy/Kconfig    |  2 +-
 drivers/usb/gadget/Kconfig |  2 +-
 net-lwip/Kconfig           | 37 +++++++++++++++++++++++++++++++++++
 net/Kconfig                | 14 -------------
 10 files changed, 85 insertions(+), 21 deletions(-)
 create mode 100644 net-lwip/Kconfig

diff --git a/Kconfig b/Kconfig
index 82df59f176e..b7304bd37c5 100644
--- a/Kconfig
+++ b/Kconfig
@@ -745,7 +745,47 @@ source "dts/Kconfig"
 
 source "env/Kconfig"
 
+choice
+	prompt "Networking stack"
+	default NET
+
+config NO_NET
+	bool "No networking support"
+
+config NET
+	bool "Legacy U-Boot networking stack"
+	imply NETDEVICES
+
+config NET_LWIP
+	bool "Use lwIP for networking stack"
+	imply NETDEVICES
+	help
+	  Include networking support based on the lwIP (lightweight IP)
+	  TCP/IP stack (https://nongnu.org/lwip). This is a replacement for
+	  the default U-Boot network stack and applications located in net/
+	  and enabled via CONFIG_NET as well as other pieces of code that
+	  depend on CONFIG_NET (such as cmd/net.c enabled via CONFIG_CMD_NET).
+	  Therefore the two symbols CONFIG_NET and CONFIG_NET_LWIP are mutually
+	  exclusive.
+
+endchoice
+
+if NET
 source "net/Kconfig"
+endif
+
+if NET_LWIP
+source "net-lwip/Kconfig"
+endif
+
+config SYS_RX_ETH_BUFFER
+	int "Number of receive packet buffers"
+	default 4
+	help
+	  Defines the number of Ethernet receive buffers. On some Ethernet
+	  controllers it is recommended to set this value to 8 or even higher,
+	  since all buffers can be full shortly after enabling the interface on
+	  high Ethernet traffic.
 
 source "drivers/Kconfig"
 
diff --git a/Makefile b/Makefile
index f8206b2e30a..ceb99a2698e 100644
--- a/Makefile
+++ b/Makefile
@@ -859,7 +859,7 @@ libs-$(CONFIG_OF_EMBED) += dts/
 libs-y += env/
 libs-y += lib/
 libs-y += fs/
-libs-y += net/
+libs-$(CONFIG_NET) += net/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/common/Kconfig b/common/Kconfig
index 5e3070e9253..807b726384d 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -424,7 +424,7 @@ config LOGF_FUNC_PAD
 
 config LOG_SYSLOG
 	bool "Log output to syslog server"
-	depends on NET
+	depends on NET || NET_LWIP
 	help
 	  Enables a log driver which broadcasts log records via UDP port 514
 	  to syslog servers.
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc1..f67f0a859db 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1055,6 +1055,7 @@ config SPL_DM_SPI_FLASH
 
 config SPL_NET
 	bool "Support networking"
+	depends on !NET_LWIP
 	help
 	  Enable support for network devices (such as Ethernet) in SPL.
 	  This permits SPL to load U-Boot over a network link rather than
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0360d9da142..c6bce82eb10 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -11,7 +11,7 @@ config DFU_OVER_USB
 
 config DFU_OVER_TFTP
 	bool
-	depends on NET
+	depends on NET && !NET_LWIP
 
 if DFU
 config DFU_WRITE_ALT
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 70207573de2..05e988166fb 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -27,7 +27,7 @@ config USB_FUNCTION_FASTBOOT
 	  This enables the USB part of the fastboot gadget.
 
 config UDP_FUNCTION_FASTBOOT
-	depends on NET
+	depends on NET || NET_LWIP
 	select FASTBOOT
 	bool "Enable fastboot protocol over UDP"
 	help
@@ -41,7 +41,7 @@ config UDP_FUNCTION_FASTBOOT_PORT
 	  The fastboot protocol requires a UDP port number.
 
 config TCP_FUNCTION_FASTBOOT
-	depends on NET
+	depends on NET || NET_LWIP
 	select FASTBOOT
 	bool "Enable fastboot protocol over TCP"
 	help
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d96938eaba..738752d29c2 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -11,7 +11,7 @@ config MV88E6352_SWITCH
 
 menuconfig PHYLIB
 	bool "Ethernet PHY (physical media interface) support"
-	depends on NET
+	depends on NET || NET_LWIP
 	help
 	  Enable Ethernet PHY (physical media interface) support.
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 4621a6fd5e6..03fe3bca197 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -224,7 +224,7 @@ endif # USB_GADGET_DOWNLOAD
 
 config USB_ETHER
 	bool "USB Ethernet Gadget"
-	depends on NET
+	depends on NET || NET_LWIP
 	default y if ARCH_SUNXI && USB_MUSB_GADGET
 	help
 	  Creates an Ethernet network device through a USB peripheral
diff --git a/net-lwip/Kconfig b/net-lwip/Kconfig
new file mode 100644
index 00000000000..a0938964b51
--- /dev/null
+++ b/net-lwip/Kconfig
@@ -0,0 +1,37 @@
+#
+# Network configuration (with lwIP stack)
+#
+
+config LWIP_DEBUG
+	bool "Enable debug traces in the lwIP library"
+
+config LWIP_ASSERT
+	bool "Enable assertions in the lwIP library"
+
+config PROT_DHCP_LWIP
+	bool "DHCP support in lwIP"
+	depends on PROT_UDP_LWIP
+	help
+	  Enable support for the DHCP protocol in lwIP.
+
+config PROT_DNS_LWIP
+	bool
+	depends on PROT_UDP_LWIP
+
+config PROT_RAW_LWIP
+	bool
+
+config PROT_TCP_LWIP
+	bool
+
+config PROT_UDP_LWIP
+	bool
+
+config BOOTDEV_ETH
+        bool "Enable bootdev for ethernet"
+        depends on BOOTSTD
+        default y
+        help
+          Provide a bootdev for ethernet so that is it possible to boot
+          an operating system over the network, using the PXE (Preboot
+          Execution Environment) protocol.
diff --git a/net/Kconfig b/net/Kconfig
index 5dff6336293..4929428d2a5 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -2,11 +2,6 @@
 # Network configuration
 #
 
-menuconfig NET
-	bool "Networking support"
-	default y
-	imply NETDEVICES
-
 if NET
 
 config ARP_TIMEOUT
@@ -254,12 +249,3 @@ config IPV6
 	  address and find it, it will force using IPv6 in the network stack.
 
 endif   # if NET
-
-config SYS_RX_ETH_BUFFER
-	int "Number of receive packet buffers"
-	default 4
-	help
-	  Defines the number of Ethernet receive buffers. On some Ethernet
-	  controllers it is recommended to set this value to 8 or even higher,
-	  since all buffers can be full shortly after enabling the interface on
-	  high Ethernet traffic.
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 02/12] net-lwip: build lwIP
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
  2024-06-06 13:35 ` [PATCH v3 01/12] net: introduce alternative implementation as net-lwip/ Jerome Forissier
@ 2024-06-06 13:35 ` Jerome Forissier
  2024-06-06 15:50   ` Ilias Apalodimas
  2024-06-06 13:35 ` [PATCH v3 03/12] net-lwip: add DHCP support and dhcp commmand Jerome Forissier
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:35 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Sean Anderson, Oleksandr Suvorov

Build the lwIP library when NET_LWIP is enabled. The following files
are adaptation layers written specially for U-Boot:

 lib/lwip/u-boot/arch/cc.h
 lib/lwip/u-boot/arch/sys_arch.h (empty)
 lib/lwip/u-boot/limits.h (empty)
 lib/lwip/u-boot/lwipopts.h

They were initially contributed by Maxim in a previous RFC patch series.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
Cc: Maxim Uvarov <muvarov@gmail.com>
---
 lib/Makefile                    |   2 +
 lib/lwip/Makefile               |  57 +++++++++
 lib/lwip/u-boot/arch/cc.h       |  43 +++++++
 lib/lwip/u-boot/arch/sys_arch.h |   0
 lib/lwip/u-boot/limits.h        |   0
 lib/lwip/u-boot/lwipopts.h      | 197 ++++++++++++++++++++++++++++++++
 6 files changed, 299 insertions(+)
 create mode 100644 lib/lwip/Makefile
 create mode 100644 lib/lwip/u-boot/arch/cc.h
 create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
 create mode 100644 lib/lwip/u-boot/limits.h
 create mode 100644 lib/lwip/u-boot/lwipopts.h

diff --git a/lib/Makefile b/lib/Makefile
index 2a76acf100d..c35786a0576 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -94,6 +94,8 @@ obj-$(CONFIG_LIBAVB) += libavb/
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
 obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
 
+obj-$(CONFIG_NET_LWIP) += lwip/
+
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o
 obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
new file mode 100644
index 00000000000..158e59b91fc
--- /dev/null
+++ b/lib/lwip/Makefile
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2024 Linaro Ltd.
+
+ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+
+obj-y += \
+	lwip/src/api/api_lib.o \
+	lwip/src/api/api_msg.o \
+	lwip/src/api/err.o \
+	lwip/src/api/if_api.o \
+	lwip/src/api/netbuf.o \
+	lwip/src/api/netdb.o \
+	lwip/src/api/netifapi.o \
+	lwip/src/api/sockets.o \
+	lwip/src/api/tcpip.o \
+	lwip/src/apps/http/http_client.o \
+	lwip/src/apps/tftp/tftp.o \
+	lwip/src/core/altcp_alloc.o \
+	lwip/src/core/altcp.o \
+	lwip/src/core/altcp_tcp.o \
+	lwip/src/core/def.o \
+	lwip/src/core/dns.o \
+	lwip/src/core/inet_chksum.o \
+	lwip/src/core/init.o \
+	lwip/src/core/ip.o \
+	lwip/src/core/ipv4/acd.o \
+	lwip/src/core/ipv4/autoip.o \
+	lwip/src/core/ipv4/dhcp.o \
+	lwip/src/core/ipv4/etharp.o \
+	lwip/src/core/ipv4/icmp.o \
+	lwip/src/core/ipv4/igmp.o \
+	lwip/src/core/ipv4/ip4_addr.o \
+	lwip/src/core/ipv4/ip4.o \
+	lwip/src/core/ipv4/ip4_frag.o \
+	lwip/src/core/ipv6/dhcp6.o \
+	lwip/src/core/ipv6/ethip6.o \
+	lwip/src/core/ipv6/icmp6.o \
+	lwip/src/core/ipv6/inet6.o \
+	lwip/src/core/ipv6/ip6_addr.o \
+	lwip/src/core/ipv6/ip6.o \
+	lwip/src/core/ipv6/ip6_frag.o \
+	lwip/src/core/ipv6/mld6.o \
+	lwip/src/core/ipv6/nd6.o \
+	lwip/src/core/mem.o \
+	lwip/src/core/memp.o \
+	lwip/src/core/netif.o \
+	lwip/src/core/pbuf.o \
+	lwip/src/core/raw.o \
+	lwip/src/core/stats.o \
+	lwip/src/core/sys.o \
+	lwip/src/core/tcp.o \
+	lwip/src/core/tcp_in.o \
+	lwip/src/core/tcp_out.o \
+	lwip/src/core/timeouts.o \
+	lwip/src/core/udp.o \
+	lwip/src/netif/ethernet.o
diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
new file mode 100644
index 00000000000..31c036dc0c5
--- /dev/null
+++ b/lib/lwip/u-boot/arch/cc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023 Linaro Ltd. <maxim.uvarov@linaro.org> */
+
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <vsprintf.h>
+#include <rand.h>
+
+#define LWIP_ERRNO_INCLUDE <errno.h>
+
+#define LWIP_ERRNO_STDINCLUDE	1
+#define LWIP_NO_UNISTD_H 1
+#define LWIP_TIMEVAL_PRIVATE 1
+
+#ifdef CONFIG_LIB_RAND
+#define LWIP_RAND() ((u32_t)rand())
+#endif
+
+/* different handling for unit test, normally not needed */
+#ifdef LWIP_NOASSERT_ON_ERROR
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+						handler; }} while (0)
+#endif
+
+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
+
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
+				    x, __LINE__, __FILE__); } while (0)
+
+#define atoi(str) (int)dectoul(str, NULL)
+#define lwip_strnstr(a, b)  strnstr(a, b)
+
+#define LWIP_ERR_T int
+#define LWIP_CONST_CAST(target_type, val) ((target_type)((uintptr_t)val))
+
+#if defined(CONFIG_SYS_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/lib/lwip/u-boot/arch/sys_arch.h b/lib/lwip/u-boot/arch/sys_arch.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/lwip/u-boot/limits.h b/lib/lwip/u-boot/limits.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/lwip/u-boot/lwipopts.h b/lib/lwip/u-boot/lwipopts.h
new file mode 100644
index 00000000000..aac0a6259fd
--- /dev/null
+++ b/lib/lwip/u-boot/lwipopts.h
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/* Copyright (C) 2023 Linaro Ltd. <maxim.uvarov@linaro.org> */
+
+#ifndef LWIP_UBOOT_LWIPOPTS_H
+#define LWIP_UBOOT_LWIPOPTS_H
+
+#if defined(CONFIG_LWIP_DEBUG)
+#define LWIP_DEBUG 1
+#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
+#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
+#define ETHARP_DEBUG                    LWIP_DBG_ON
+#define NETIF_DEBUG                     LWIP_DBG_ON
+#define PBUF_DEBUG                      LWIP_DBG_OFF
+#define API_LIB_DEBUG                   LWIP_DBG_ON
+#define API_MSG_DEBUG                   LWIP_DBG_OFF
+#define SOCKETS_DEBUG                   LWIP_DBG_OFF
+#define ICMP_DEBUG                      LWIP_DBG_OFF
+#define IGMP_DEBUG                      LWIP_DBG_OFF
+#define INET_DEBUG                      LWIP_DBG_OFF
+#define IP_DEBUG                        LWIP_DBG_ON
+#define IP_REASS_DEBUG                  LWIP_DBG_OFF
+#define RAW_DEBUG                       LWIP_DBG_OFF
+#define MEM_DEBUG                       LWIP_DBG_OFF
+#define MEMP_DEBUG                      LWIP_DBG_OFF
+#define SYS_DEBUG                       LWIP_DBG_OFF
+#define TIMERS_DEBUG                    LWIP_DBG_ON
+#define TCP_DEBUG                       LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
+#define TCP_FR_DEBUG                    LWIP_DBG_OFF
+#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
+#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
+#define TCP_WND_DEBUG                   LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
+#define TCP_RST_DEBUG                   LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
+#define UDP_DEBUG                       LWIP_DBG_OFF
+#define TCPIP_DEBUG                     LWIP_DBG_OFF
+#define SLIP_DEBUG                      LWIP_DBG_OFF
+#define DHCP_DEBUG                      LWIP_DBG_ON
+#define AUTOIP_DEBUG                    LWIP_DBG_ON
+#define DNS_DEBUG                       LWIP_DBG_ON
+#define IP6_DEBUG                       LWIP_DBG_OFF
+#define DHCP6_DEBUG                     LWIP_DBG_OFF
+#else
+#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
+#define LWIP_DBG_TYPES_ON               LWIP_DBG_OFF
+#define ETHARP_DEBUG                    LWIP_DBG_OFF
+#define NETIF_DEBUG                     LWIP_DBG_OFF
+#define PBUF_DEBUG                      LWIP_DBG_OFF
+#define API_LIB_DEBUG                   LWIP_DBG_OFF
+#define API_MSG_DEBUG                   LWIP_DBG_OFF
+#define SOCKETS_DEBUG                   LWIP_DBG_OFF
+#define ICMP_DEBUG                      LWIP_DBG_OFF
+#define IGMP_DEBUG                      LWIP_DBG_OFF
+#define INET_DEBUG                      LWIP_DBG_OFF
+#define IP_DEBUG                        LWIP_DBG_OFF
+#define IP_REASS_DEBUG                  LWIP_DBG_OFF
+#define RAW_DEBUG                       LWIP_DBG_OFF
+#define MEM_DEBUG                       LWIP_DBG_OFF
+#define MEMP_DEBUG                      LWIP_DBG_OFF
+#define SYS_DEBUG                       LWIP_DBG_OFF
+#define TIMERS_DEBUG                    LWIP_DBG_OFF
+#define TCP_DEBUG                       LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
+#define TCP_FR_DEBUG                    LWIP_DBG_OFF
+#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
+#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
+#define TCP_WND_DEBUG                   LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
+#define TCP_RST_DEBUG                   LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
+#define UDP_DEBUG                       LWIP_DBG_OFF
+#define TCPIP_DEBUG                     LWIP_DBG_OFF
+#define SLIP_DEBUG                      LWIP_DBG_OFF
+#define DHCP_DEBUG                      LWIP_DBG_OFF
+#define AUTOIP_DEBUG                    LWIP_DBG_OFF
+#define DNS_DEBUG                       LWIP_DBG_OFF
+#define IP6_DEBUG                       LWIP_DBG_OFF
+#define DHCP6_DEBUG                     LWIP_DBG_OFF
+#endif
+#define LWIP_TESTMODE                   0
+
+#if !defined(CONFIG_LWIP_ASSERT)
+#define LWIP_NOASSERT 1
+#define LWIP_ASSERT(message, assertion)
+#endif
+
+#include "lwip/debug.h"
+
+#define SYS_LIGHTWEIGHT_PROT            0
+#define NO_SYS                          1
+
+#define LWIP_IPV4			1
+#define LWIP_IPV6			0
+
+#define MEM_ALIGNMENT                   1
+#define MEM_SIZE                        1600
+
+#define MEMP_NUM_PBUF                   4
+#define MEMP_NUM_RAW_PCB                2
+#define MEMP_NUM_UDP_PCB                4
+#define MEMP_NUM_TCP_PCB                2
+#define MEMP_NUM_TCP_PCB_LISTEN         2
+#define MEMP_NUM_TCP_SEG                16
+#define MEMP_NUM_REASSDATA              1
+#define MEMP_NUM_ARP_QUEUE              2
+#define MEMP_NUM_SYS_TIMEOUT            4
+#define MEMP_NUM_NETBUF                 2
+#define MEMP_NUM_NETCONN               32
+#define MEMP_NUM_TCPIP_MSG_API          8
+#define MEMP_NUM_TCPIP_MSG_INPKT        8
+#define PBUF_POOL_SIZE                  8
+
+#define LWIP_ARP                        1
+#define ARP_TABLE_SIZE                  1
+#define ARP_QUEUEING                    0
+
+#define IP_FORWARD                      0
+#define IP_OPTIONS_ALLOWED              1
+#define IP_REASSEMBLY                   0
+#define IP_FRAG                         0
+#define IP_REASS_MAXAGE                 3
+#define IP_REASS_MAX_PBUFS              4
+#define IP_FRAG_USES_STATIC_BUF         0
+
+#define IP_DEFAULT_TTL                  255
+
+#define LWIP_ICMP                       0
+
+#if defined(CONFIG_PROT_RAW_LWIP)
+#define LWIP_RAW                        1
+#else
+#define LWIP_RAW			0
+#endif
+
+#if defined(CONFIG_PROT_DHCP_LWIP)
+#define LWIP_DHCP                       1
+#define LWIP_DHCP_BOOTP_FILE		1
+#else
+#define LWIP_DHCP			0
+#endif
+
+#define LWIP_DHCP_DOES_ACD_CHECK	0
+
+#define LWIP_AUTOIP                     0
+
+#define LWIP_SNMP                       0
+
+#define LWIP_IGMP                       0
+
+#if defined(CONFIG_PROT_DNS_LWIP)
+#define LWIP_DNS                        1
+#define DNS_TABLE_SIZE                  1
+#else
+#define LWIP_DNS                        0
+#endif
+
+#if defined(CONFIG_PROT_UDP_LWIP)
+#define LWIP_UDP                        1
+#else
+#define LWIP_UDP                        0
+#endif
+
+#if defined(CONFIG_PROT_TCP_LWIP)
+#define LWIP_TCP                        1
+#else
+#define LWIP_TCP                        0
+#endif
+
+#define LWIP_LISTEN_BACKLOG             0
+
+#define PBUF_LINK_HLEN                  14
+#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN)
+
+#define LWIP_HAVE_LOOPIF                0
+
+#define LWIP_NETCONN                    0
+#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1
+
+#define LWIP_SOCKET                     0
+#define SO_REUSE                        0
+
+#define LWIP_STATS                      0
+
+#define PPP_SUPPORT                     0
+
+#define LWIP_TCPIP_CORE_LOCKING		0
+
+#define LWIP_NETIF_LOOPBACK		0
+
+/* use malloc instead of pool */
+#define MEMP_MEM_MALLOC                 1
+#define MEMP_MEM_INIT			1
+#define MEM_LIBC_MALLOC			1
+
+#endif /* LWIP_UBOOT_LWIPOPTS_H */
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 03/12] net-lwip: add DHCP support and dhcp commmand
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
  2024-06-06 13:35 ` [PATCH v3 01/12] net: introduce alternative implementation as net-lwip/ Jerome Forissier
  2024-06-06 13:35 ` [PATCH v3 02/12] net-lwip: build lwIP Jerome Forissier
@ 2024-06-06 13:35 ` Jerome Forissier
  2024-06-06 13:35 ` [PATCH v3 04/12] net-lwip: add TFTP support and tftpboot command Jerome Forissier
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:35 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Joe Hershberger, Ramon Fried, Simon Glass,
	Heinrich Schuchardt, Marek Vasut, Sumit Garg, Andrew Davis,
	Bryan Brattlof, Jesse Taube, Leon M. Busch-George, Eddie James,
	Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson, Abdellatif El Khlifi, Artur Rojek,
	Bin Meng, Shiji Yang, Yang Xiwen, Kever Yang, Eugen Hristev,
	Yanhong Wang, Jonas Karlman, Boon Khai Ng, Neil Armstrong,
	Masahisa Kojima, Ioana Ciornei, Sean Anderson

Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as
well as the dhcp command.
- net-lwip/net-lwip.c is mostly empty for now. It will provide functions
similar to net/net.c except based on the lwIP stack
- include/net-lwip.h is a replacement for include/net.h which is unused
when NET_LWIP is enabled. Declarations from the latter will be
transferred to the former as needed when new network commands are ported
on top of lwIP.
- CMD_TFTPBOOT is selected by BOOTMETH_EFI due to this code having
an implicit dependency on do_tftpb().

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 Makefile                |   1 +
 boot/Kconfig            |   3 +-
 cmd/Kconfig             |  26 +++++
 cmd/Makefile            |   4 +
 cmd/net-lwip.c          |  13 +++
 common/board_r.c        |   4 +-
 drivers/net/Kconfig     |   2 +-
 include/net-lwip.h      |  85 +++++++++++++++
 include/net.h           |   2 +-
 net-lwip/Makefile       |  15 +++
 net-lwip/dhcp.c         | 105 +++++++++++++++++++
 net-lwip/eth_internal.h |  35 +++++++
 net-lwip/net-lwip.c     | 224 ++++++++++++++++++++++++++++++++++++++++
 net-lwip/tftp.c         |  11 ++
 14 files changed, 525 insertions(+), 5 deletions(-)
 create mode 100644 cmd/net-lwip.c
 create mode 100644 include/net-lwip.h
 create mode 100644 net-lwip/Makefile
 create mode 100644 net-lwip/dhcp.c
 create mode 100644 net-lwip/eth_internal.h
 create mode 100644 net-lwip/net-lwip.c
 create mode 100644 net-lwip/tftp.c

diff --git a/Makefile b/Makefile
index ceb99a2698e..d3c9e6775dc 100644
--- a/Makefile
+++ b/Makefile
@@ -860,6 +860,7 @@ libs-y += env/
 libs-y += lib/
 libs-y += fs/
 libs-$(CONFIG_NET) += net/
+libs-$(CONFIG_NET_LWIP) += net-lwip/
 libs-y += disk/
 libs-y += drivers/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a6..004e69dd92a 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -378,7 +378,7 @@ config BOOT_DEFAULTS_CMDS
 	select CMD_FAT
 	select CMD_FS_GENERIC
 	select CMD_PART if PARTITIONS
-	select CMD_DHCP if CMD_NET
+	select CMD_DHCP if CMD_NET || CMD_NET_LWIP
 	select CMD_PING if CMD_NET
 	select CMD_PXE if CMD_NET
 	select CMD_BOOTI if ARM64
@@ -540,6 +540,7 @@ config BOOTMETH_EXTLINUX_PXE
 config BOOTMETH_EFILOADER
 	bool "Bootdev support for EFI boot"
 	depends on EFI_BINARY_EXEC
+	select CMD_TFTPBOOT if CMD_NET_LWIP
 	default y
 	help
 	  Enables support for EFI boot using bootdevs. This makes the
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b026439c773..1bfa528e945 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2084,6 +2084,32 @@ config CMD_WOL
 
 endif
 
+if NET_LWIP
+
+menuconfig CMD_NET_LWIP
+	bool "Network commands (lwIP)"
+	default y
+
+if CMD_NET_LWIP
+
+config CMD_DHCP
+	bool "dhcp"
+	select PROT_DHCP_LWIP
+	help
+	  Boot image via network using DHCP/TFTP protocol
+
+config CMD_TFTPBOOT
+	bool "tftp"
+	select PROT_UDP_LWIP
+	default n
+	help
+	  tftpboot - load file via network using TFTP protocol
+	  Currently a placeholder (not implemented)
+
+endif
+
+endif
+
 menu "Misc commands"
 
 config CMD_2048
diff --git a/cmd/Makefile b/cmd/Makefile
index 87133cc27a8..535b6838ca5 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -128,6 +128,10 @@ endif
 obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+ifdef CONFIG_CMD_NET_LWIP
+CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
 obj-$(CONFIG_CMD_ONENAND) += onenand.o
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
new file mode 100644
index 00000000000..966d7226eda
--- /dev/null
+++ b/cmd/net-lwip.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <net-lwip.h>
+
+#if defined(CONFIG_CMD_DHCP)
+U_BOOT_CMD(
+        dhcp,   3,      1,      do_dhcp,
+        "boot image via network using DHCP/TFTP protocol",
+        "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/common/board_r.c b/common/board_r.c
index da0b80f24ff..6548eb8fdd5 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -472,7 +472,7 @@ static int initr_status_led(void)
 }
 #endif
 
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
 static int initr_net(void)
 {
 	puts("Net:   ");
@@ -727,7 +727,7 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_PCI_ENDPOINT
 	pci_ep_init,
 #endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b2d7b499766..4ba09c9d6f8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -96,7 +96,7 @@ config DSA_SANDBOX
 
 menuconfig NETDEVICES
 	bool "Network device support"
-	depends on NET
+	depends on NET || NET_LWIP
 	select DM_ETH
 	help
 	  You must select Y to enable any network device support
diff --git a/include/net-lwip.h b/include/net-lwip.h
new file mode 100644
index 00000000000..2308703e46b
--- /dev/null
+++ b/include/net-lwip.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __NET_LWIP_H__
+#define __NET_LWIP_H__
+
+#include <asm/cache.h>
+#include <linux/types.h>
+#include <lwip/netif.h>
+#include <time.h>
+
+/*
+ *	The number of receive packet buffers, and the required packet buffer
+ *	alignment in memory.
+ *
+ */
+#define PKTBUFSRX	CONFIG_SYS_RX_ETH_BUFFER
+#define PKTALIGN	ARCH_DMA_MINALIGN
+
+/* ARP hardware address length */
+#define ARP_HLEN 6
+
+/*
+ * Maximum packet size; used to allocate packet storage. Use
+ * the maxium Ethernet frame size as specified by the Ethernet
+ * standard including the 802.1Q tag (VLAN tagging).
+ * maximum packet size =  1522
+ * maximum packet size and multiple of 32 bytes =  1536
+ */
+#define PKTSIZE			1522
+#ifndef CONFIG_DM_DSA
+#define PKTSIZE_ALIGN		1536
+#else
+/* Maximum DSA tagging overhead (headroom and/or tailroom) */
+#define DSA_MAX_OVR		256
+#define PKTSIZE_ALIGN		(1536 + DSA_MAX_OVR)
+#endif
+
+struct udevice *eth_get_dev(void); /* get the current device */
+/*
+ * Get the hardware address for an ethernet interface .
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	index - device index number (0 for first)
+ *	enetaddr - returns 6 byte hardware address
+ * Returns:
+ *	Return true if the address is valid.
+ */
+int eth_env_get_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
+int eth_init(void);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
+int eth_rx(void);
+int eth_get_dev_index(void);
+int eth_init_state_only(void); /* Set active state */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
+struct ethernet_hdr {
+	u8		et_dest[ARP_HLEN];	/* Destination node	*/
+	u8		et_src[ARP_HLEN];	/* Source node		*/
+	u16		et_protlen;		/* Protocol or length	*/
+} __attribute__((packed));
+
+/* Ethernet header size */
+#define ETHER_HDR_SIZE	(sizeof(struct ethernet_hdr))
+
+/**
+ * string_to_enetaddr() - Parse a MAC address
+ *
+ * Convert a string MAC address
+ *
+ * Implemented in lib/net_utils.c (built unconditionally)
+ *
+ * @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit
+ *	hex value
+ * @enetaddr: Place to put MAC address (6 bytes)
+ */
+void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
+
+int net_lwip_init(void);
+struct netif *net_lwip_get_netif(void);
+
+int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+
+#endif /* __NET_LWIP_H__ */
diff --git a/include/net.h b/include/net.h
index ac511eab103..330bc6bf66c 100644
--- a/include/net.h
+++ b/include/net.h
@@ -914,7 +914,7 @@ static inline struct in_addr env_get_ip(char *var)
  */
 void reset_phy(void);
 
-#if CONFIG_IS_ENABLED(NET)
+#if CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP)
 /**
  * eth_set_enable_bootdevs() - Enable or disable binding of Ethernet bootdevs
  *
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
new file mode 100644
index 00000000000..a56c32bfa74
--- /dev/null
+++ b/net-lwip/Makefile
@@ -0,0 +1,15 @@
+ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+
+obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_ETH) += ../net/eth_bootdev.o
+obj-$(CONFIG_DM_MDIO)  += ../net/mdio-uclass.o
+obj-$(CONFIG_DM_MDIO_MUX) += ../net/mdio-mux-uclass.o
+obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
+obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
+obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
+obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
+
+# Disable this warning as it is triggered by:
+# sprintf(buf, index ? "foo%d" : "foo", index)
+# and this is intentional usage.
+CFLAGS_eth_common.o += -Wno-format-extra-args
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
new file mode 100644
index 00000000000..d1d35999b04
--- /dev/null
+++ b/net-lwip/dhcp.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <lwip/dhcp.h>
+#include <lwip/dns.h>
+#include <lwip/timeouts.h>
+#include <net-lwip.h>
+#include <time.h>
+
+#define DHCP_TIMEOUT_MS 2000
+
+#ifdef CONFIG_CMD_TFTPBOOT
+/* Boot file obtained from DHCP (if present) */
+static char boot_file_name[DHCP_BOOT_FILE_LEN];
+#endif
+
+static void call_lwip_dhcp_fine_tmr(void *ctx)
+{
+	dhcp_fine_tmr();
+}
+
+int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	unsigned long start;
+	struct netif *netif;
+	struct dhcp *dhcp;
+	bool bound;
+
+	/* Running DHCP on the primary interface only */
+	if (eth_get_dev_index() != 0)
+		return -EINVAL;
+
+	net_lwip_init();
+
+	netif = net_lwip_get_netif();
+	if (!netif)
+		return CMD_RET_FAILURE;
+
+	/*
+	 * The fine timer is half a second, it deals with the initial DHCP
+	 * request.
+	 * We don't bother with the coarse timer (1 minute) which handles the
+	 * DHCP lease renewal.
+	 */
+	sys_timeout(500, call_lwip_dhcp_fine_tmr, NULL);
+	start = get_timer(0);
+	dhcp_start(netif);
+
+	/* Wait for DHCP to complete */
+	do {
+		eth_rx();
+		sys_check_timeouts();
+		bound = dhcp_supplied_address(netif);
+		if (bound)
+			break;
+	} while (get_timer(start) < DHCP_TIMEOUT_MS);
+
+	sys_untimeout(call_lwip_dhcp_fine_tmr, NULL);
+
+	if (!bound)
+		return CMD_RET_FAILURE;
+
+	dhcp = netif_dhcp_data(netif);
+
+	env_set("bootfile", dhcp->boot_file_name);
+	if (dhcp->offered_gw_addr.addr != 0) {
+
+		env_set("gatewayip", ip4addr_ntoa(&dhcp->offered_gw_addr));
+		/* Set this interface as the default for IP routing */
+		netif_set_default(netif);
+	}
+	env_set("ipaddr", ip4addr_ntoa(&dhcp->offered_ip_addr));
+	env_set("netmask", ip4addr_ntoa(&dhcp->offered_sn_mask));
+	env_set("serverip", ip4addr_ntoa(&dhcp->server_ip_addr));
+#ifdef CONFIG_PROT_DNS_LWIP
+	env_set("dnsip", ip4addr_ntoa(dns_getserver(0)));
+	env_set("dnsip2", ip4addr_ntoa(dns_getserver(1)));
+#endif
+#ifdef CONFIG_CMD_TFTPBOOT
+	if (dhcp->boot_file_name[0] != '\0')
+		strncpy(boot_file_name, dhcp->boot_file_name,
+			sizeof(boot_file_name));
+#endif
+
+	printf("DHCP client bound to address %pI4 (%lu ms)\n",
+	       &dhcp->offered_ip_addr, get_timer(start));
+
+	return CMD_RET_SUCCESS;
+}
+
+int dhcp_run(ulong addr, const char *fname, bool autoload)
+{
+	char *dhcp_argv[] = {"dhcp", NULL, };
+	struct cmd_tbl cmdtp = {};	/* dummy */
+
+	if (autoload) {
+		/* Will be supported when TFTP is added */
+		return -EOPNOTSUPP;
+	}
+
+	return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
+}
diff --git a/net-lwip/eth_internal.h b/net-lwip/eth_internal.h
new file mode 100644
index 00000000000..0b829a8d388
--- /dev/null
+++ b/net-lwip/eth_internal.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2001-2015
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Joe Hershberger, National Instruments
+ */
+
+#ifndef __ETH_INTERNAL_H
+#define __ETH_INTERNAL_H
+
+/* Do init that is common to driver model and legacy networking */
+void eth_common_init(void);
+
+/**
+ * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
+ *
+ * This sets up an environment variable with the given MAC address (@enetaddr).
+ * The environment variable to be set is defined by <@base_name><@index>addr.
+ * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
+ * eth1addr, etc.
+ *
+ * @base_name:	Base name for variable, typically "eth"
+ * @index:	Index of interface being updated (>=0)
+ * @enetaddr:	Pointer to MAC address to put into the variable
+ * Return: 0 if OK, other value on error
+ */
+int eth_env_set_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
+
+int eth_mac_skip(int index);
+void eth_current_changed(void);
+void eth_set_dev(struct udevice *dev);
+void eth_set_current_to_next(void);
+
+#endif
diff --git a/net-lwip/net-lwip.c b/net-lwip/net-lwip.c
new file mode 100644
index 00000000000..886028b68c3
--- /dev/null
+++ b/net-lwip/net-lwip.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <lwip/ip4_addr.h>
+#include <lwip/err.h>
+#include <lwip/netif.h>
+#include <lwip/pbuf.h>
+#include <lwip/etharp.h>
+#include <lwip/prot/etharp.h>
+#include <net-lwip.h>
+
+/* xx:xx:xx:xx:xx:xx\0 */
+#define MAC_ADDR_STRLEN 18
+
+#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
+void (*push_packet)(void *, int len) = 0;
+#endif
+int net_restart_wrap;
+static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
+uchar *net_rx_packets[PKTBUFSRX];
+uchar *net_rx_packet;
+uchar *net_tx_packet;
+
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+        int err;
+
+        /* switch dev to active state */
+        eth_init_state_only();
+
+        err = eth_send(p->payload, p->len);
+        if (err) {
+                log_err("eth_send error %d\n", err);
+                return ERR_ABRT;
+        }
+        return ERR_OK;
+}
+
+static err_t net_lwip_if_init(struct netif *netif)
+{
+#if LWIP_IPV4
+	netif->output = etharp_output;
+#endif
+	netif->linkoutput = low_level_output;
+	netif->mtu = 1500;
+	netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+
+	return ERR_OK;
+}
+
+static void eth_init_rings(void)
+{
+        static bool called;
+	int i;
+
+        if (called)
+		return;
+	called = true;
+
+	net_tx_packet = &net_pkt_buf[0] + (PKTALIGN - 1);
+	net_tx_packet -= (ulong)net_tx_packet % PKTALIGN;
+	for (i = 0; i < PKTBUFSRX; i++)
+		net_rx_packets[i] = net_tx_packet + (i + 1) * PKTSIZE_ALIGN;
+}
+
+int net_lwip_init(void)
+{
+	ip4_addr_t ipaddr, netmask, gw;
+	struct netif *unetif;
+	struct udevice *udev;
+	int ret;
+	unsigned char env_enetaddr[ARP_HLEN];
+	const struct udevice *dev;
+	struct uclass *uc;
+
+	eth_set_current();
+
+	udev = eth_get_dev();
+	if (!udev) {
+		log_err("no active eth device\n");
+		return ERR_IF;
+	}
+
+	eth_init_rings();
+
+	ret = eth_init();
+	if (ret) {
+		log_err("eth_init error %d\n", ret);
+		return ERR_IF;
+	}
+
+	uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
+		char ipstr[IP4ADDR_STRLEN_MAX];
+		char maskstr[IP4ADDR_STRLEN_MAX];
+		char gwstr[IP4ADDR_STRLEN_MAX];
+		char hwstr[MAC_ADDR_STRLEN];
+		char *env;
+
+		eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
+		log_info("eth%d: %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
+			 udev == dev ? "active" : "");
+
+		unetif = malloc(sizeof(struct netif));
+		if (!unetif)
+			return ERR_MEM;
+		memset(unetif, 0, sizeof(struct netif));
+
+		ip4_addr_set_zero(&gw);
+		ip4_addr_set_zero(&ipaddr);
+		ip4_addr_set_zero(&netmask);
+
+		if (dev_seq(dev) == 0) {
+			snprintf(ipstr, IP4ADDR_STRLEN_MAX, "ipaddr");
+			snprintf(maskstr, IP4ADDR_STRLEN_MAX, "netmask");
+			snprintf(gwstr, IP4ADDR_STRLEN_MAX, "gw");
+		} else {
+			snprintf(ipstr, IP4ADDR_STRLEN_MAX, "ipaddr%d", dev_seq(dev));
+			snprintf(maskstr, IP4ADDR_STRLEN_MAX, "netmask%d", dev_seq(dev));
+			snprintf(gwstr, IP4ADDR_STRLEN_MAX, "gw%d", dev_seq(dev));
+		}
+		snprintf(hwstr, MAC_ADDR_STRLEN, "%pM",  env_enetaddr);
+		snprintf(unetif->name, 2, "%d", dev_seq(dev));
+
+		string_to_enetaddr(hwstr, unetif->hwaddr);
+		unetif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+		env = env_get(ipstr);
+		if (env)
+			ipaddr_aton(env, &ipaddr);
+
+		env = env_get(maskstr);
+		if (env)
+			ipaddr_aton(env, &netmask);
+
+		if (!netif_add(unetif, &ipaddr, &netmask, &gw,
+			       unetif, net_lwip_if_init, netif_input)) {
+			log_err("err: netif_add failed!\n");
+			free(unetif);
+			return ERR_IF;
+		}
+
+		netif_set_up(unetif);
+		netif_set_link_up(unetif);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/*
+ * Return the current network interface for lwIP. In other words, the struct
+ * netif that corresponds to eth_get_dev().
+ */
+struct netif *net_lwip_get_netif(void)
+{
+	int idx;
+
+	idx = eth_get_dev_index();
+	if (idx < 0)
+		return NULL;
+
+	return netif_get_by_index(idx + 1);
+}
+
+int net_init(void)
+{
+	return net_lwip_init();
+}
+
+static struct pbuf *alloc_pbuf_and_copy(uchar *data, int len)
+{
+        struct pbuf *p, *q;
+
+        /* We allocate a pbuf chain of pbufs from the pool. */
+        p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+        if (!p) {
+                LINK_STATS_INC(link.memerr);
+                LINK_STATS_INC(link.drop);
+                return NULL;
+        }
+
+        for (q = p; q != NULL; q = q->next) {
+                memcpy(q->payload, data, q->len);
+                data += q->len;
+        }
+
+        LINK_STATS_INC(link.recv);
+
+        return p;
+}
+
+void net_process_received_packet(uchar *in_packet, int len)
+{
+	struct netif *netif;
+	struct pbuf *pbuf;
+
+	if (len < ETHER_HDR_SIZE)
+		return;
+
+#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
+	if (push_packet) {
+		(*push_packet)(in_packet, len);
+		return;
+	}
+#endif
+
+	netif = net_lwip_get_netif();
+	if (!netif)
+		return;
+
+	pbuf = alloc_pbuf_and_copy(in_packet, len);
+	if (!pbuf)
+		return;
+
+	netif->input(pbuf, netif);
+}
+
+u32_t sys_now(void)
+{
+	return get_timer(0);
+}
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
new file mode 100644
index 00000000000..1fa246f55d9
--- /dev/null
+++ b/net-lwip/tftp.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <net-lwip.h>
+
+int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	/* Not implemented */
+	return CMD_RET_FAILURE;
+}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 04/12] net-lwip: add TFTP support and tftpboot command
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (2 preceding siblings ...)
  2024-06-06 13:35 ` [PATCH v3 03/12] net-lwip: add DHCP support and dhcp commmand Jerome Forissier
@ 2024-06-06 13:35 ` Jerome Forissier
  2024-06-06 13:36 ` [PATCH v3 05/12] net-lwip: add ping command Jerome Forissier
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:35 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
	Francis Laniel, Peter Robinson

Implement do_tftpb().

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 cmd/Kconfig     |   3 +-
 cmd/net-lwip.c  |   8 ++
 net-lwip/dhcp.c |  11 ++-
 net-lwip/tftp.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 219 insertions(+), 5 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1bfa528e945..94a8de266f6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2101,10 +2101,9 @@ config CMD_DHCP
 config CMD_TFTPBOOT
 	bool "tftp"
 	select PROT_UDP_LWIP
-	default n
+	default y
 	help
 	  tftpboot - load file via network using TFTP protocol
-	  Currently a placeholder (not implemented)
 
 endif
 
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 966d7226eda..490a2e4ac5c 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -11,3 +11,11 @@ U_BOOT_CMD(
         "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_TFTPBOOT)
+U_BOOT_CMD(
+	tftpboot,	3,	0,	do_tftpb,
+	"boot image via network using TFTP protocol\n",
+	"[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
index d1d35999b04..7bacc234f1e 100644
--- a/net-lwip/dhcp.c
+++ b/net-lwip/dhcp.c
@@ -94,11 +94,20 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 int dhcp_run(ulong addr, const char *fname, bool autoload)
 {
 	char *dhcp_argv[] = {"dhcp", NULL, };
+#ifdef CONFIG_CMD_TFTPBOOT
+	char *tftp_argv[] = {"tftpboot", boot_file_name, NULL, };
+#endif
 	struct cmd_tbl cmdtp = {};	/* dummy */
 
 	if (autoload) {
-		/* Will be supported when TFTP is added */
+#ifdef CONFIG_CMD_TFTPBOOT
+		/* Assume DHCP was already performed */
+		if (boot_file_name[0])
+			return do_tftpb(&cmdtp, 0, 2, tftp_argv);
+		return 0;
+#else
 		return -EOPNOTSUPP;
+#endif
 	}
 
 	return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
index 1fa246f55d9..02ee4aacca5 100644
--- a/net-lwip/tftp.c
+++ b/net-lwip/tftp.c
@@ -2,10 +2,208 @@
 /* Copyright (C) 2024 Linaro Ltd. */
 
 #include <command.h>
+#include <console.h>
+#include <image.h>
+#include <linux/delay.h>
+#include <lwip/apps/tftp_client.h>
+#include <lwip/timeouts.h>
 #include <net-lwip.h>
+#include <time.h>
+
+static ulong daddr;
+static ulong size;
+static ulong prevsize;
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+static ulong start_time;
+static enum done_state {
+	NOT_DONE = 0,
+	SUCCESS = 1,
+	FAILURE = 2
+} done;
+
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write)
+{
+	return NULL;
+}
+
+static void tftp_close(void *handle)
+{
+	ulong elapsed;
+
+	if (done == FAILURE) {
+		/* Closing after an error */
+		return;
+	}
+
+	elapsed = get_timer(start_time);
+	done = SUCCESS;
+	printf("\nBytes transferred = %lu (%lx hex)\n", size, size);
+
+	if (env_set_hex("filesize", size)) {
+		log_err("filesize not updated\n");
+		return;
+	}
+}
+
+static int tftp_read(void *handle, void *buf, int bytes)
+{
+	return 0;
+}
+
+static int tftp_write(void *handle, struct pbuf *p)
+{
+	struct pbuf *q;
+
+	for (q = p; q != NULL; q = q->next) {
+		memcpy((void *)daddr, q->payload, q->len);
+		daddr += q->len;
+		size += q->len;
+		if (size - prevsize > PROGRESS_PRINT_STEP_BYTES) {
+			printf("#");
+			prevsize = size;
+		}
+	}
+
+	return 0;
+}
+
+static void tftp_error(void *handle, int err, const char *msg, int size)
+{
+	char message[100];
+
+	done = FAILURE;
+	memset(message, 0, sizeof(message));
+	memcpy(message, msg, LWIP_MIN(sizeof(message) - 1, (size_t)size));
+
+	log_info("\nTFTP error: %d (%s)\n", err, message);
+}
+
+static const struct tftp_context tftp_context = {
+	tftp_open,
+	tftp_close,
+	tftp_read,
+	tftp_write,
+	tftp_error
+};
+
+static int tftp_run(ulong addr, char *fname, ip_addr_t srvip)
+{
+	void *f = (void *)0x1; /* unused fake file handle*/
+	err_t err;
+
+	if (!fname || addr == 0)
+		return -1;
+
+	done = NOT_DONE;
+	size = 0;
+	prevsize = 0;
+	daddr = addr;
+
+	log_info("TFTP from server %s; our IP address is %s\n",
+		 ip4addr_ntoa(&srvip), env_get("ipaddr"));
+	log_info("Filename '%s'.\n", fname);
+	log_info("Load address: 0x%lx\n", daddr);
+	log_info("Loading: ");
+
+	err = tftp_init_client(&tftp_context);
+	if (!(err == ERR_OK || err == ERR_USE))
+		log_err("tftp_init_client err: %d\n", err);
+
+	start_time = get_timer(0);
+	err = tftp_get(f, &srvip, TFTP_PORT, fname, TFTP_MODE_OCTET);
+	/* might return different errors, like routing problems */
+	if (err != ERR_OK) {
+		log_err("tftp_get err=%d\n", err);
+		return -1;
+	}
+
+	while (!done) {
+		eth_rx();
+		sys_check_timeouts();
+		if (ctrlc())
+			break;
+	}
+
+	tftp_cleanup();
+
+	if (done == SUCCESS) {
+		if (env_set_hex("fileaddr", addr)) {
+			log_err("fileaddr not updated\n");
+			return -1;
+		}
+		return 0;
+	}
+
+	return -1;
+}
 
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	/* Not implemented */
-	return CMD_RET_FAILURE;
+	char *fname;
+	char *server_ip;
+	ip_addr_t srvip;
+	ulong addr;
+	char *end;
+	char *col;
+
+	image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr);
+
+	switch (argc) {
+	case 1:
+		fname = env_get("bootfile");
+		break;
+	case 2:
+		/*
+		 * Only one arg - accept two forms:
+		 * Just load address, or just boot file name. The latter
+		 * form must be written in a format which can not be
+		 * mis-interpreted as a valid number.
+		 */
+		addr = hextoul(argv[1], &end);
+		if (end == (argv[1] + strlen(argv[1]))) {
+			image_load_addr = addr;
+			fname = env_get("bootfile");
+		} else {
+			fname = argv[1];
+		}
+		break;
+	case 3:
+		image_load_addr = hextoul(argv[1], NULL);
+		fname = argv[2];
+		break;
+	default:
+		return CMD_RET_USAGE;
+	}
+
+	col = strchr(fname, ':');
+	if (col) {
+		server_ip = fname;
+		*col = '\0';
+		fname = col + 1;
+	} else {
+		server_ip = env_get("serverip");
+		if (!server_ip) {
+			log_err("error: serverip variable has to be set\n");
+			return CMD_RET_FAILURE;
+		}
+	}
+	if (!ipaddr_aton(server_ip, &srvip)) {
+		log_err("error: ipaddr_aton\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (!fname) {
+		log_err("error: no file name\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (!image_load_addr) {
+		log_err("error: no load address\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (tftp_run(image_load_addr, fname, srvip) < 0)
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
 }
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 05/12] net-lwip: add ping command
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (3 preceding siblings ...)
  2024-06-06 13:35 ` [PATCH v3 04/12] net-lwip: add TFTP support and tftpboot command Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 16:53   ` Ilias Apalodimas
  2024-06-06 13:36 ` [PATCH v3 06/12] net-lwip: add dns command Jerome Forissier
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Eddie James, Mattijs Korpershoek,
	AKASHI Takahiro, Michal Simek, Francis Laniel, Peter Robinson

Add support for the the ping command with NET_LWIP. The implementation
is derived from lwIP's contrib/apps/ping/ping.c.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 boot/Kconfig       |   2 +-
 cmd/Kconfig        |   6 ++
 cmd/net-lwip.c     |   8 +++
 include/net-lwip.h |   3 +
 net-lwip/Makefile  |   1 +
 net-lwip/ping.c    | 163 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 182 insertions(+), 1 deletion(-)
 create mode 100644 net-lwip/ping.c

diff --git a/boot/Kconfig b/boot/Kconfig
index 004e69dd92a..983a284ec52 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -379,7 +379,7 @@ config BOOT_DEFAULTS_CMDS
 	select CMD_FS_GENERIC
 	select CMD_PART if PARTITIONS
 	select CMD_DHCP if CMD_NET || CMD_NET_LWIP
-	select CMD_PING if CMD_NET
+	select CMD_PING if CMD_NET || CMD_NET_LWIP
 	select CMD_PXE if CMD_NET
 	select CMD_BOOTI if ARM64
 	select CMD_BOOTZ if ARM && !ARM64
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 94a8de266f6..07cfe824e3f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
 	help
 	  Boot image via network using DHCP/TFTP protocol
 
+config CMD_PING
+	bool "ping"
+	select PROT_RAW_LWIP
+	help
+	  Send ICMP ECHO_REQUEST to network host
+
 config CMD_TFTPBOOT
 	bool "tftp"
 	select PROT_UDP_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 490a2e4ac5c..13856703fcf 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -12,6 +12,14 @@ U_BOOT_CMD(
 );
 #endif
 
+#if defined(CONFIG_CMD_PING)
+U_BOOT_CMD(
+	ping,	2,	1,	do_ping,
+	"send ICMP ECHO_REQUEST to network host",
+	"pingAddress"
+);
+#endif
+
 #if defined(CONFIG_CMD_TFTPBOOT)
 U_BOOT_CMD(
 	tftpboot,	3,	0,	do_tftpb,
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2308703e46b..2abaaa3b4e3 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -5,6 +5,7 @@
 
 #include <asm/cache.h>
 #include <linux/types.h>
+#include <lwip/ip_addr.h>
 #include <lwip/netif.h>
 #include <time.h>
 
@@ -50,6 +51,7 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int index,
 int eth_init(void);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 int eth_rx(void);
+const char *eth_get_name(void);
 int eth_get_dev_index(void);
 int eth_init_state_only(void); /* Set active state */
 void eth_set_current(void);		/* set nterface to ethcur var */
@@ -80,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
 #endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index a56c32bfa74..e68d4e24197 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 
 # Disable this warning as it is triggered by:
diff --git a/net-lwip/ping.c b/net-lwip/ping.c
new file mode 100644
index 00000000000..51947d615ed
--- /dev/null
+++ b/net-lwip/ping.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <lwip/icmp.h>
+#include <lwip/inet_chksum.h>
+#include <lwip/raw.h>
+#include <lwip/timeouts.h>
+#include <net-lwip.h>
+#include <time.h>
+
+#define PING_DELAY_MS 1000
+#define PING_TIMEOUT_MS 10000
+/* Ping identifier - must fit on a u16_t */
+#define PING_ID 0xAFAF
+
+static const ip_addr_t *ping_target;
+static struct raw_pcb *ping_pcb;
+static uint16_t ping_seq_num;
+
+static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+		      const ip_addr_t *addr)
+{
+	struct icmp_echo_hdr *iecho;
+	bool *alive = arg;
+
+	if (addr->addr != ping_target->addr)
+		return 0;
+
+	if ((p->tot_len >= (IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
+	    pbuf_remove_header(p, IP_HLEN) == 0) {
+		iecho = (struct icmp_echo_hdr *)p->payload;
+
+		if ((iecho->id == PING_ID) &&
+		    (iecho->seqno == lwip_htons(ping_seq_num))) {
+			*alive = true;
+			printf("host %s is alive\n", ipaddr_ntoa(addr));
+			pbuf_free(p);
+			return 1; /* eat the packet */
+		}
+		/* not eaten, restore original packet */
+		pbuf_add_header(p, IP_HLEN);
+	}
+
+	return 0; /* don't eat the packet */
+}
+
+static int ping_raw_init(void *recv_arg)
+{
+	ping_pcb = raw_new(IP_PROTO_ICMP);
+	if (!ping_pcb)
+		return -ENOMEM;
+
+	raw_recv(ping_pcb, ping_recv, recv_arg);
+	raw_bind(ping_pcb, IP_ADDR_ANY);
+
+	return 0;
+}
+
+static void ping_raw_stop(void)
+{
+	if (ping_pcb != NULL) {
+		raw_remove(ping_pcb);
+		ping_pcb = NULL;
+	}
+}
+
+static void ping_prepare_echo(struct icmp_echo_hdr *iecho)
+{
+	ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+	ICMPH_CODE_SET(iecho, 0);
+	iecho->chksum = 0;
+	iecho->id = PING_ID;
+	iecho->seqno = lwip_htons(++ping_seq_num);
+
+	iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
+}
+
+static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
+{
+	struct pbuf *p;
+	struct icmp_echo_hdr *iecho;
+	size_t ping_size = sizeof(struct icmp_echo_hdr);
+
+	p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
+	if (!p)
+		return;
+
+	if ((p->len == p->tot_len) && (p->next == NULL)) {
+		iecho = (struct icmp_echo_hdr *)p->payload;
+		ping_prepare_echo(iecho);
+		raw_sendto(raw, p, addr);
+	}
+
+	pbuf_free(p);
+}
+
+static void ping_send(void *arg)
+{
+	struct raw_pcb *pcb = (struct raw_pcb *)arg;
+
+	ping_send_icmp(pcb, ping_target);
+	sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
+}
+
+static int ping_loop(const ip_addr_t* addr)
+{
+	bool alive;
+	ulong start;
+	int ret;
+
+	printf("Using %s device\n", eth_get_name());
+
+	ret = ping_raw_init(&alive);
+	if (ret < 0)
+		return ret;
+	ping_target = addr;
+	ping_seq_num = 0;
+
+	start = get_timer(0);
+	ping_send(ping_pcb);
+
+	do {
+		eth_rx();
+		if (alive)
+			break;
+		sys_check_timeouts();
+		if (ctrlc()) {
+			printf("\nAbort\n");
+			break;
+		}
+	} while (get_timer(start) < PING_TIMEOUT_MS);
+
+	sys_untimeout(ping_send, ping_pcb);
+	ping_raw_stop();
+	ping_target = NULL;
+
+	if (alive) {
+		alive = false;
+		return 0;
+	}
+	printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr));
+	return -1;
+}
+
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	ip_addr_t addr;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	if (!ipaddr_aton(argv[1], &addr))
+		return CMD_RET_USAGE;
+
+	if (ping_loop(&addr) < 0)
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 06/12] net-lwip: add dns command
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (4 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 05/12] net-lwip: add ping command Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 15:46   ` Ilias Apalodimas
  2024-06-06 13:36 ` [PATCH v3 07/12] net-lwip: add wget command Jerome Forissier
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
	Francis Laniel, Peter Robinson

Add CMD_DNS when NET_LWIP is enabled to provide the dns command using
lwIP.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 cmd/Kconfig        |   6 +++
 cmd/net-lwip.c     |   8 ++++
 include/net-lwip.h |   1 +
 net-lwip/Makefile  |   1 +
 net-lwip/dns.c     | 107 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 123 insertions(+)
 create mode 100644 net-lwip/dns.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07cfe824e3f..6ef0b52cd34 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
 	help
 	  Boot image via network using DHCP/TFTP protocol
 
+config CMD_DNS
+	bool "dns"
+	select PROT_DNS_LWIP
+	help
+	  Lookup the IP of a hostname
+
 config CMD_PING
 	bool "ping"
 	select PROT_RAW_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 13856703fcf..3abafdf7969 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -27,3 +27,11 @@ U_BOOT_CMD(
 	"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 #endif
+
+#if defined(CONFIG_CMD_DNS)
+U_BOOT_CMD(
+	dns,	3,	1,	do_dns,
+	"lookup the IP of a hostname",
+	"hostname [envvar]"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 2abaaa3b4e3..0019d1524e5 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -82,6 +82,7 @@ int net_lwip_init(void);
 struct netif *net_lwip_get_netif(void);
 
 int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index e68d4e24197..aa247859483 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
 obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_DNS) += dns.o
 obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 
diff --git a/net-lwip/dns.c b/net-lwip/dns.c
new file mode 100644
index 00000000000..24a5149343a
--- /dev/null
+++ b/net-lwip/dns.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <lwip/dns.h>
+#include <lwip/timeouts.h>
+#include <net-lwip.h>
+#include <time.h>
+
+#define DNS_RESEND_MS 1000
+#define DNS_TIMEOUT_MS 10000
+
+static ulong start;
+static ip_addr_t host_ipaddr;
+static bool done;
+
+static void do_dns_tmr(void *arg)
+{
+	dns_tmr();
+}
+
+static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
+{
+	const char *var = arg;
+	char *ipstr = ip4addr_ntoa(ipaddr);
+
+	done = true;
+
+	if (!ipaddr) {
+		printf("DNS: host not found\n");
+		host_ipaddr.addr = 0;
+		return;
+	}
+
+	if (var)
+		env_set(var, ipstr);
+
+	printf("%s\n", ipstr);
+}
+
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	bool has_server = false;
+	ip_addr_t ipaddr;
+	ip_addr_t ns;
+	char *nsenv;
+	char *name;
+	char *var;
+	int ret;
+
+	if (argc == 1 || argc > 3)
+		return CMD_RET_USAGE;
+
+	if (argc >= 2)
+		name = argv[1];
+
+	if (argc == 3)
+		var = argv[2];
+
+	dns_init();
+
+	nsenv = env_get("dnsip");
+	if (nsenv && ipaddr_aton(nsenv, &ns)) {
+		dns_setserver(0, &ns);
+		has_server = true;
+	}
+
+	nsenv = env_get("dnsip2");
+	if (nsenv && ipaddr_aton(nsenv, &ns)) {
+		dns_setserver(1, &ns);
+		has_server = true;
+	}
+
+	if (!has_server) {
+		log_err("No valid name server (dnsip/dnsip2)\n");
+		return CMD_RET_FAILURE;
+	}
+
+	done = false;
+
+	ret = dns_gethostbyname(name, &ipaddr, dns_cb, var);
+
+	if (ret == ERR_OK) {
+		dns_cb(name, &ipaddr, var);
+	} else if (ret == ERR_INPROGRESS) {
+		start = get_timer(0);
+		sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
+		do {
+			eth_rx();
+			if (done)
+				break;
+			sys_check_timeouts();
+			if (ctrlc()) {
+				printf("\nAbort\n");
+				break;
+			}
+		} while (get_timer(start) < DNS_TIMEOUT_MS);
+		sys_untimeout(do_dns_tmr, NULL);
+	}
+
+	if (done && host_ipaddr.addr != 0)
+		return CMD_RET_SUCCESS;
+
+	return CMD_RET_FAILURE;
+}
+
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 07/12] net-lwip: add wget command
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (5 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 06/12] net-lwip: add dns command Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 15:41   ` Ilias Apalodimas
  2024-06-06 13:36 ` [PATCH v3 08/12] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y Jerome Forissier
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Heinrich Schuchardt, Simon Glass, Mattijs Korpershoek,
	AKASHI Takahiro, Michal Simek, Francis Laniel, Peter Robinson,
	Abdellatif El Khlifi, Masahisa Kojima, Ramon Fried, Ioana Ciornei,
	Peng Fan, Sean Edmond

Add support for the wget command with NET_LWIP.

About the small change in cmd/efidebug.c: when the wget command based
on the lwIP stack is used the wget command has a built-in URL
validation function since it needs to parse it anyways (in parse_url()).
Therefore wget_validate_uri() doesn't exist. So, guard the call in
efidebug.c with CONFIG_CMD_WGET.

Based on code initially developed by Maxim U.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
Cc: Maxim Uvarov <muvarov@gmail.com>
---
 cmd/Kconfig        |   7 ++
 cmd/Makefile       |   5 +-
 cmd/efidebug.c     |   8 +-
 cmd/net-common.c   | 115 +++++++++++++++++++++++++++++
 cmd/net-lwip.c     |  12 +++
 cmd/net.c          | 115 -----------------------------
 include/net-lwip.h |  51 +++++++++++++
 net-lwip/Makefile  |   1 +
 net-lwip/wget.c    | 180 +++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 375 insertions(+), 119 deletions(-)
 create mode 100644 cmd/net-common.c
 create mode 100644 net-lwip/wget.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6ef0b52cd34..d9a86540be6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
 	help
 	  tftpboot - load file via network using TFTP protocol
 
+config CMD_WGET
+	bool "wget"
+	select PROT_TCP_LWIP
+	help
+	  wget is a simple command to download kernel, or other files,
+	  from a http server over TCP.
+
 endif
 
 endif
diff --git a/cmd/Makefile b/cmd/Makefile
index 535b6838ca5..e90f2f68211 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -129,8 +129,11 @@ obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
 obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+obj-$(filter y,$(CONFIG_CMD_NET) $(CONFIG_CMD_NET_LWIP)) += net-common.o
 ifdef CONFIG_CMD_NET_LWIP
-CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+lwip-includes := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+CFLAGS_net-lwip.o := $(lwip-includes)
+CFLAGS_net-common.o := $(lwip-includes)
 endif
 obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index c2c525f2351..d80e91ecadd 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -741,9 +741,11 @@ static int efi_boot_add_uri(int argc, char *const argv[], u16 *var_name16,
 	if (!label)
 		return CMD_RET_FAILURE;
 
-	if (!wget_validate_uri(argv[3])) {
-		printf("ERROR: invalid URI\n");
-		return CMD_RET_FAILURE;
+	if (IS_ENABLED(CONFIG_CMD_WGET)) {
+		if (!wget_validate_uri(argv[3])) {
+			printf("ERROR: invalid URI\n");
+			return CMD_RET_FAILURE;
+		}
 	}
 
 	efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
diff --git a/cmd/net-common.c b/cmd/net-common.c
new file mode 100644
index 00000000000..f01d9e63998
--- /dev/null
+++ b/cmd/net-common.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <command.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+#ifdef CONFIG_NET
+#include <net.h>
+#elif defined CONFIG_NET_LWIP
+#include <net-lwip.h>
+#else
+#error Either NET or NET_LWIP must be enabled
+#endif
+#include <linux/compat.h>
+#include <linux/ethtool.h>
+
+static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	const struct udevice *current = eth_get_dev();
+	unsigned char env_enetaddr[ARP_HLEN];
+	const struct udevice *dev;
+	struct uclass *uc;
+
+	uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
+		eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
+		printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
+		       current == dev ? "active" : "");
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	int nstats, err, i, off;
+	struct udevice *dev;
+	u64 *values;
+	u8 *strings;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
+	if (err) {
+		printf("Could not find device %s\n", argv[1]);
+		return CMD_RET_FAILURE;
+	}
+
+	if (!eth_get_ops(dev)->get_sset_count ||
+	    !eth_get_ops(dev)->get_strings ||
+	    !eth_get_ops(dev)->get_stats) {
+		printf("Driver does not implement stats dump!\n");
+		return CMD_RET_FAILURE;
+	}
+
+	nstats = eth_get_ops(dev)->get_sset_count(dev);
+	strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
+	if (!strings)
+		return CMD_RET_FAILURE;
+
+	values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
+	if (!values)
+		goto err_free_strings;
+
+	eth_get_ops(dev)->get_strings(dev, strings);
+	eth_get_ops(dev)->get_stats(dev, values);
+
+	off = 0;
+	for (i = 0; i < nstats; i++) {
+		printf("  %s: %llu\n", &strings[off], values[i]);
+		off += ETH_GSTRING_LEN;
+	};
+
+	kfree(strings);
+	kfree(values);
+
+	return CMD_RET_SUCCESS;
+
+err_free_strings:
+	kfree(strings);
+
+	return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_net[] = {
+	U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
+	U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
+};
+
+static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *cp;
+
+	cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
+
+	/* Drop the net command */
+	argc--;
+	argv++;
+
+	if (!cp || argc > cp->maxargs)
+		return CMD_RET_USAGE;
+	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+		return CMD_RET_SUCCESS;
+
+	return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+	net, 3, 1, do_net,
+	"NET sub-system",
+	"list - list available devices\n"
+	"stats <device> - dump statistics for specified device\n"
+);
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 3abafdf7969..b80375c831e 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -2,6 +2,10 @@
 /* Copyright (C) 2024 Linaro Ltd. */
 
 #include <command.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <linux/compat.h>
+#include <linux/ethtool.h>
 #include <net-lwip.h>
 
 #if defined(CONFIG_CMD_DHCP)
@@ -35,3 +39,11 @@ U_BOOT_CMD(
 	"hostname [envvar]"
 );
 #endif
+
+#if defined(CONFIG_CMD_WGET)
+U_BOOT_CMD(
+	wget,   3,      1,      do_wget,
+	"boot image via network using HTTP protocol",
+	"[loadAddress] URL"
+);
+#endif
diff --git a/cmd/net.c b/cmd/net.c
index d407d8320a3..03b4582204f 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -676,118 +676,3 @@ U_BOOT_CMD(
 );
 
 #endif  /* CONFIG_CMD_LINK_LOCAL */
-
-static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-	const struct udevice *current = eth_get_dev();
-	unsigned char env_enetaddr[ARP_HLEN];
-	const struct udevice *dev;
-	struct uclass *uc;
-
-	uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
-		eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
-		printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
-		       current == dev ? "active" : "");
-	}
-	return CMD_RET_SUCCESS;
-}
-
-static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-	int nstats, err, i, off;
-	struct udevice *dev;
-	u64 *values;
-	u8 *strings;
-
-	if (argc < 2)
-		return CMD_RET_USAGE;
-
-	err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
-	if (err) {
-		printf("Could not find device %s\n", argv[1]);
-		return CMD_RET_FAILURE;
-	}
-
-	if (!eth_get_ops(dev)->get_sset_count ||
-	    !eth_get_ops(dev)->get_strings ||
-	    !eth_get_ops(dev)->get_stats) {
-		printf("Driver does not implement stats dump!\n");
-		return CMD_RET_FAILURE;
-	}
-
-	nstats = eth_get_ops(dev)->get_sset_count(dev);
-	strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
-	if (!strings)
-		return CMD_RET_FAILURE;
-
-	values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
-	if (!values)
-		goto err_free_strings;
-
-	eth_get_ops(dev)->get_strings(dev, strings);
-	eth_get_ops(dev)->get_stats(dev, values);
-
-	off = 0;
-	for (i = 0; i < nstats; i++) {
-		printf("  %s: %llu\n", &strings[off], values[i]);
-		off += ETH_GSTRING_LEN;
-	};
-
-	return CMD_RET_SUCCESS;
-
-err_free_strings:
-	kfree(strings);
-
-	return CMD_RET_FAILURE;
-}
-
-static struct cmd_tbl cmd_net[] = {
-	U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
-	U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
-};
-
-static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
-	struct cmd_tbl *cp;
-
-	cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
-
-	/* Drop the net command */
-	argc--;
-	argv++;
-
-	if (!cp || argc > cp->maxargs)
-		return CMD_RET_USAGE;
-	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
-		return CMD_RET_SUCCESS;
-
-	return cp->cmd(cmdtp, flag, argc, argv);
-}
-
-U_BOOT_CMD(
-	net, 3, 1, do_net,
-	"NET sub-system",
-	"list - list available devices\n"
-	"stats <device> - dump statistics for specified device\n"
-);
-
-#if defined(CONFIG_CMD_NCSI)
-static int do_ncsi(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
-{
-	if (!phy_interface_is_ncsi() || !ncsi_active()) {
-		printf("Device not configured for NC-SI\n");
-		return CMD_RET_FAILURE;
-	}
-
-	if (net_loop(NCSI) < 0)
-		return CMD_RET_FAILURE;
-
-	return CMD_RET_SUCCESS;
-}
-
-U_BOOT_CMD(
-	ncsi,	1,	1,	do_ncsi,
-	"Configure attached NIC via NC-SI",
-	""
-);
-#endif  /* CONFIG_CMD_NCSI */
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 0019d1524e5..6fda940fec2 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -51,6 +51,56 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int index,
 int eth_init(void);			/* Initialize the device */
 int eth_send(void *packet, int length);	   /* Send a packet */
 int eth_rx(void);
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. If so, set the pointer to the
+ *	 packet buffer in the packetp parameter. If not, return an error or 0 to
+ *	 indicate that the hardware receive FIFO is empty. If 0 is returned, the
+ *	 network stack will not process the empty packet, but free_pkt() will be
+ *	 called if supplied
+ * free_pkt: Give the driver an opportunity to manage its packet buffer memory
+ *	     when the network stack is finished processing it. This will only be
+ *	     called when no error was returned from recv - optional
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *	 state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFTP) - optional
+ * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
+ *		 on some platforms like ARM). This function expects the
+ *		 eth_pdata::enetaddr field to be populated. The method can
+ *		 return -ENOSYS to indicate that this is not implemented for
+		 this hardware - optional.
+ * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
+ *		    ROM on the board. This is how the driver should expose it
+ *		    to the network stack. This function should fill in the
+ *		    eth_pdata::enetaddr field - optional
+ * set_promisc: Enable or Disable promiscuous mode
+ * get_sset_count: Number of statistics counters
+ * get_string: Names of the statistic counters
+ * get_stats: The values of the statistic counters
+ */
+struct eth_ops {
+	int (*start)(struct udevice *dev);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev, int flags, uchar **packetp);
+	int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
+	void (*stop)(struct udevice *dev);
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+	int (*write_hwaddr)(struct udevice *dev);
+	int (*read_rom_hwaddr)(struct udevice *dev);
+	int (*set_promisc)(struct udevice *dev, bool enable);
+	int (*get_sset_count)(struct udevice *dev);
+	void (*get_strings)(struct udevice *dev, u8 *data);
+	void (*get_stats)(struct udevice *dev, u64 *data);
+};
+
+#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
+
+struct udevice *eth_get_dev(void); /* get the current device */
+int eth_get_dev_index(void);
 const char *eth_get_name(void);
 int eth_get_dev_index(void);
 int eth_init_state_only(void); /* Set active state */
@@ -85,5 +135,6 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 
 #endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index aa247859483..bc011bb0e32 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
 obj-$(CONFIG_CMD_DNS) += dns.o
 obj-$(CONFIG_CMD_PING) += ping.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
+obj-$(CONFIG_CMD_WGET) += wget.o
 
 # Disable this warning as it is triggered by:
 # sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
new file mode 100644
index 00000000000..e3e6f525674
--- /dev/null
+++ b/net-lwip/wget.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <display_options.h>
+#include <image.h>
+#include <lwip/apps/http_client.h>
+#include <lwip/timeouts.h>
+#include <net-lwip.h>
+#include <time.h>
+
+#define SERVER_NAME_SIZE 200
+#define HTTP_PORT_DEFAULT 80
+
+static ulong daddr;
+static ulong saved_daddr;
+static ulong size;
+static ulong prevsize;
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+static ulong start_time;
+static enum done_state {
+        NOT_DONE = 0,
+        SUCCESS = 1,
+        FAILURE = 2
+} done;
+
+static int parse_url(char *url, char *host, u16 *port, char **path)
+{
+	char *p, *pp;
+	long lport;
+
+	p = strstr(url, "http://");
+	if (!p)
+		return -EINVAL;
+
+	p += strlen("http://");
+
+	/* Parse hostname */
+	pp = strchr(p, ':');
+	if (!pp)
+		pp = strchr(p, '/');
+	if (!pp)
+		return -EINVAL;
+
+	if (p + SERVER_NAME_SIZE <= pp)
+		return -EINVAL;
+
+	memcpy(host, p, pp - p);
+	host[pp - p + 1] = '\0';
+
+	if (*pp == ':') {
+		/* Parse port number */
+		p = pp + 1;
+		lport = simple_strtol(p, &pp, 10);
+		if (pp && *pp != '/')
+			return -EINVAL;
+		if (lport > 65535)
+			return -EINVAL;
+		*port = (u16)lport;
+	} else {
+		*port = HTTP_PORT_DEFAULT;
+	}
+	if (*pp != '/')
+		return -EINVAL;
+	*path = pp;
+
+	return 0;
+}
+
+static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf,
+			   err_t err)
+{
+	struct pbuf *buf;
+
+	if (!pbuf)
+		return ERR_BUF;
+
+	for (buf = pbuf; buf; buf = buf->next) {
+		memcpy((void *)daddr, buf->payload, buf->len);
+		daddr += buf->len;
+		size += buf->len;
+		if (size - prevsize > PROGRESS_PRINT_STEP_BYTES) {
+			printf("#");
+			prevsize = size;
+		}
+	}
+
+	altcp_recved(pcb, pbuf->tot_len);
+	pbuf_free(pbuf);
+	return ERR_OK;
+}
+
+static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
+			    u32_t rx_content_len, u32_t srv_res, err_t err)
+{
+	ulong elapsed;
+
+	if (httpc_result != HTTPC_RESULT_OK) {
+		log_err("\nHTTP client error %d\n", httpc_result);
+		done = FAILURE;
+		return;
+	}
+
+	elapsed = get_timer(start_time);
+        log_info("\n%u bytes transferred in %lu ms (", rx_content_len,
+                 get_timer(start_time));
+        print_size(rx_content_len / elapsed * 1000, "/s)\n");
+
+	if (env_set_hex("filesize", rx_content_len) ||
+	    env_set_hex("fileaddr", saved_daddr)) {
+		log_err("Could not set filesize or fileaddr\n");
+		done = FAILURE;
+		return;
+	}
+
+	done = SUCCESS;
+}
+
+int wget_with_dns(ulong dst_addr, char *uri)
+{
+	char server_name[SERVER_NAME_SIZE];
+	httpc_connection_t conn;
+	httpc_state_t *state;
+	char *path;
+	u16 port;
+
+	daddr = dst_addr;
+	saved_daddr = dst_addr;
+	done = NOT_DONE;
+	size = 0;
+	prevsize = 0;
+
+	if (parse_url(uri, server_name, &port, &path))
+		return CMD_RET_USAGE;
+
+	memset(&conn, 0, sizeof(conn));
+	conn.result_fn = httpc_result_cb;
+	start_time = get_timer(0);
+	if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
+			       NULL, &state))
+		return CMD_RET_FAILURE;
+
+	while (!done) {
+		eth_rx();
+		sys_check_timeouts();
+		if (ctrlc())
+			break;
+	}
+
+	if (done == SUCCESS)
+		return 0;
+
+	return -1;
+}
+
+int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *end;
+	char *url;
+	ulong dst_addr;
+
+	if (argc < 2 || argc > 3)
+		return CMD_RET_USAGE;
+
+	dst_addr = hextoul(argv[1], &end);
+        if (end == (argv[1] + strlen(argv[1]))) {
+		if (argc < 3)
+			return CMD_RET_USAGE;
+		url = argv[2];
+	} else {
+		dst_addr = image_load_addr;
+		url = argv[1];
+	}
+
+	if (wget_with_dns(dst_addr, url))
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 08/12] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (6 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 07/12] net-lwip: add wget command Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 13:36 ` [PATCH v3 09/12] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y Jerome Forissier
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Simon Glass, Tom Rini, Sean Anderson

Some sandbox tests make strong assumptions on how the network stack is
implemented. For example, the ping tests assume that ARP resolution
occurs upon sending out the ICMP packet. This is not always the case
with the lwIP stack which can cache ARP information.
Therefore, disable these tests when CONFIG_NET_LWIP is enabled.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 test/dm/dsa.c | 2 ++
 test/dm/eth.c | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/test/dm/dsa.c b/test/dm/dsa.c
index c857106eaf4..147e2a4afe2 100644
--- a/test/dm/dsa.c
+++ b/test/dm/dsa.c
@@ -59,6 +59,7 @@ static int dm_test_dsa_probe(struct unit_test_state *uts)
 
 DM_TEST(dm_test_dsa_probe, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* This test sends ping requests with the local address through each DSA port
  * via the sandbox DSA master Eth.
  */
@@ -80,3 +81,4 @@ static int dm_test_dsa(struct unit_test_state *uts)
 }
 
 DM_TEST(dm_test_dsa, UT_TESTF_SCAN_FDT);
+#endif /* !defined(CONFIG_NET_LWIP) */
diff --git a/test/dm/eth.c b/test/dm/eth.c
index bb3dcc6b954..cf97b1c1ab3 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -170,6 +170,7 @@ static int dm_test_ip6_make_lladdr(struct unit_test_state *uts)
 DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
 #endif
 
+#if !defined(CONFIG_NET_LWIP)
 static int dm_test_eth(struct unit_test_state *uts)
 {
 	net_ping_ip = string_to_ip("1.1.2.2");
@@ -298,6 +299,7 @@ static int dm_test_eth_act(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 /* Ensure that all addresses are loaded properly */
 static int dm_test_ethaddr(struct unit_test_state *uts)
@@ -332,6 +334,7 @@ static int dm_test_ethaddr(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
 
+#if !defined(CONFIG_NET_LWIP)
 /* The asserts include a return on fail; cleanup in the caller */
 static int _dm_test_eth_rotate1(struct unit_test_state *uts)
 {
@@ -616,6 +619,7 @@ static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
 }
 
 DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
+#endif /* !CONFIG_NET_LWIP */
 
 #if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 09/12] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (7 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 08/12] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 13:36 ` [PATCH v3 10/12] configs: add qemu_arm64_lwip_defconfig Jerome Forissier
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Bin Meng, Marek Vasut, Nikhil M Jain

Support "bdinfo -e" when lwIP is selected.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
---
 cmd/bdinfo.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 79106caeec2..690fb894bf6 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -152,7 +152,7 @@ static int bdinfo_print_all(struct bd_info *bd)
 	bdinfo_print_num_l("relocaddr", gd->relocaddr);
 	bdinfo_print_num_l("reloc off", gd->reloc_off);
 	printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
-	if (IS_ENABLED(CONFIG_CMD_NET))
+	if (IS_ENABLED(CONFIG_CMD_NET) || IS_ENABLED(CONFIG_CMD_NET_LWIP))
 		print_eth();
 	bdinfo_print_num_l("fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob));
 	bdinfo_print_num_l("new_fdt", (ulong)map_to_sysmem(gd->new_fdt));
@@ -198,7 +198,8 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		case 'a':
 			return bdinfo_print_all(bd);
 		case 'e':
-			if (!IS_ENABLED(CONFIG_CMD_NET))
+			if (!IS_ENABLED(CONFIG_CMD_NET) &&
+			    !IS_ENABLED(CONFIG_CMD_NET_LWIP))
 				return CMD_RET_USAGE;
 			print_eth();
 			return CMD_RET_SUCCESS;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 10/12] configs: add qemu_arm64_lwip_defconfig
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (8 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 09/12] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 13:36 ` [PATCH v3 11/12] MAINTAINERS: net-lwip: add myself as a maintainer Jerome Forissier
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini

Add qemu_arm64_lwip_defconfig based on qemu_arm64_defconfig but
with NET_LWIP instead of NET.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 configs/qemu_arm64_lwip_defconfig | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 configs/qemu_arm64_lwip_defconfig

diff --git a/configs/qemu_arm64_lwip_defconfig b/configs/qemu_arm64_lwip_defconfig
new file mode 100644
index 00000000000..050c93ff97b
--- /dev/null
+++ b/configs/qemu_arm64_lwip_defconfig
@@ -0,0 +1,3 @@
+#include <configs/qemu_arm64_defconfig>
+CONFIG_NET_LWIP=y
+# CONFIG_DFU_TFTP is not set
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 11/12] MAINTAINERS: net-lwip: add myself as a maintainer
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (9 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 10/12] configs: add qemu_arm64_lwip_defconfig Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 13:36 ` [PATCH v3 12/12] CI: add qemu_arm64_lwip to the test matrix Jerome Forissier
  2024-06-06 16:56 ` [PATCH v3 00/12] Introduce the lwIP network stack Tom Rini
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Mattijs Korpershoek, Abdellatif El Khlifi,
	Sumit Garg, Neil Armstrong, Caleb Connolly, Sam Protsenko,
	Marek Vasut, Nathan Barrett-Morrison

Add myself as a maintainer for the lwIP network stack integration code
and network commands. The library code itself (i.e., most files under
lib/lwip/ except README, Makefile and integration files in u-boot) is
unmodified from upstream and therefore does not need a maintainer.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
 MAINTAINERS | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f8afd7d51e2..11105869304 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1310,6 +1310,17 @@ F:	drivers/net/
 F:	include/net.h
 F:	net/
 
+NETWORK (LWIP)
+M:	Jerome Forissier <jerome.forissier@linaro.org>
+S:	Maintained
+F:	cmd/net-lwip.c
+F:	configs/qemu_arm64_lwip_defconfig
+F:	include/net-lwip.h
+F:	lib/lwip/Makefile
+F:	lib/lwip/README
+F:	lib/lwip/u-boot/
+F:	net-lwip/
+
 NIOS
 M:	Thomas Chou <thomas@wytron.com.tw>
 S:	Maintained
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 12/12] CI: add qemu_arm64_lwip to the test matrix
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (10 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 11/12] MAINTAINERS: net-lwip: add myself as a maintainer Jerome Forissier
@ 2024-06-06 13:36 ` Jerome Forissier
  2024-06-06 16:56 ` [PATCH v3 00/12] Introduce the lwIP network stack Tom Rini
  12 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 13:36 UTC (permalink / raw)
  To: u-boot
  Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
	Tom Rini, Simon Glass, Leo Yu-Chi Liang

Build and run qemu_arm64_lwip_defconfig in CI. This tests the lightweight
IP (lwIP) implementation of the dhcp, tftpboot and ping commands.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
 .azure-pipelines.yml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 27f69583c65..4da1bb12fab 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -199,6 +199,10 @@ stages:
           cd \${WORK_DIR}
           git config --global --add safe.directory \${WORK_DIR}
           git clone --depth=1 https://source.denx.de/u-boot/u-boot-test-hooks /tmp/uboot-test-hooks
+          # qemu_arm64_lwip_defconfig is the same as qemu_arm64 but with NET_LWIP enabled.
+          # The test config and the boardenv file from qemu_arm64 can be re-used so create symlinks
+          ln -s conf.qemu_arm64_na /tmp/uboot-test-hooks/bin/travis-ci/conf.qemu_arm64_lwip_na
+          ln -s u_boot_boardenv_qemu_arm64_na.py /tmp/uboot-test-hooks/py/travis-ci/u_boot_boardenv_qemu_arm64_lwip_na.py
           ln -s travis-ci /tmp/uboot-test-hooks/bin/\`hostname\`
           ln -s travis-ci /tmp/uboot-test-hooks/py/\`hostname\`
           grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
@@ -371,6 +375,9 @@ stages:
         qemu_arm64:
           TEST_PY_BD: "qemu_arm64"
           TEST_PY_TEST_SPEC: "not sleep"
+        qemu_arm64_lwip:
+          TEST_PY_BD: "qemu_arm64_lwip"
+          TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or test_net_tftpboot"
         qemu_m68k:
           TEST_PY_BD: "M5208EVBE"
           TEST_PY_ID: "--id qemu"
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 07/12] net-lwip: add wget command
  2024-06-06 13:36 ` [PATCH v3 07/12] net-lwip: add wget command Jerome Forissier
@ 2024-06-06 15:41   ` Ilias Apalodimas
  2024-06-07  9:23     ` Jerome Forissier
  0 siblings, 1 reply; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 15:41 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Heinrich Schuchardt,
	Simon Glass, Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson, Abdellatif El Khlifi,
	Masahisa Kojima, Ramon Fried, Ioana Ciornei, Peng Fan,
	Sean Edmond

Hi Jerome,

Can we split this in 2 patches instead?
A preparatory one, with split the net-common etc and one that adds wget?

Thanks
/Ilias

On Thu, 6 Jun 2024 at 16:37, Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> Add support for the wget command with NET_LWIP.
>
> About the small change in cmd/efidebug.c: when the wget command based
> on the lwIP stack is used the wget command has a built-in URL
> validation function since it needs to parse it anyways (in parse_url()).
> Therefore wget_validate_uri() doesn't exist. So, guard the call in
> efidebug.c with CONFIG_CMD_WGET.
>
> Based on code initially developed by Maxim U.
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
> Cc: Maxim Uvarov <muvarov@gmail.com>
> ---
>  cmd/Kconfig        |   7 ++
>  cmd/Makefile       |   5 +-
>  cmd/efidebug.c     |   8 +-
>  cmd/net-common.c   | 115 +++++++++++++++++++++++++++++
>  cmd/net-lwip.c     |  12 +++
>  cmd/net.c          | 115 -----------------------------
>  include/net-lwip.h |  51 +++++++++++++
>  net-lwip/Makefile  |   1 +
>  net-lwip/wget.c    | 180 +++++++++++++++++++++++++++++++++++++++++++++
>  9 files changed, 375 insertions(+), 119 deletions(-)
>  create mode 100644 cmd/net-common.c
>  create mode 100644 net-lwip/wget.c
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 6ef0b52cd34..d9a86540be6 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
>         help
>           tftpboot - load file via network using TFTP protocol
>
> +config CMD_WGET
> +       bool "wget"
> +       select PROT_TCP_LWIP
> +       help
> +         wget is a simple command to download kernel, or other files,
> +         from a http server over TCP.
> +
>  endif
>
>  endif
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 535b6838ca5..e90f2f68211 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -129,8 +129,11 @@ obj-$(CONFIG_CMD_MUX) += mux.o
>  obj-$(CONFIG_CMD_NAND) += nand.o
>  obj-$(CONFIG_CMD_NET) += net.o
>  obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
> +obj-$(filter y,$(CONFIG_CMD_NET) $(CONFIG_CMD_NET_LWIP)) += net-common.o
>  ifdef CONFIG_CMD_NET_LWIP
> -CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
> +lwip-includes := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
> +CFLAGS_net-lwip.o := $(lwip-includes)
> +CFLAGS_net-common.o := $(lwip-includes)
>  endif
>  obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
>  obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
> diff --git a/cmd/efidebug.c b/cmd/efidebug.c
> index c2c525f2351..d80e91ecadd 100644
> --- a/cmd/efidebug.c
> +++ b/cmd/efidebug.c
> @@ -741,9 +741,11 @@ static int efi_boot_add_uri(int argc, char *const argv[], u16 *var_name16,
>         if (!label)
>                 return CMD_RET_FAILURE;
>
> -       if (!wget_validate_uri(argv[3])) {
> -               printf("ERROR: invalid URI\n");
> -               return CMD_RET_FAILURE;
> +       if (IS_ENABLED(CONFIG_CMD_WGET)) {
> +               if (!wget_validate_uri(argv[3])) {
> +                       printf("ERROR: invalid URI\n");
> +                       return CMD_RET_FAILURE;
> +               }
>         }
>
>         efi_create_indexed_name(var_name16, var_name16_size, "Boot", id);
> diff --git a/cmd/net-common.c b/cmd/net-common.c
> new file mode 100644
> index 00000000000..f01d9e63998
> --- /dev/null
> +++ b/cmd/net-common.c
> @@ -0,0 +1,115 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2000
> + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
> + */
> +
> +#include <command.h>
> +#include <dm/device.h>
> +#include <dm/uclass.h>
> +#ifdef CONFIG_NET
> +#include <net.h>
> +#elif defined CONFIG_NET_LWIP
> +#include <net-lwip.h>
> +#else
> +#error Either NET or NET_LWIP must be enabled
> +#endif
> +#include <linux/compat.h>
> +#include <linux/ethtool.h>
> +
> +static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       const struct udevice *current = eth_get_dev();
> +       unsigned char env_enetaddr[ARP_HLEN];
> +       const struct udevice *dev;
> +       struct uclass *uc;
> +
> +       uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
> +               eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
> +               printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
> +                      current == dev ? "active" : "");
> +       }
> +       return CMD_RET_SUCCESS;
> +}
> +
> +static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       int nstats, err, i, off;
> +       struct udevice *dev;
> +       u64 *values;
> +       u8 *strings;
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +       err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
> +       if (err) {
> +               printf("Could not find device %s\n", argv[1]);
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (!eth_get_ops(dev)->get_sset_count ||
> +           !eth_get_ops(dev)->get_strings ||
> +           !eth_get_ops(dev)->get_stats) {
> +               printf("Driver does not implement stats dump!\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       nstats = eth_get_ops(dev)->get_sset_count(dev);
> +       strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
> +       if (!strings)
> +               return CMD_RET_FAILURE;
> +
> +       values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
> +       if (!values)
> +               goto err_free_strings;
> +
> +       eth_get_ops(dev)->get_strings(dev, strings);
> +       eth_get_ops(dev)->get_stats(dev, values);
> +
> +       off = 0;
> +       for (i = 0; i < nstats; i++) {
> +               printf("  %s: %llu\n", &strings[off], values[i]);
> +               off += ETH_GSTRING_LEN;
> +       };
> +
> +       kfree(strings);
> +       kfree(values);
> +
> +       return CMD_RET_SUCCESS;
> +
> +err_free_strings:
> +       kfree(strings);
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +static struct cmd_tbl cmd_net[] = {
> +       U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
> +       U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
> +};
> +
> +static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct cmd_tbl *cp;
> +
> +       cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
> +
> +       /* Drop the net command */
> +       argc--;
> +       argv++;
> +
> +       if (!cp || argc > cp->maxargs)
> +               return CMD_RET_USAGE;
> +       if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
> +               return CMD_RET_SUCCESS;
> +
> +       return cp->cmd(cmdtp, flag, argc, argv);
> +}
> +
> +U_BOOT_CMD(
> +       net, 3, 1, do_net,
> +       "NET sub-system",
> +       "list - list available devices\n"
> +       "stats <device> - dump statistics for specified device\n"
> +);
> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
> index 3abafdf7969..b80375c831e 100644
> --- a/cmd/net-lwip.c
> +++ b/cmd/net-lwip.c
> @@ -2,6 +2,10 @@
>  /* Copyright (C) 2024 Linaro Ltd. */
>
>  #include <command.h>
> +#include <dm/device.h>
> +#include <dm/uclass.h>
> +#include <linux/compat.h>
> +#include <linux/ethtool.h>
>  #include <net-lwip.h>
>
>  #if defined(CONFIG_CMD_DHCP)
> @@ -35,3 +39,11 @@ U_BOOT_CMD(
>         "hostname [envvar]"
>  );
>  #endif
> +
> +#if defined(CONFIG_CMD_WGET)
> +U_BOOT_CMD(
> +       wget,   3,      1,      do_wget,
> +       "boot image via network using HTTP protocol",
> +       "[loadAddress] URL"
> +);
> +#endif
> diff --git a/cmd/net.c b/cmd/net.c
> index d407d8320a3..03b4582204f 100644
> --- a/cmd/net.c
> +++ b/cmd/net.c
> @@ -676,118 +676,3 @@ U_BOOT_CMD(
>  );
>
>  #endif  /* CONFIG_CMD_LINK_LOCAL */
> -
> -static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> -{
> -       const struct udevice *current = eth_get_dev();
> -       unsigned char env_enetaddr[ARP_HLEN];
> -       const struct udevice *dev;
> -       struct uclass *uc;
> -
> -       uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
> -               eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
> -               printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
> -                      current == dev ? "active" : "");
> -       }
> -       return CMD_RET_SUCCESS;
> -}
> -
> -static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> -{
> -       int nstats, err, i, off;
> -       struct udevice *dev;
> -       u64 *values;
> -       u8 *strings;
> -
> -       if (argc < 2)
> -               return CMD_RET_USAGE;
> -
> -       err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
> -       if (err) {
> -               printf("Could not find device %s\n", argv[1]);
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       if (!eth_get_ops(dev)->get_sset_count ||
> -           !eth_get_ops(dev)->get_strings ||
> -           !eth_get_ops(dev)->get_stats) {
> -               printf("Driver does not implement stats dump!\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       nstats = eth_get_ops(dev)->get_sset_count(dev);
> -       strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
> -       if (!strings)
> -               return CMD_RET_FAILURE;
> -
> -       values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
> -       if (!values)
> -               goto err_free_strings;
> -
> -       eth_get_ops(dev)->get_strings(dev, strings);
> -       eth_get_ops(dev)->get_stats(dev, values);
> -
> -       off = 0;
> -       for (i = 0; i < nstats; i++) {
> -               printf("  %s: %llu\n", &strings[off], values[i]);
> -               off += ETH_GSTRING_LEN;
> -       };
> -
> -       return CMD_RET_SUCCESS;
> -
> -err_free_strings:
> -       kfree(strings);
> -
> -       return CMD_RET_FAILURE;
> -}
> -
> -static struct cmd_tbl cmd_net[] = {
> -       U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
> -       U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
> -};
> -
> -static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> -{
> -       struct cmd_tbl *cp;
> -
> -       cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
> -
> -       /* Drop the net command */
> -       argc--;
> -       argv++;
> -
> -       if (!cp || argc > cp->maxargs)
> -               return CMD_RET_USAGE;
> -       if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
> -               return CMD_RET_SUCCESS;
> -
> -       return cp->cmd(cmdtp, flag, argc, argv);
> -}
> -
> -U_BOOT_CMD(
> -       net, 3, 1, do_net,
> -       "NET sub-system",
> -       "list - list available devices\n"
> -       "stats <device> - dump statistics for specified device\n"
> -);
> -
> -#if defined(CONFIG_CMD_NCSI)
> -static int do_ncsi(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
> -{
> -       if (!phy_interface_is_ncsi() || !ncsi_active()) {
> -               printf("Device not configured for NC-SI\n");
> -               return CMD_RET_FAILURE;
> -       }
> -
> -       if (net_loop(NCSI) < 0)
> -               return CMD_RET_FAILURE;
> -
> -       return CMD_RET_SUCCESS;
> -}
> -
> -U_BOOT_CMD(
> -       ncsi,   1,      1,      do_ncsi,
> -       "Configure attached NIC via NC-SI",
> -       ""
> -);
> -#endif  /* CONFIG_CMD_NCSI */
> diff --git a/include/net-lwip.h b/include/net-lwip.h
> index 0019d1524e5..6fda940fec2 100644
> --- a/include/net-lwip.h
> +++ b/include/net-lwip.h
> @@ -51,6 +51,56 @@ int eth_env_get_enetaddr_by_index(const char *base_name, int index,
>  int eth_init(void);                    /* Initialize the device */
>  int eth_send(void *packet, int length);           /* Send a packet */
>  int eth_rx(void);
> +
> +/**
> + * struct eth_ops - functions of Ethernet MAC controllers
> + *
> + * start: Prepare the hardware to send and receive packets
> + * send: Send the bytes passed in "packet" as a packet on the wire
> + * recv: Check if the hardware received a packet. If so, set the pointer to the
> + *      packet buffer in the packetp parameter. If not, return an error or 0 to
> + *      indicate that the hardware receive FIFO is empty. If 0 is returned, the
> + *      network stack will not process the empty packet, but free_pkt() will be
> + *      called if supplied
> + * free_pkt: Give the driver an opportunity to manage its packet buffer memory
> + *          when the network stack is finished processing it. This will only be
> + *          called when no error was returned from recv - optional
> + * stop: Stop the hardware from looking for packets - may be called even if
> + *      state == PASSIVE
> + * mcast: Join or leave a multicast group (for TFTP) - optional
> + * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
> + *              on some platforms like ARM). This function expects the
> + *              eth_pdata::enetaddr field to be populated. The method can
> + *              return -ENOSYS to indicate that this is not implemented for
> +                this hardware - optional.
> + * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
> + *                 ROM on the board. This is how the driver should expose it
> + *                 to the network stack. This function should fill in the
> + *                 eth_pdata::enetaddr field - optional
> + * set_promisc: Enable or Disable promiscuous mode
> + * get_sset_count: Number of statistics counters
> + * get_string: Names of the statistic counters
> + * get_stats: The values of the statistic counters
> + */
> +struct eth_ops {
> +       int (*start)(struct udevice *dev);
> +       int (*send)(struct udevice *dev, void *packet, int length);
> +       int (*recv)(struct udevice *dev, int flags, uchar **packetp);
> +       int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
> +       void (*stop)(struct udevice *dev);
> +       int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
> +       int (*write_hwaddr)(struct udevice *dev);
> +       int (*read_rom_hwaddr)(struct udevice *dev);
> +       int (*set_promisc)(struct udevice *dev, bool enable);
> +       int (*get_sset_count)(struct udevice *dev);
> +       void (*get_strings)(struct udevice *dev, u8 *data);
> +       void (*get_stats)(struct udevice *dev, u64 *data);
> +};
> +
> +#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
> +
> +struct udevice *eth_get_dev(void); /* get the current device */
> +int eth_get_dev_index(void);
>  const char *eth_get_name(void);
>  int eth_get_dev_index(void);
>  int eth_init_state_only(void); /* Set active state */
> @@ -85,5 +135,6 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>  int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>  int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>  int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
>
>  #endif /* __NET_LWIP_H__ */
> diff --git a/net-lwip/Makefile b/net-lwip/Makefile
> index aa247859483..bc011bb0e32 100644
> --- a/net-lwip/Makefile
> +++ b/net-lwip/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
>  obj-$(CONFIG_CMD_DNS) += dns.o
>  obj-$(CONFIG_CMD_PING) += ping.o
>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
> +obj-$(CONFIG_CMD_WGET) += wget.o
>
>  # Disable this warning as it is triggered by:
>  # sprintf(buf, index ? "foo%d" : "foo", index)
> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
> new file mode 100644
> index 00000000000..e3e6f525674
> --- /dev/null
> +++ b/net-lwip/wget.c
> @@ -0,0 +1,180 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <console.h>
> +#include <display_options.h>
> +#include <image.h>
> +#include <lwip/apps/http_client.h>
> +#include <lwip/timeouts.h>
> +#include <net-lwip.h>
> +#include <time.h>
> +
> +#define SERVER_NAME_SIZE 200
> +#define HTTP_PORT_DEFAULT 80
> +
> +static ulong daddr;
> +static ulong saved_daddr;
> +static ulong size;
> +static ulong prevsize;
> +#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
> +static ulong start_time;
> +static enum done_state {
> +        NOT_DONE = 0,
> +        SUCCESS = 1,
> +        FAILURE = 2
> +} done;
> +
> +static int parse_url(char *url, char *host, u16 *port, char **path)
> +{
> +       char *p, *pp;
> +       long lport;
> +
> +       p = strstr(url, "http://");
> +       if (!p)
> +               return -EINVAL;
> +
> +       p += strlen("http://");
> +
> +       /* Parse hostname */
> +       pp = strchr(p, ':');
> +       if (!pp)
> +               pp = strchr(p, '/');
> +       if (!pp)
> +               return -EINVAL;
> +
> +       if (p + SERVER_NAME_SIZE <= pp)
> +               return -EINVAL;
> +
> +       memcpy(host, p, pp - p);
> +       host[pp - p + 1] = '\0';
> +
> +       if (*pp == ':') {
> +               /* Parse port number */
> +               p = pp + 1;
> +               lport = simple_strtol(p, &pp, 10);
> +               if (pp && *pp != '/')
> +                       return -EINVAL;
> +               if (lport > 65535)
> +                       return -EINVAL;
> +               *port = (u16)lport;
> +       } else {
> +               *port = HTTP_PORT_DEFAULT;
> +       }
> +       if (*pp != '/')
> +               return -EINVAL;
> +       *path = pp;
> +
> +       return 0;
> +}
> +
> +static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf,
> +                          err_t err)
> +{
> +       struct pbuf *buf;
> +
> +       if (!pbuf)
> +               return ERR_BUF;
> +
> +       for (buf = pbuf; buf; buf = buf->next) {
> +               memcpy((void *)daddr, buf->payload, buf->len);
> +               daddr += buf->len;
> +               size += buf->len;
> +               if (size - prevsize > PROGRESS_PRINT_STEP_BYTES) {
> +                       printf("#");
> +                       prevsize = size;
> +               }
> +       }
> +
> +       altcp_recved(pcb, pbuf->tot_len);
> +       pbuf_free(pbuf);
> +       return ERR_OK;
> +}
> +
> +static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
> +                           u32_t rx_content_len, u32_t srv_res, err_t err)
> +{
> +       ulong elapsed;
> +
> +       if (httpc_result != HTTPC_RESULT_OK) {
> +               log_err("\nHTTP client error %d\n", httpc_result);
> +               done = FAILURE;
> +               return;
> +       }
> +
> +       elapsed = get_timer(start_time);
> +        log_info("\n%u bytes transferred in %lu ms (", rx_content_len,
> +                 get_timer(start_time));
> +        print_size(rx_content_len / elapsed * 1000, "/s)\n");
> +
> +       if (env_set_hex("filesize", rx_content_len) ||
> +           env_set_hex("fileaddr", saved_daddr)) {
> +               log_err("Could not set filesize or fileaddr\n");
> +               done = FAILURE;
> +               return;
> +       }
> +
> +       done = SUCCESS;
> +}
> +
> +int wget_with_dns(ulong dst_addr, char *uri)
> +{
> +       char server_name[SERVER_NAME_SIZE];
> +       httpc_connection_t conn;
> +       httpc_state_t *state;
> +       char *path;
> +       u16 port;
> +
> +       daddr = dst_addr;
> +       saved_daddr = dst_addr;
> +       done = NOT_DONE;
> +       size = 0;
> +       prevsize = 0;
> +
> +       if (parse_url(uri, server_name, &port, &path))
> +               return CMD_RET_USAGE;
> +
> +       memset(&conn, 0, sizeof(conn));
> +       conn.result_fn = httpc_result_cb;
> +       start_time = get_timer(0);
> +       if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
> +                              NULL, &state))
> +               return CMD_RET_FAILURE;
> +
> +       while (!done) {
> +               eth_rx();
> +               sys_check_timeouts();
> +               if (ctrlc())
> +                       break;
> +       }
> +
> +       if (done == SUCCESS)
> +               return 0;
> +
> +       return -1;
> +}
> +
> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       char *end;
> +       char *url;
> +       ulong dst_addr;
> +
> +       if (argc < 2 || argc > 3)
> +               return CMD_RET_USAGE;
> +
> +       dst_addr = hextoul(argv[1], &end);
> +        if (end == (argv[1] + strlen(argv[1]))) {
> +               if (argc < 3)
> +                       return CMD_RET_USAGE;
> +               url = argv[2];
> +       } else {
> +               dst_addr = image_load_addr;
> +               url = argv[1];
> +       }
> +
> +       if (wget_with_dns(dst_addr, url))
> +               return CMD_RET_FAILURE;
> +
> +       return CMD_RET_SUCCESS;
> +}
> --
> 2.40.1
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 06/12] net-lwip: add dns command
  2024-06-06 13:36 ` [PATCH v3 06/12] net-lwip: add dns command Jerome Forissier
@ 2024-06-06 15:46   ` Ilias Apalodimas
  2024-06-06 15:59     ` Jerome Forissier
  0 siblings, 1 reply; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 15:46 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Mattijs Korpershoek, AKASHI Takahiro, Francis Laniel,
	Peter Robinson

> @@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
>  obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
>  obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
>  obj-$(CONFIG_CMD_DHCP) += dhcp.o
> +obj-$(CONFIG_CMD_DNS) += dns.o
>  obj-$(CONFIG_CMD_PING) += ping.o
>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>
> diff --git a/net-lwip/dns.c b/net-lwip/dns.c
> new file mode 100644
> index 00000000000..24a5149343a
> --- /dev/null
> +++ b/net-lwip/dns.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <console.h>
> +#include <lwip/dns.h>
> +#include <lwip/timeouts.h>
> +#include <net-lwip.h>
> +#include <time.h>
> +
> +#define DNS_RESEND_MS 1000
> +#define DNS_TIMEOUT_MS 10000
> +
> +static ulong start;
> +static ip_addr_t host_ipaddr;
> +static bool done;
> +
> +static void do_dns_tmr(void *arg)
> +{
> +       dns_tmr();
> +}
> +
> +static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
> +{
> +       const char *var = arg;
> +       char *ipstr = ip4addr_ntoa(ipaddr);
> +
> +       done = true;
> +
> +       if (!ipaddr) {
> +               printf("DNS: host not found\n");
> +               host_ipaddr.addr = 0;
> +               return;
> +       }
> +
> +       if (var)
> +               env_set(var, ipstr);

Do we need this? Won't this set <dns_name> == ipaddr?
If we do not need it repurpose the void *arg and get rid of the global 'done'

> +
> +       printf("%s\n", ipstr);
> +}
> +
> +int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       bool has_server = false;
> +       ip_addr_t ipaddr;
> +       ip_addr_t ns;
> +       char *nsenv;
> +       char *name;
> +       char *var;
> +       int ret;

[...]

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 02/12] net-lwip: build lwIP
  2024-06-06 13:35 ` [PATCH v3 02/12] net-lwip: build lwIP Jerome Forissier
@ 2024-06-06 15:50   ` Ilias Apalodimas
  0 siblings, 0 replies; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 15:50 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Sean Anderson, Oleksandr Suvorov

On Thu, 6 Jun 2024 at 16:36, Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> Build the lwIP library when NET_LWIP is enabled. The following files
> are adaptation layers written specially for U-Boot:
>
>  lib/lwip/u-boot/arch/cc.h
>  lib/lwip/u-boot/arch/sys_arch.h (empty)
>  lib/lwip/u-boot/limits.h (empty)
>  lib/lwip/u-boot/lwipopts.h
>
> They were initially contributed by Maxim in a previous RFC patch series.
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
> Cc: Maxim Uvarov <muvarov@gmail.com>
> ---
>  lib/Makefile                    |   2 +
>  lib/lwip/Makefile               |  57 +++++++++
>  lib/lwip/u-boot/arch/cc.h       |  43 +++++++
>  lib/lwip/u-boot/arch/sys_arch.h |   0
>  lib/lwip/u-boot/limits.h        |   0
>  lib/lwip/u-boot/lwipopts.h      | 197 ++++++++++++++++++++++++++++++++
>  6 files changed, 299 insertions(+)
>  create mode 100644 lib/lwip/Makefile
>  create mode 100644 lib/lwip/u-boot/arch/cc.h
>  create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
>  create mode 100644 lib/lwip/u-boot/limits.h
>  create mode 100644 lib/lwip/u-boot/lwipopts.h
>
> diff --git a/lib/Makefile b/lib/Makefile
> index 2a76acf100d..c35786a0576 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -94,6 +94,8 @@ obj-$(CONFIG_LIBAVB) += libavb/
>  obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
>  obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
>
> +obj-$(CONFIG_NET_LWIP) += lwip/
> +
>  ifdef CONFIG_SPL_BUILD
>  obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o
>  obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o
> diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
> new file mode 100644
> index 00000000000..158e59b91fc
> --- /dev/null
> +++ b/lib/lwip/Makefile
> @@ -0,0 +1,57 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright (C) 2024 Linaro Ltd.
> +
> +ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
> +
> +obj-y += \
> +       lwip/src/api/api_lib.o \
> +       lwip/src/api/api_msg.o \
> +       lwip/src/api/err.o \
> +       lwip/src/api/if_api.o \
> +       lwip/src/api/netbuf.o \
> +       lwip/src/api/netdb.o \
> +       lwip/src/api/netifapi.o \
> +       lwip/src/api/sockets.o \
> +       lwip/src/api/tcpip.o \
> +       lwip/src/apps/http/http_client.o \
> +       lwip/src/apps/tftp/tftp.o \
> +       lwip/src/core/altcp_alloc.o \
> +       lwip/src/core/altcp.o \
> +       lwip/src/core/altcp_tcp.o \
> +       lwip/src/core/def.o \
> +       lwip/src/core/dns.o \
> +       lwip/src/core/inet_chksum.o \
> +       lwip/src/core/init.o \
> +       lwip/src/core/ip.o \
> +       lwip/src/core/ipv4/acd.o \
> +       lwip/src/core/ipv4/autoip.o \
> +       lwip/src/core/ipv4/dhcp.o \
> +       lwip/src/core/ipv4/etharp.o \
> +       lwip/src/core/ipv4/icmp.o \
> +       lwip/src/core/ipv4/igmp.o \
> +       lwip/src/core/ipv4/ip4_addr.o \
> +       lwip/src/core/ipv4/ip4.o \
> +       lwip/src/core/ipv4/ip4_frag.o \
> +       lwip/src/core/ipv6/dhcp6.o \
> +       lwip/src/core/ipv6/ethip6.o \
> +       lwip/src/core/ipv6/icmp6.o \
> +       lwip/src/core/ipv6/inet6.o \
> +       lwip/src/core/ipv6/ip6_addr.o \
> +       lwip/src/core/ipv6/ip6.o \
> +       lwip/src/core/ipv6/ip6_frag.o \
> +       lwip/src/core/ipv6/mld6.o \
> +       lwip/src/core/ipv6/nd6.o \
> +       lwip/src/core/mem.o \
> +       lwip/src/core/memp.o \
> +       lwip/src/core/netif.o \
> +       lwip/src/core/pbuf.o \
> +       lwip/src/core/raw.o \
> +       lwip/src/core/stats.o \
> +       lwip/src/core/sys.o \
> +       lwip/src/core/tcp.o \
> +       lwip/src/core/tcp_in.o \
> +       lwip/src/core/tcp_out.o \
> +       lwip/src/core/timeouts.o \
> +       lwip/src/core/udp.o \
> +       lwip/src/netif/ethernet.o
> diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
> new file mode 100644
> index 00000000000..31c036dc0c5
> --- /dev/null
> +++ b/lib/lwip/u-boot/arch/cc.h
> @@ -0,0 +1,43 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2023 Linaro Ltd. <maxim.uvarov@linaro.org> */
> +
> +#ifndef LWIP_ARCH_CC_H
> +#define LWIP_ARCH_CC_H
> +
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <vsprintf.h>
> +#include <rand.h>
> +
> +#define LWIP_ERRNO_INCLUDE <errno.h>
> +
> +#define LWIP_ERRNO_STDINCLUDE  1
> +#define LWIP_NO_UNISTD_H 1
> +#define LWIP_TIMEVAL_PRIVATE 1
> +
> +#ifdef CONFIG_LIB_RAND
> +#define LWIP_RAND() ((u32_t)rand())
> +#endif
> +
> +/* different handling for unit test, normally not needed */
> +#ifdef LWIP_NOASSERT_ON_ERROR
> +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
> +                                               handler; }} while (0)
> +#endif
> +
> +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
> +
> +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
> +                                   x, __LINE__, __FILE__); } while (0)
> +
> +#define atoi(str) (int)dectoul(str, NULL)
> +#define lwip_strnstr(a, b)  strnstr(a, b)
> +
> +#define LWIP_ERR_T int
> +#define LWIP_CONST_CAST(target_type, val) ((target_type)((uintptr_t)val))
> +
> +#if defined(CONFIG_SYS_BIG_ENDIAN)
> +#define BYTE_ORDER BIG_ENDIAN
> +#endif
> +
> +#endif /* LWIP_ARCH_CC_H */
> diff --git a/lib/lwip/u-boot/arch/sys_arch.h b/lib/lwip/u-boot/arch/sys_arch.h
> new file mode 100644
> index 00000000000..e69de29bb2d
> diff --git a/lib/lwip/u-boot/limits.h b/lib/lwip/u-boot/limits.h
> new file mode 100644
> index 00000000000..e69de29bb2d
> diff --git a/lib/lwip/u-boot/lwipopts.h b/lib/lwip/u-boot/lwipopts.h
> new file mode 100644
> index 00000000000..aac0a6259fd
> --- /dev/null
> +++ b/lib/lwip/u-boot/lwipopts.h
> @@ -0,0 +1,197 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +/* Copyright (C) 2023 Linaro Ltd. <maxim.uvarov@linaro.org> */
> +
> +#ifndef LWIP_UBOOT_LWIPOPTS_H
> +#define LWIP_UBOOT_LWIPOPTS_H
> +
> +#if defined(CONFIG_LWIP_DEBUG)
> +#define LWIP_DEBUG 1
> +#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
> +#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
> +#define ETHARP_DEBUG                    LWIP_DBG_ON
> +#define NETIF_DEBUG                     LWIP_DBG_ON
> +#define PBUF_DEBUG                      LWIP_DBG_OFF
> +#define API_LIB_DEBUG                   LWIP_DBG_ON
> +#define API_MSG_DEBUG                   LWIP_DBG_OFF
> +#define SOCKETS_DEBUG                   LWIP_DBG_OFF
> +#define ICMP_DEBUG                      LWIP_DBG_OFF
> +#define IGMP_DEBUG                      LWIP_DBG_OFF
> +#define INET_DEBUG                      LWIP_DBG_OFF
> +#define IP_DEBUG                        LWIP_DBG_ON
> +#define IP_REASS_DEBUG                  LWIP_DBG_OFF
> +#define RAW_DEBUG                       LWIP_DBG_OFF
> +#define MEM_DEBUG                       LWIP_DBG_OFF
> +#define MEMP_DEBUG                      LWIP_DBG_OFF
> +#define SYS_DEBUG                       LWIP_DBG_OFF
> +#define TIMERS_DEBUG                    LWIP_DBG_ON
> +#define TCP_DEBUG                       LWIP_DBG_OFF
> +#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
> +#define TCP_FR_DEBUG                    LWIP_DBG_OFF
> +#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
> +#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
> +#define TCP_WND_DEBUG                   LWIP_DBG_OFF
> +#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
> +#define TCP_RST_DEBUG                   LWIP_DBG_OFF
> +#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
> +#define UDP_DEBUG                       LWIP_DBG_OFF
> +#define TCPIP_DEBUG                     LWIP_DBG_OFF
> +#define SLIP_DEBUG                      LWIP_DBG_OFF
> +#define DHCP_DEBUG                      LWIP_DBG_ON
> +#define AUTOIP_DEBUG                    LWIP_DBG_ON
> +#define DNS_DEBUG                       LWIP_DBG_ON
> +#define IP6_DEBUG                       LWIP_DBG_OFF
> +#define DHCP6_DEBUG                     LWIP_DBG_OFF
> +#else
> +#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
> +#define LWIP_DBG_TYPES_ON               LWIP_DBG_OFF
> +#define ETHARP_DEBUG                    LWIP_DBG_OFF
> +#define NETIF_DEBUG                     LWIP_DBG_OFF
> +#define PBUF_DEBUG                      LWIP_DBG_OFF
> +#define API_LIB_DEBUG                   LWIP_DBG_OFF
> +#define API_MSG_DEBUG                   LWIP_DBG_OFF
> +#define SOCKETS_DEBUG                   LWIP_DBG_OFF
> +#define ICMP_DEBUG                      LWIP_DBG_OFF
> +#define IGMP_DEBUG                      LWIP_DBG_OFF
> +#define INET_DEBUG                      LWIP_DBG_OFF
> +#define IP_DEBUG                        LWIP_DBG_OFF
> +#define IP_REASS_DEBUG                  LWIP_DBG_OFF
> +#define RAW_DEBUG                       LWIP_DBG_OFF
> +#define MEM_DEBUG                       LWIP_DBG_OFF
> +#define MEMP_DEBUG                      LWIP_DBG_OFF
> +#define SYS_DEBUG                       LWIP_DBG_OFF
> +#define TIMERS_DEBUG                    LWIP_DBG_OFF
> +#define TCP_DEBUG                       LWIP_DBG_OFF
> +#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
> +#define TCP_FR_DEBUG                    LWIP_DBG_OFF
> +#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
> +#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
> +#define TCP_WND_DEBUG                   LWIP_DBG_OFF
> +#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
> +#define TCP_RST_DEBUG                   LWIP_DBG_OFF
> +#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
> +#define UDP_DEBUG                       LWIP_DBG_OFF
> +#define TCPIP_DEBUG                     LWIP_DBG_OFF
> +#define SLIP_DEBUG                      LWIP_DBG_OFF
> +#define DHCP_DEBUG                      LWIP_DBG_OFF
> +#define AUTOIP_DEBUG                    LWIP_DBG_OFF
> +#define DNS_DEBUG                       LWIP_DBG_OFF
> +#define IP6_DEBUG                       LWIP_DBG_OFF
> +#define DHCP6_DEBUG                     LWIP_DBG_OFF
> +#endif
> +#define LWIP_TESTMODE                   0
> +
> +#if !defined(CONFIG_LWIP_ASSERT)
> +#define LWIP_NOASSERT 1
> +#define LWIP_ASSERT(message, assertion)
> +#endif
> +
> +#include "lwip/debug.h"
> +
> +#define SYS_LIGHTWEIGHT_PROT            0
> +#define NO_SYS                          1
> +
> +#define LWIP_IPV4                      1
> +#define LWIP_IPV6                      0
> +
> +#define MEM_ALIGNMENT                   1
> +#define MEM_SIZE                        1600
> +
> +#define MEMP_NUM_PBUF                   4
> +#define MEMP_NUM_RAW_PCB                2
> +#define MEMP_NUM_UDP_PCB                4
> +#define MEMP_NUM_TCP_PCB                2
> +#define MEMP_NUM_TCP_PCB_LISTEN         2
> +#define MEMP_NUM_TCP_SEG                16
> +#define MEMP_NUM_REASSDATA              1
> +#define MEMP_NUM_ARP_QUEUE              2
> +#define MEMP_NUM_SYS_TIMEOUT            4
> +#define MEMP_NUM_NETBUF                 2
> +#define MEMP_NUM_NETCONN               32
> +#define MEMP_NUM_TCPIP_MSG_API          8
> +#define MEMP_NUM_TCPIP_MSG_INPKT        8
> +#define PBUF_POOL_SIZE                  8
> +
> +#define LWIP_ARP                        1
> +#define ARP_TABLE_SIZE                  1
> +#define ARP_QUEUEING                    0
> +
> +#define IP_FORWARD                      0
> +#define IP_OPTIONS_ALLOWED              1
> +#define IP_REASSEMBLY                   0
> +#define IP_FRAG                         0
> +#define IP_REASS_MAXAGE                 3
> +#define IP_REASS_MAX_PBUFS              4
> +#define IP_FRAG_USES_STATIC_BUF         0
> +
> +#define IP_DEFAULT_TTL                  255
> +
> +#define LWIP_ICMP                       0
> +
> +#if defined(CONFIG_PROT_RAW_LWIP)
> +#define LWIP_RAW                        1
> +#else
> +#define LWIP_RAW                       0
> +#endif
> +
> +#if defined(CONFIG_PROT_DHCP_LWIP)
> +#define LWIP_DHCP                       1
> +#define LWIP_DHCP_BOOTP_FILE           1
> +#else
> +#define LWIP_DHCP                      0
> +#endif
> +
> +#define LWIP_DHCP_DOES_ACD_CHECK       0
> +
> +#define LWIP_AUTOIP                     0
> +
> +#define LWIP_SNMP                       0
> +
> +#define LWIP_IGMP                       0
> +
> +#if defined(CONFIG_PROT_DNS_LWIP)
> +#define LWIP_DNS                        1
> +#define DNS_TABLE_SIZE                  1
> +#else
> +#define LWIP_DNS                        0
> +#endif
> +
> +#if defined(CONFIG_PROT_UDP_LWIP)
> +#define LWIP_UDP                        1
> +#else
> +#define LWIP_UDP                        0
> +#endif
> +
> +#if defined(CONFIG_PROT_TCP_LWIP)
> +#define LWIP_TCP                        1
> +#else
> +#define LWIP_TCP                        0
> +#endif
> +
> +#define LWIP_LISTEN_BACKLOG             0
> +
> +#define PBUF_LINK_HLEN                  14
> +#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN)
> +
> +#define LWIP_HAVE_LOOPIF                0
> +
> +#define LWIP_NETCONN                    0
> +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1
> +
> +#define LWIP_SOCKET                     0
> +#define SO_REUSE                        0
> +
> +#define LWIP_STATS                      0
> +
> +#define PPP_SUPPORT                     0
> +
> +#define LWIP_TCPIP_CORE_LOCKING                0
> +
> +#define LWIP_NETIF_LOOPBACK            0
> +
> +/* use malloc instead of pool */
> +#define MEMP_MEM_MALLOC                 1
> +#define MEMP_MEM_INIT                  1
> +#define MEM_LIBC_MALLOC                        1
> +
> +#endif /* LWIP_UBOOT_LWIPOPTS_H */
> --
> 2.40.1
>

Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 06/12] net-lwip: add dns command
  2024-06-06 15:46   ` Ilias Apalodimas
@ 2024-06-06 15:59     ` Jerome Forissier
  2024-06-06 16:02       ` Ilias Apalodimas
  0 siblings, 1 reply; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 15:59 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Mattijs Korpershoek, AKASHI Takahiro, Francis Laniel,
	Peter Robinson



On 6/6/24 17:46, Ilias Apalodimas wrote:
>> @@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
>>  obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
>>  obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
>>  obj-$(CONFIG_CMD_DHCP) += dhcp.o
>> +obj-$(CONFIG_CMD_DNS) += dns.o
>>  obj-$(CONFIG_CMD_PING) += ping.o
>>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>>
>> diff --git a/net-lwip/dns.c b/net-lwip/dns.c
>> new file mode 100644
>> index 00000000000..24a5149343a
>> --- /dev/null
>> +++ b/net-lwip/dns.c
>> @@ -0,0 +1,107 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <console.h>
>> +#include <lwip/dns.h>
>> +#include <lwip/timeouts.h>
>> +#include <net-lwip.h>
>> +#include <time.h>
>> +
>> +#define DNS_RESEND_MS 1000
>> +#define DNS_TIMEOUT_MS 10000
>> +
>> +static ulong start;
>> +static ip_addr_t host_ipaddr;
>> +static bool done;
>> +
>> +static void do_dns_tmr(void *arg)
>> +{
>> +       dns_tmr();
>> +}
>> +
>> +static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
>> +{
>> +       const char *var = arg;
>> +       char *ipstr = ip4addr_ntoa(ipaddr);
>> +
>> +       done = true;
>> +
>> +       if (!ipaddr) {
>> +               printf("DNS: host not found\n");
>> +               host_ipaddr.addr = 0;
>> +               return;
>> +       }
>> +
>> +       if (var)
>> +               env_set(var, ipstr);
> 
> Do we need this? Won't this set <dns_name> == ipaddr?

No, the syntax of the dns command is: 'dns hostname [env_var]' so one can
pretty much give any variable name to receive the IP address.

> If we do not need it repurpose the void *arg and get rid of the global 'done'

I could probably use a struct to get rid of the globals. Let me see what I can do.
 
>> +
>> +       printf("%s\n", ipstr);
>> +}
>> +
>> +int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> +       bool has_server = false;
>> +       ip_addr_t ipaddr;
>> +       ip_addr_t ns;
>> +       char *nsenv;
>> +       char *name;
>> +       char *var;
>> +       int ret;
> 
> [...]
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 06/12] net-lwip: add dns command
  2024-06-06 15:59     ` Jerome Forissier
@ 2024-06-06 16:02       ` Ilias Apalodimas
  2024-06-06 16:21         ` Jerome Forissier
  0 siblings, 1 reply; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 16:02 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Mattijs Korpershoek, AKASHI Takahiro, Francis Laniel,
	Peter Robinson

[...]

> >> +
> >> +       if (!ipaddr) {
> >> +               printf("DNS: host not found\n");
> >> +               host_ipaddr.addr = 0;
> >> +               return;
> >> +       }
> >> +
> >> +       if (var)
> >> +               env_set(var, ipstr);
> >
> > Do we need this? Won't this set <dns_name> == ipaddr?
>
> No, the syntax of the dns command is: 'dns hostname [env_var]' so one can
> pretty much give any variable name to receive the IP address.
>
> > If we do not need it repurpose the void *arg and get rid of the global 'done'
>
> I could probably use a struct to get rid of the globals. Let me see what I can do.

Yea just pass a struct with char* and a bool * and you should be fine

Thanks
/Ilias
>
> >> +
> >> +       printf("%s\n", ipstr);
> >> +}
> >> +
> >> +int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >> +{
> >> +       bool has_server = false;
> >> +       ip_addr_t ipaddr;
> >> +       ip_addr_t ns;
> >> +       char *nsenv;
> >> +       char *name;
> >> +       char *var;
> >> +       int ret;
> >
> > [...]
> >
> > Thanks
> > /Ilias

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 06/12] net-lwip: add dns command
  2024-06-06 16:02       ` Ilias Apalodimas
@ 2024-06-06 16:21         ` Jerome Forissier
  0 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-06 16:21 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Mattijs Korpershoek, AKASHI Takahiro, Francis Laniel,
	Peter Robinson



On 6/6/24 18:02, Ilias Apalodimas wrote:
> [...]
> 
>>>> +
>>>> +       if (!ipaddr) {
>>>> +               printf("DNS: host not found\n");
>>>> +               host_ipaddr.addr = 0;
>>>> +               return;
>>>> +       }
>>>> +
>>>> +       if (var)
>>>> +               env_set(var, ipstr);
>>>
>>> Do we need this? Won't this set <dns_name> == ipaddr?
>>
>> No, the syntax of the dns command is: 'dns hostname [env_var]' so one can
>> pretty much give any variable name to receive the IP address.
>>
>>> If we do not need it repurpose the void *arg and get rid of the global 'done'
>>
>> I could probably use a struct to get rid of the globals. Let me see what I can do.
> 
> Yea just pass a struct with char* and a bool * and you should be fine

Done in v4.

Thanks,
-- 
Jerome

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 05/12] net-lwip: add ping command
  2024-06-06 13:36 ` [PATCH v3 05/12] net-lwip: add ping command Jerome Forissier
@ 2024-06-06 16:53   ` Ilias Apalodimas
  2024-06-06 17:02     ` Ilias Apalodimas
  0 siblings, 1 reply; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 16:53 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Eddie James, Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson

[...]

> +static int ping_raw_init(void *recv_arg)
> +{
> +       ping_pcb = raw_new(IP_PROTO_ICMP);
> +       if (!ping_pcb)
> +               return -ENOMEM;
> +
> +       raw_recv(ping_pcb, ping_recv, recv_arg);
> +       raw_bind(ping_pcb, IP_ADDR_ANY);
> +
> +       return 0;
> +}
> +
> +static void ping_raw_stop(void)
> +{
> +       if (ping_pcb != NULL) {

nits, but we usually do if (!ping_pcb) for NULL pointers and variables
that have a value of 0.
Please change it in other files as well


> +               raw_remove(ping_pcb);
> +               ping_pcb = NULL;
> +       }
> +}
> +
> +static void ping_prepare_echo(struct icmp_echo_hdr *iecho)
> +{
> +       ICMPH_TYPE_SET(iecho, ICMP_ECHO);
> +       ICMPH_CODE_SET(iecho, 0);
> +       iecho->chksum = 0;
> +       iecho->id = PING_ID;
> +       iecho->seqno = lwip_htons(++ping_seq_num);
> +
> +       iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
> +}
> +
> +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
> +{
> +       struct pbuf *p;
> +       struct icmp_echo_hdr *iecho;
> +       size_t ping_size = sizeof(struct icmp_echo_hdr);
> +
> +       p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
> +       if (!p)
> +               return;
> +
> +       if ((p->len == p->tot_len) && (p->next == NULL)) {

&& !p->next

> +               iecho = (struct icmp_echo_hdr *)p->payload;
> +               ping_prepare_echo(iecho);
> +               raw_sendto(raw, p, addr);
> +       }
> +
> +       pbuf_free(p);
> +}
> +
> +static void ping_send(void *arg)
> +{
> +       struct raw_pcb *pcb = (struct raw_pcb *)arg;
> +
> +       ping_send_icmp(pcb, ping_target);
> +       sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
> +}
> +
> +static int ping_loop(const ip_addr_t* addr)
> +{
> +       bool alive;
> +       ulong start;
> +       int ret;
> +
> +       printf("Using %s device\n", eth_get_name());
> +
> +       ret = ping_raw_init(&alive);
> +       if (ret < 0)
> +               return ret;
> +       ping_target = addr;
> +       ping_seq_num = 0;
> +
> +       start = get_timer(0);
> +       ping_send(ping_pcb);
> +
> +       do {
> +               eth_rx();
> +               if (alive)
> +                       break;
> +               sys_check_timeouts();
> +               if (ctrlc()) {
> +                       printf("\nAbort\n");
> +                       break;
> +               }
> +       } while (get_timer(start) < PING_TIMEOUT_MS);

I am a bit confused about what happens here.
ping_send() will send the packet, but it will also schedule itself to
rerun after 1 ms and send another ping?

> +
> +       sys_untimeout(ping_send, ping_pcb);

So we need the sys_untimeout() because we queued 2 pings? Because
sys_timeout() is supposed to be an one shot.

Thanks
/Ilias
> +       ping_raw_stop();
> +       ping_target = NULL;
> +
> +       if (alive) {
> +               alive = false;
> +               return 0;
> +       }
> +       printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr));
> +       return -1;
> +}
> +
> +int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       ip_addr_t addr;
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +       if (!ipaddr_aton(argv[1], &addr))
> +               return CMD_RET_USAGE;
> +
> +       if (ping_loop(&addr) < 0)
> +               return CMD_RET_FAILURE;
> +
> +       return CMD_RET_SUCCESS;
> +}
> --
> 2.40.1
>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 00/12] Introduce the lwIP network stack
  2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
                   ` (11 preceding siblings ...)
  2024-06-06 13:36 ` [PATCH v3 12/12] CI: add qemu_arm64_lwip to the test matrix Jerome Forissier
@ 2024-06-06 16:56 ` Tom Rini
  2024-06-07  9:11   ` Jerome Forissier
  12 siblings, 1 reply; 27+ messages in thread
From: Tom Rini @ 2024-06-06 16:56 UTC (permalink / raw)
  To: Jerome Forissier; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov

[-- Attachment #1: Type: text/plain, Size: 2393 bytes --]

On Thu, Jun 06, 2024 at 03:35:55PM +0200, Jerome Forissier wrote:

> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> stack [2] [3] as an alternative to the current implementation in net/,
> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> reasons for doing so are:
> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> has some additional lwIP and Mbed TLS patches to do so. With that it
> becomes possible to fetch and launch a distro installer such as Debian
> etc. using a secure, authenticated connection directly from the U-Boot
> shell. Several use cases:
>   * Authentication: prevent MITM attack (third party replacing the
> binary with a different one)
>   * Confidentiality: prevent third parties from grabbing a copy of the
> image as it is being downloaded
>   * Allow connection to servers that do not support plain HTTP anymore
> (this is becoming more and more common on the Internet these days)
> - Possibly benefit from additional features implemented in lwIP
> - Less code to maintain in U-Boot

Alright, on Pi 3, I think we have more "output changed, test fails"
problems:
========================================== FAILURES ===========================================
_____________________________________ test_efi_fit_launch _____________________________________
test/py/tests/test_efi_fit.py:452: in test_efi_fit_launch
    launch_efi(False, False)
test/py/tests/test_efi_fit.py:394: in launch_efi
    net_set_up = net_dhcp()
test/py/tests/test_efi_fit.py:178: in net_dhcp
    assert 'DHCP client bound to address ' in output
E   AssertionError: assert 'DHCP client bound to address ' in 'Waiting for Ethernet connection... done.\r\neth0: smsc95xx_eth b8:27:eb:fc:64:a6 active'
------------------------------------ Captured stdout call -------------------------------------
U-Boot> usb start
U-Boot> U-Boot> setenv autoload no
U-Boot> U-Boot> dhcp
Waiting for Ethernet connection... done.
eth0: smsc95xx_eth b8:27:eb:fc:64:a6 active
U-Boot>
=================================== short test summary info ===================================

I'm going to skip that set of tests and see how far we get but I suspect
it'll keep failing on DHCP output being different.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 05/12] net-lwip: add ping command
  2024-06-06 16:53   ` Ilias Apalodimas
@ 2024-06-06 17:02     ` Ilias Apalodimas
  2024-06-06 17:45       ` Ilias Apalodimas
  0 siblings, 1 reply; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 17:02 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Eddie James, Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson

On Thu, 6 Jun 2024 at 19:53, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> [...]
>
> > +static int ping_raw_init(void *recv_arg)
> > +{
> > +       ping_pcb = raw_new(IP_PROTO_ICMP);
> > +       if (!ping_pcb)
> > +               return -ENOMEM;
> > +
> > +       raw_recv(ping_pcb, ping_recv, recv_arg);
> > +       raw_bind(ping_pcb, IP_ADDR_ANY);
> > +
> > +       return 0;
> > +}
> > +
> > +static void ping_raw_stop(void)
> > +{
> > +       if (ping_pcb != NULL) {
>
> nits, but we usually do if (!ping_pcb) for NULL pointers and variables
> that have a value of 0.
> Please change it in other files as well
>
>
> > +               raw_remove(ping_pcb);
> > +               ping_pcb = NULL;
> > +       }
> > +}
> > +
> > +static void ping_prepare_echo(struct icmp_echo_hdr *iecho)
> > +{
> > +       ICMPH_TYPE_SET(iecho, ICMP_ECHO);
> > +       ICMPH_CODE_SET(iecho, 0);
> > +       iecho->chksum = 0;
> > +       iecho->id = PING_ID;
> > +       iecho->seqno = lwip_htons(++ping_seq_num);
> > +
> > +       iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
> > +}
> > +
> > +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
> > +{
> > +       struct pbuf *p;
> > +       struct icmp_echo_hdr *iecho;
> > +       size_t ping_size = sizeof(struct icmp_echo_hdr);
> > +
> > +       p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
> > +       if (!p)
> > +               return;
> > +
> > +       if ((p->len == p->tot_len) && (p->next == NULL)) {
>
> && !p->next
>
> > +               iecho = (struct icmp_echo_hdr *)p->payload;
> > +               ping_prepare_echo(iecho);
> > +               raw_sendto(raw, p, addr);
> > +       }
> > +
> > +       pbuf_free(p);
> > +}
> > +
> > +static void ping_send(void *arg)
> > +{
> > +       struct raw_pcb *pcb = (struct raw_pcb *)arg;
> > +
> > +       ping_send_icmp(pcb, ping_target);
> > +       sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
> > +}
> > +
> > +static int ping_loop(const ip_addr_t* addr)
> > +{
> > +       bool alive;
> > +       ulong start;
> > +       int ret;
> > +
> > +       printf("Using %s device\n", eth_get_name());
> > +
> > +       ret = ping_raw_init(&alive);
> > +       if (ret < 0)
> > +               return ret;
> > +       ping_target = addr;
> > +       ping_seq_num = 0;
> > +
> > +       start = get_timer(0);
> > +       ping_send(ping_pcb);
> > +
> > +       do {
> > +               eth_rx();
> > +               if (alive)
> > +                       break;
> > +               sys_check_timeouts();
> > +               if (ctrlc()) {
> > +                       printf("\nAbort\n");
> > +                       break;
> > +               }
> > +       } while (get_timer(start) < PING_TIMEOUT_MS);
>
> I am a bit confused about what happens here.
> ping_send() will send the packet, but it will also schedule itself to
> rerun after 1 ms and send another ping?
>
> > +
> > +       sys_untimeout(ping_send, ping_pcb);
>
> So we need the sys_untimeout() because we queued 2 pings? Because
> sys_timeout() is supposed to be an one shot.

Ah nvm, I misread that. We always reschedule ping_send_icmp(), that's
why we have to delete it here


>
> Thanks
> /Ilias
> > +       ping_raw_stop();
> > +       ping_target = NULL;
> > +
> > +       if (alive) {
> > +               alive = false;
> > +               return 0;
> > +       }
> > +       printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr));
> > +       return -1;
> > +}
> > +
> > +int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > +{
> > +       ip_addr_t addr;
> > +
> > +       if (argc < 2)
> > +               return CMD_RET_USAGE;
> > +
> > +       if (!ipaddr_aton(argv[1], &addr))
> > +               return CMD_RET_USAGE;
> > +
> > +       if (ping_loop(&addr) < 0)
> > +               return CMD_RET_FAILURE;
> > +
> > +       return CMD_RET_SUCCESS;
> > +}
> > --
> > 2.40.1
> >

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 05/12] net-lwip: add ping command
  2024-06-06 17:02     ` Ilias Apalodimas
@ 2024-06-06 17:45       ` Ilias Apalodimas
  2024-06-07  7:55         ` Jerome Forissier
  0 siblings, 1 reply; 27+ messages in thread
From: Ilias Apalodimas @ 2024-06-06 17:45 UTC (permalink / raw)
  To: Jerome Forissier
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Eddie James, Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson

On Thu, 6 Jun 2024 at 20:02, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Thu, 6 Jun 2024 at 19:53, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > [...]
> >
> > > +static int ping_raw_init(void *recv_arg)
> > > +{
> > > +       ping_pcb = raw_new(IP_PROTO_ICMP);
> > > +       if (!ping_pcb)
> > > +               return -ENOMEM;
> > > +
> > > +       raw_recv(ping_pcb, ping_recv, recv_arg);
> > > +       raw_bind(ping_pcb, IP_ADDR_ANY);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void ping_raw_stop(void)
> > > +{
> > > +       if (ping_pcb != NULL) {
> >
> > nits, but we usually do if (!ping_pcb) for NULL pointers and variables
> > that have a value of 0.
> > Please change it in other files as well
> >
> >
> > > +               raw_remove(ping_pcb);
> > > +               ping_pcb = NULL;
> > > +       }
> > > +}
> > > +
> > > +static void ping_prepare_echo(struct icmp_echo_hdr *iecho)
> > > +{
> > > +       ICMPH_TYPE_SET(iecho, ICMP_ECHO);
> > > +       ICMPH_CODE_SET(iecho, 0);
> > > +       iecho->chksum = 0;
> > > +       iecho->id = PING_ID;
> > > +       iecho->seqno = lwip_htons(++ping_seq_num);
> > > +
> > > +       iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
> > > +}
> > > +
> > > +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
> > > +{
> > > +       struct pbuf *p;
> > > +       struct icmp_echo_hdr *iecho;
> > > +       size_t ping_size = sizeof(struct icmp_echo_hdr);
> > > +
> > > +       p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
> > > +       if (!p)
> > > +               return;
> > > +
> > > +       if ((p->len == p->tot_len) && (p->next == NULL)) {
> >
> > && !p->next
> >
> > > +               iecho = (struct icmp_echo_hdr *)p->payload;
> > > +               ping_prepare_echo(iecho);
> > > +               raw_sendto(raw, p, addr);
> > > +       }
> > > +
> > > +       pbuf_free(p);
> > > +}
> > > +
> > > +static void ping_send(void *arg)
> > > +{
> > > +       struct raw_pcb *pcb = (struct raw_pcb *)arg;
> > > +
> > > +       ping_send_icmp(pcb, ping_target);
> > > +       sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
> > > +}
> > > +
> > > +static int ping_loop(const ip_addr_t* addr)
> > > +{
> > > +       bool alive;
> > > +       ulong start;
> > > +       int ret;
> > > +
> > > +       printf("Using %s device\n", eth_get_name());
> > > +
> > > +       ret = ping_raw_init(&alive);
> > > +       if (ret < 0)
> > > +               return ret;
> > > +       ping_target = addr;
> > > +       ping_seq_num = 0;
> > > +
> > > +       start = get_timer(0);
> > > +       ping_send(ping_pcb);
> > > +
> > > +       do {
> > > +               eth_rx();
> > > +               if (alive)
> > > +                       break;
> > > +               sys_check_timeouts();
> > > +               if (ctrlc()) {
> > > +                       printf("\nAbort\n");
> > > +                       break;
> > > +               }
> > > +       } while (get_timer(start) < PING_TIMEOUT_MS);
> >
> > I am a bit confused about what happens here.
> > ping_send() will send the packet, but it will also schedule itself to
> > rerun after 1 ms and send another ping?
> >
> > > +
> > > +       sys_untimeout(ping_send, ping_pcb);
> >
> > So we need the sys_untimeout() because we queued 2 pings? Because
> > sys_timeout() is supposed to be an one shot.
>
> Ah nvm, I misread that. We always reschedule ping_send_icmp(), that's
> why we have to delete it here

Ok so looking at it a bit more. Why do we have to schedule contunuous pings?
We just have to send one packet and wait for the response no?

Thanks
/Ilias
>
>
> >
> > Thanks
> > /Ilias
> > > +       ping_raw_stop();
> > > +       ping_target = NULL;
> > > +
> > > +       if (alive) {
> > > +               alive = false;
> > > +               return 0;
> > > +       }
> > > +       printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr));
> > > +       return -1;
> > > +}
> > > +
> > > +int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > +{
> > > +       ip_addr_t addr;
> > > +
> > > +       if (argc < 2)
> > > +               return CMD_RET_USAGE;
> > > +
> > > +       if (!ipaddr_aton(argv[1], &addr))
> > > +               return CMD_RET_USAGE;
> > > +
> > > +       if (ping_loop(&addr) < 0)
> > > +               return CMD_RET_FAILURE;
> > > +
> > > +       return CMD_RET_SUCCESS;
> > > +}
> > > --
> > > 2.40.1
> > >

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 05/12] net-lwip: add ping command
  2024-06-06 17:45       ` Ilias Apalodimas
@ 2024-06-07  7:55         ` Jerome Forissier
  0 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-07  7:55 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
	Eddie James, Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson



On 6/6/24 19:45, Ilias Apalodimas wrote:
> On Thu, 6 Jun 2024 at 20:02, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
>>
>> On Thu, 6 Jun 2024 at 19:53, Ilias Apalodimas
>> <ilias.apalodimas@linaro.org> wrote:
>>>
>>> [...]
>>>
>>>> +static int ping_raw_init(void *recv_arg)
>>>> +{
>>>> +       ping_pcb = raw_new(IP_PROTO_ICMP);
>>>> +       if (!ping_pcb)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       raw_recv(ping_pcb, ping_recv, recv_arg);
>>>> +       raw_bind(ping_pcb, IP_ADDR_ANY);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static void ping_raw_stop(void)
>>>> +{
>>>> +       if (ping_pcb != NULL) {
>>>
>>> nits, but we usually do if (!ping_pcb) for NULL pointers and variables
>>> that have a value of 0.
>>> Please change it in other files as well
>>>
>>>
>>>> +               raw_remove(ping_pcb);
>>>> +               ping_pcb = NULL;
>>>> +       }
>>>> +}
>>>> +
>>>> +static void ping_prepare_echo(struct icmp_echo_hdr *iecho)
>>>> +{
>>>> +       ICMPH_TYPE_SET(iecho, ICMP_ECHO);
>>>> +       ICMPH_CODE_SET(iecho, 0);
>>>> +       iecho->chksum = 0;
>>>> +       iecho->id = PING_ID;
>>>> +       iecho->seqno = lwip_htons(++ping_seq_num);
>>>> +
>>>> +       iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
>>>> +}
>>>> +
>>>> +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr)
>>>> +{
>>>> +       struct pbuf *p;
>>>> +       struct icmp_echo_hdr *iecho;
>>>> +       size_t ping_size = sizeof(struct icmp_echo_hdr);
>>>> +
>>>> +       p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
>>>> +       if (!p)
>>>> +               return;
>>>> +
>>>> +       if ((p->len == p->tot_len) && (p->next == NULL)) {
>>>
>>> && !p->next
>>>
>>>> +               iecho = (struct icmp_echo_hdr *)p->payload;
>>>> +               ping_prepare_echo(iecho);
>>>> +               raw_sendto(raw, p, addr);
>>>> +       }
>>>> +
>>>> +       pbuf_free(p);
>>>> +}
>>>> +
>>>> +static void ping_send(void *arg)
>>>> +{
>>>> +       struct raw_pcb *pcb = (struct raw_pcb *)arg;
>>>> +
>>>> +       ping_send_icmp(pcb, ping_target);
>>>> +       sys_timeout(PING_DELAY_MS, ping_send, ping_pcb);
>>>> +}
>>>> +
>>>> +static int ping_loop(const ip_addr_t* addr)
>>>> +{
>>>> +       bool alive;
>>>> +       ulong start;
>>>> +       int ret;
>>>> +
>>>> +       printf("Using %s device\n", eth_get_name());
>>>> +
>>>> +       ret = ping_raw_init(&alive);
>>>> +       if (ret < 0)
>>>> +               return ret;
>>>> +       ping_target = addr;
>>>> +       ping_seq_num = 0;
>>>> +
>>>> +       start = get_timer(0);
>>>> +       ping_send(ping_pcb);
>>>> +
>>>> +       do {
>>>> +               eth_rx();
>>>> +               if (alive)
>>>> +                       break;
>>>> +               sys_check_timeouts();
>>>> +               if (ctrlc()) {
>>>> +                       printf("\nAbort\n");
>>>> +                       break;
>>>> +               }
>>>> +       } while (get_timer(start) < PING_TIMEOUT_MS);
>>>
>>> I am a bit confused about what happens here.
>>> ping_send() will send the packet, but it will also schedule itself to
>>> rerun after 1 ms and send another ping?
>>>
>>>> +
>>>> +       sys_untimeout(ping_send, ping_pcb);
>>>
>>> So we need the sys_untimeout() because we queued 2 pings? Because
>>> sys_timeout() is supposed to be an one shot.
>>
>> Ah nvm, I misread that. We always reschedule ping_send_icmp(), that's
>> why we have to delete it here
> 
> Ok so looking at it a bit more. Why do we have to schedule contunuous pings?
> We just have to send one packet and wait for the response no?

We could send just one packet as NET does, but if there's packet loss then
the ping command will report the host is unreachable. I think it is safer
to allow for a few retries for better reliability. The code for one packet
would be marginally simpler anyways. What I can do however is use a send
counter rather than a timeout.

Thanks,
-- 
Jerome


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 00/12] Introduce the lwIP network stack
  2024-06-06 16:56 ` [PATCH v3 00/12] Introduce the lwIP network stack Tom Rini
@ 2024-06-07  9:11   ` Jerome Forissier
  2024-06-07 13:52     ` Tom Rini
  0 siblings, 1 reply; 27+ messages in thread
From: Jerome Forissier @ 2024-06-07  9:11 UTC (permalink / raw)
  To: Tom Rini; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov



On 6/6/24 18:56, Tom Rini wrote:
> On Thu, Jun 06, 2024 at 03:35:55PM +0200, Jerome Forissier wrote:
> 
>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>> stack [2] [3] as an alternative to the current implementation in net/,
>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>> reasons for doing so are:
>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>> has some additional lwIP and Mbed TLS patches to do so. With that it
>> becomes possible to fetch and launch a distro installer such as Debian
>> etc. using a secure, authenticated connection directly from the U-Boot
>> shell. Several use cases:
>>   * Authentication: prevent MITM attack (third party replacing the
>> binary with a different one)
>>   * Confidentiality: prevent third parties from grabbing a copy of the
>> image as it is being downloaded
>>   * Allow connection to servers that do not support plain HTTP anymore
>> (this is becoming more and more common on the Internet these days)
>> - Possibly benefit from additional features implemented in lwIP
>> - Less code to maintain in U-Boot
> 
> Alright, on Pi 3, I think we have more "output changed, test fails"
> problems:
> ========================================== FAILURES ===========================================
> _____________________________________ test_efi_fit_launch _____________________________________
> test/py/tests/test_efi_fit.py:452: in test_efi_fit_launch
>     launch_efi(False, False)
> test/py/tests/test_efi_fit.py:394: in launch_efi
>     net_set_up = net_dhcp()
> test/py/tests/test_efi_fit.py:178: in net_dhcp
>     assert 'DHCP client bound to address ' in output
> E   AssertionError: assert 'DHCP client bound to address ' in 'Waiting for Ethernet connection... done.\r\neth0: smsc95xx_eth b8:27:eb:fc:64:a6 active'
> ------------------------------------ Captured stdout call -------------------------------------
> U-Boot> usb start
> U-Boot> U-Boot> setenv autoload no
> U-Boot> U-Boot> dhcp
> Waiting for Ethernet connection... done.
> eth0: smsc95xx_eth b8:27:eb:fc:64:a6 active
> U-Boot>
> =================================== short test summary info ===================================
> 
> I'm going to skip that set of tests and see how far we get but I suspect
> it'll keep failing on DHCP output being different.

As discussed offline with Ilias it might be a timeout issue, although 2000 ms
for DHCP_TIMEOUT_MS seems a large value to me, it might not be enough in your
environment. Can you please try to increase it? NET effectively has a timeout
of 28 seconds if we take the retries into account.

Thanks,
-- 
Jerome

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 07/12] net-lwip: add wget command
  2024-06-06 15:41   ` Ilias Apalodimas
@ 2024-06-07  9:23     ` Jerome Forissier
  0 siblings, 0 replies; 27+ messages in thread
From: Jerome Forissier @ 2024-06-07  9:23 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini, Heinrich Schuchardt,
	Simon Glass, Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
	Francis Laniel, Peter Robinson, Abdellatif El Khlifi,
	Masahisa Kojima, Ramon Fried, Ioana Ciornei, Peng Fan,
	Sean Edmond



On 6/6/24 17:41, Ilias Apalodimas wrote:
> Hi Jerome,
> 
> Can we split this in 2 patches instead?
> A preparatory one, with split the net-common etc and one that adds wget?

Sure, done in v4.

> Thanks
> /Ilias
> 
> On Thu, 6 Jun 2024 at 16:37, Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>> Add support for the wget command with NET_LWIP.
>>
>> About the small change in cmd/efidebug.c: when the wget command based
>> on the lwIP stack is used the wget command has a built-in URL
>> validation function since it needs to parse it anyways (in parse_url()).
>> Therefore wget_validate_uri() doesn't exist. So, guard the call in
>> efidebug.c with CONFIG_CMD_WGET.
>>
>> Based on code initially developed by Maxim U.
>>
>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
>> Cc: Maxim Uvarov <muvarov@gmail.com>
>> ---
>>  cmd/Kconfig        |   7 ++
>>  cmd/Makefile       |   5 +-
>>  cmd/efidebug.c     |   8 +-
>>  cmd/net-common.c   | 115 +++++++++++++++++++++++++++++
>>  cmd/net-lwip.c     |  12 +++
>>  cmd/net.c          | 115 -----------------------------
>>  include/net-lwip.h |  51 +++++++++++++
>>  net-lwip/Makefile  |   1 +
>>  net-lwip/wget.c    | 180 +++++++++++++++++++++++++++++++++++++++++++++
>>  9 files changed, 375 insertions(+), 119 deletions(-)
>>  create mode 100644 cmd/net-common.c
>>  create mode 100644 net-lwip/wget.c

Thanks,
-- 
Jerome

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 00/12] Introduce the lwIP network stack
  2024-06-07  9:11   ` Jerome Forissier
@ 2024-06-07 13:52     ` Tom Rini
  0 siblings, 0 replies; 27+ messages in thread
From: Tom Rini @ 2024-06-07 13:52 UTC (permalink / raw)
  To: Jerome Forissier; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov

[-- Attachment #1: Type: text/plain, Size: 3004 bytes --]

On Fri, Jun 07, 2024 at 11:11:49AM +0200, Jerome Forissier wrote:
> 
> 
> On 6/6/24 18:56, Tom Rini wrote:
> > On Thu, Jun 06, 2024 at 03:35:55PM +0200, Jerome Forissier wrote:
> > 
> >> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> >> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> >> stack [2] [3] as an alternative to the current implementation in net/,
> >> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> >> reasons for doing so are:
> >> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> >> has some additional lwIP and Mbed TLS patches to do so. With that it
> >> becomes possible to fetch and launch a distro installer such as Debian
> >> etc. using a secure, authenticated connection directly from the U-Boot
> >> shell. Several use cases:
> >>   * Authentication: prevent MITM attack (third party replacing the
> >> binary with a different one)
> >>   * Confidentiality: prevent third parties from grabbing a copy of the
> >> image as it is being downloaded
> >>   * Allow connection to servers that do not support plain HTTP anymore
> >> (this is becoming more and more common on the Internet these days)
> >> - Possibly benefit from additional features implemented in lwIP
> >> - Less code to maintain in U-Boot
> > 
> > Alright, on Pi 3, I think we have more "output changed, test fails"
> > problems:
> > ========================================== FAILURES ===========================================
> > _____________________________________ test_efi_fit_launch _____________________________________
> > test/py/tests/test_efi_fit.py:452: in test_efi_fit_launch
> >     launch_efi(False, False)
> > test/py/tests/test_efi_fit.py:394: in launch_efi
> >     net_set_up = net_dhcp()
> > test/py/tests/test_efi_fit.py:178: in net_dhcp
> >     assert 'DHCP client bound to address ' in output
> > E   AssertionError: assert 'DHCP client bound to address ' in 'Waiting for Ethernet connection... done.\r\neth0: smsc95xx_eth b8:27:eb:fc:64:a6 active'
> > ------------------------------------ Captured stdout call -------------------------------------
> > U-Boot> usb start
> > U-Boot> U-Boot> setenv autoload no
> > U-Boot> U-Boot> dhcp
> > Waiting for Ethernet connection... done.
> > eth0: smsc95xx_eth b8:27:eb:fc:64:a6 active
> > U-Boot>
> > =================================== short test summary info ===================================
> > 
> > I'm going to skip that set of tests and see how far we get but I suspect
> > it'll keep failing on DHCP output being different.
> 
> As discussed offline with Ilias it might be a timeout issue, although 2000 ms
> for DHCP_TIMEOUT_MS seems a large value to me, it might not be enough in your
> environment. Can you please try to increase it? NET effectively has a timeout
> of 28 seconds if we take the retries into account.

I increased it to 20000 ms and no change.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2024-06-07 13:52 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-06 13:35 [PATCH v3 00/12] Introduce the lwIP network stack Jerome Forissier
2024-06-06 13:35 ` [PATCH v3 01/12] net: introduce alternative implementation as net-lwip/ Jerome Forissier
2024-06-06 13:35 ` [PATCH v3 02/12] net-lwip: build lwIP Jerome Forissier
2024-06-06 15:50   ` Ilias Apalodimas
2024-06-06 13:35 ` [PATCH v3 03/12] net-lwip: add DHCP support and dhcp commmand Jerome Forissier
2024-06-06 13:35 ` [PATCH v3 04/12] net-lwip: add TFTP support and tftpboot command Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 05/12] net-lwip: add ping command Jerome Forissier
2024-06-06 16:53   ` Ilias Apalodimas
2024-06-06 17:02     ` Ilias Apalodimas
2024-06-06 17:45       ` Ilias Apalodimas
2024-06-07  7:55         ` Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 06/12] net-lwip: add dns command Jerome Forissier
2024-06-06 15:46   ` Ilias Apalodimas
2024-06-06 15:59     ` Jerome Forissier
2024-06-06 16:02       ` Ilias Apalodimas
2024-06-06 16:21         ` Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 07/12] net-lwip: add wget command Jerome Forissier
2024-06-06 15:41   ` Ilias Apalodimas
2024-06-07  9:23     ` Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 08/12] test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 09/12] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 10/12] configs: add qemu_arm64_lwip_defconfig Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 11/12] MAINTAINERS: net-lwip: add myself as a maintainer Jerome Forissier
2024-06-06 13:36 ` [PATCH v3 12/12] CI: add qemu_arm64_lwip to the test matrix Jerome Forissier
2024-06-06 16:56 ` [PATCH v3 00/12] Introduce the lwIP network stack Tom Rini
2024-06-07  9:11   ` Jerome Forissier
2024-06-07 13:52     ` Tom Rini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox