[PATCHv5 00/13] net/lwip: add lwip library for the network stack

changelog: v5: - fixed Iliases comments and split big patch on the small ones. You also need to issue command: git subtree add --prefix lib/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash Which will create merge commit of lwip library placing sources into lib/lwip/lwip-external directory. I do not send it a patch due to 1. merges are not friendly with git format-patch and 2. the source code of lwip is 78kb. v4: - tested with tests/py/ did some minor fixes (out of tree build, variables set after downloads). - accounted review comments for documentation. - implemented dns command - corrected wget command to not use serverip variable and use just url string. v3: - use lwip commands for ping,tftp,wget,dhcp if this patch applied. Drop CONFIG_LIB_LWIP_REPLACE_<COMMAND> option. - docs: use rst variant and drop references to RFC.
Maxim Uvarov (13): net/lwip: add doc/develop/net_lwip.rst net/lwip: integrate lwip library net/lwip: implement dns cmd net/lwip: implement dhcp cmd net/lwip: implement tftp cmd net/lwip: implement wget cmd net/lwip: implement ping cmd net/lwip: add lwip configuration configuration net/lwip: implement lwip port to u-boot net/lwip: update .gitignore with lwip net/lwip: connection between cmd and lwip apps net/lwip: replace original net commands with lwip net/lwip: drop old net/wget
.gitignore | 9 + boot/bootmeth_efi.c | 2 +- boot/bootmeth_pxe.c | 2 +- cmd/net.c | 86 +---- cmd/pxe.c | 2 +- doc/develop/index.rst | 1 + doc/develop/net_lwip.rst | 55 ++++ include/net.h | 8 +- include/net/lwip.h | 5 + include/net/wget.h | 22 -- lib/Kconfig | 2 + lib/Makefile | 1 + lib/lwip/Kconfig | 67 ++++ lib/lwip/Makefile | 74 +++++ lib/lwip/apps/dhcp/lwip-dhcp.c | 53 ++++ lib/lwip/apps/dns/lwip-dns.c | 46 +++ lib/lwip/apps/dns/lwip-dns.h | 3 + lib/lwip/apps/http/Makefile | 13 + lib/lwip/apps/http/lwip-wget.c | 130 ++++++++ lib/lwip/apps/ping/Makefile | 11 + lib/lwip/apps/ping/lwip_ping.c | 37 +++ lib/lwip/apps/ping/lwip_ping.h | 24 ++ lib/lwip/apps/ping/ping.h | 35 ++ lib/lwip/apps/tftp/Makefile | 16 + lib/lwip/apps/tftp/lwip-tftp.c | 124 ++++++++ lib/lwip/cmd-lwip.c | 308 ++++++++++++++++++ lib/lwip/lwipopts.h | 203 ++++++++++++ lib/lwip/port/if.c | 256 +++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ lib/lwip/ulwip.h | 9 + net/Kconfig | 1 + net/Makefile | 1 - net/net.c | 30 +- net/wget.c | 440 -------------------------- 37 files changed, 1649 insertions(+), 552 deletions(-) create mode 100644 doc/develop/net_lwip.rst create mode 100644 include/net/lwip.h delete mode 100644 include/net/wget.h create mode 100644 lib/lwip/Kconfig create mode 100644 lib/lwip/Makefile create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c create mode 100644 lib/lwip/apps/dns/lwip-dns.c create mode 100644 lib/lwip/apps/dns/lwip-dns.h create mode 100644 lib/lwip/apps/http/Makefile create mode 100644 lib/lwip/apps/http/lwip-wget.c create mode 100644 lib/lwip/apps/ping/Makefile create mode 100644 lib/lwip/apps/ping/lwip_ping.c create mode 100644 lib/lwip/apps/ping/lwip_ping.h create mode 100644 lib/lwip/apps/ping/ping.h create mode 100644 lib/lwip/apps/tftp/Makefile create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c create mode 100644 lib/lwip/cmd-lwip.c create mode 100644 lib/lwip/lwipopts.h create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c create mode 100644 lib/lwip/ulwip.h delete mode 100644 net/wget.c

Just add inital doc.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- doc/develop/index.rst | 1 + doc/develop/net_lwip.rst | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 doc/develop/net_lwip.rst
diff --git a/doc/develop/index.rst b/doc/develop/index.rst index ddbf8dad4a..f8ab6cb56e 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -46,6 +46,7 @@ Implementation smbios spl uefi/index + net_lwip vbe version
diff --git a/doc/develop/net_lwip.rst b/doc/develop/net_lwip.rst new file mode 100644 index 0000000000..784b8f960c --- /dev/null +++ b/doc/develop/net_lwip.rst @@ -0,0 +1,55 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +LWIP IP stack intergation for U-Boot +==================================== + +Intro +----- + +LWIP is a library implementating network protocols, which is commonly used +on embedded devices. + +https://savannah.nongnu.org/projects/lwip/ + +LwIP license: +LwIP is licensed under a BSD-style license: http://lwip.wikia.com/wiki/License. + +Main features include: + +* Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE + +* DHCP client, DNS client (incl. mDNS hostname resolver), AutoIP/APIPA (Zeroconf), SNMP agent (v1, v2c, v3, private MIB support & MIB compiler) + +* APIs: specialized APIs for enhanced performance, optional Berkeley-alike socket API + +* Extended features: IP forwarding over multiple network interfaces, TCP congestion control, RTT estimation and fast recovery/fast retransmit + +* Addon applications: HTTP(S) server, SNTP client, SMTP(S) client, ping, NetBIOS nameserver, mDNS responder, MQTT client, TFTP server + +U-Boot implementation details +----------------------------- + +1. In general we can build lwIP as .a library and link it against u-boot or compile it in +the U-Boot tree in the same way as other U-Boot files. There are few reasons why I selected +the second variant: LwIP is very customizable with defines for features, memory size, types of +allocation, some internal types and platform specific code. It turned out easier to enable/disable +debug which is also done with defines, and is needed periodically. + +2. lwIP has 2 APIs - raw mode and sequential (as lwIP names it, or socket API as we name it in Linux). +For now only raw API is supported. + +In raw IP mode a callback function for RX path is registered and will be called when packet +is passed to the IP stack and is ready for the application. + +Example is unmodified working ping example from lwip sources which registeres the callback: + +.. code-block:: c + + ping_pcb = raw_new(IP_PROTO_ICMP); + raw_recv(ping_pcb, ping_recv, NULL); <- ping_recv is app callback. + raw_bind(ping_pcb, IP_ADDR_ANY) + +3. Input and output + +RX packet path is injected to U-Boot eth_rx() polling loop and TX patch is in eth_send() accordingly. +So we do not touch any drivers code and just eat packets when they are ready.

Hi Maxim,
On Wed, 2 Aug 2023 at 08:09, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Just add inital doc.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
doc/develop/index.rst | 1 + doc/develop/net_lwip.rst | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 doc/develop/net_lwip.rst
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/doc/develop/index.rst b/doc/develop/index.rst index ddbf8dad4a..f8ab6cb56e 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -46,6 +46,7 @@ Implementation smbios spl uefi/index
- net_lwip vbe version
diff --git a/doc/develop/net_lwip.rst b/doc/develop/net_lwip.rst new file mode 100644 index 0000000000..784b8f960c --- /dev/null +++ b/doc/develop/net_lwip.rst @@ -0,0 +1,55 @@ +.. SPDX-License-Identifier: GPL-2.0+
+LWIP IP stack intergation for U-Boot
spelling
+====================================
+Intro +-----
+LWIP is a library implementating network protocols, which is commonly used
spelling
+on embedded devices.
+https://savannah.nongnu.org/projects/lwip/
+LwIP license: +LwIP is licensed under a BSD-style license: http://lwip.wikia.com/wiki/License.
+Main features include:
+* Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE
+* DHCP client, DNS client (incl. mDNS hostname resolver), AutoIP/APIPA (Zeroconf), SNMP agent (v1, v2c, v3, private MIB support & MIB compiler)
+* APIs: specialized APIs for enhanced performance, optional Berkeley-alike socket API
+* Extended features: IP forwarding over multiple network interfaces, TCP congestion control, RTT estimation and fast recovery/fast retransmit
Can we stick to 80cois for docs?
+* Addon applications: HTTP(S) server, SNTP client, SMTP(S) client, ping, NetBIOS nameserver, mDNS responder, MQTT client, TFTP server
+U-Boot implementation details +-----------------------------
+1. In general we can build lwIP as .a library and link it against u-boot or compile it in
as a
U-Boot (please check throughout)
+the U-Boot tree in the same way as other U-Boot files. There are few reasons why I selected +the second variant: LwIP is very customizable with defines for features, memory size, types of +allocation, some internal types and platform specific code. It turned out easier to enable/disable +debug which is also done with defines, and is needed periodically.
+2. lwIP has 2 APIs - raw mode and sequential (as lwIP names it, or socket API as we name it in Linux). +For now only raw API is supported.
+In raw IP mode a callback function for RX path is registered and will be called when packet +is passed to the IP stack and is ready for the application.
+Example is unmodified working ping example from lwip sources which registeres the callback:
spelling
+.. code-block:: c
ping_pcb = raw_new(IP_PROTO_ICMP);
raw_recv(ping_pcb, ping_recv, NULL); <- ping_recv is app callback.
raw_bind(ping_pcb, IP_ADDR_ANY)
+3. Input and output
+RX packet path is injected to U-Boot eth_rx() polling loop and TX patch is in eth_send() accordingly.
+So we do not touch any drivers code and just eat packets when they are ready.
2.30.2
Regards, Simon

--- lib/Kconfig | 2 ++ lib/Makefile | 3 +++ lib/lwip/Kconfig | 67 +++++++++++++++++++++++++++++++++++++++++++++++ lib/lwip/Makefile | 66 ++++++++++++++++++++++++++++++++++++++++++++++ net/Kconfig | 1 + net/net.c | 24 +++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 lib/lwip/Kconfig create mode 100644 lib/lwip/Makefile
diff --git a/lib/Kconfig b/lib/Kconfig index 3926652db6..79f7d5bc5d 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1112,3 +1112,5 @@ menu "FWU Multi Bank Updates" source lib/fwu_updates/Kconfig
endmenu + +source lib/lwip/Kconfig diff --git a/lib/Makefile b/lib/Makefile index 8d8ccc8bbc..598b5755dd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/ obj-$(CONFIG_LZMA) += lzma/ +obj-$(CONFIG_LWIP_LIB) += lwip/ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_FIT) += libfdt/ obj-$(CONFIG_OF_LIVE) += of_live.o @@ -92,6 +93,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
+obj-y += 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/Kconfig b/lib/lwip/Kconfig new file mode 100644 index 0000000000..5d2603701c --- /dev/null +++ b/lib/lwip/Kconfig @@ -0,0 +1,67 @@ +menu "LWIP" +config LWIP_LIB + bool "Support LWIP library" + help + This option will enable the lwIP library code with + all dependencies (cmd commands implemented with lwIP + library. This option is automatically enabled if CONFIG_NET=y. + lwIP library (https://git.savannah.nongnu.org/git/lwip.git) provides + network stack and application code for U-Boot cmd commands. + +menu "LWIP options" + +config LWIP_LIB_DEBUG + bool "enable debug" + default n + +config LWIP_LIB_NOASSERT + bool "disable asserts" + default y + help + Disabling asserts reduces binary size on 16k. + +config LWIP_LIB_TCP + bool "tcp" + default y + +config LWIP_LIB_UDP + bool "udp" + default y + +config LWIP_LIB_DNS + bool "dns" + default y + +config LWIP_LIB_DHCP + bool "dhcp" + default y + +config LWIP_LIB_LOOPBACK + bool "loopback" + help + Increases size on 1k. + +config LWIP_LIB_SOCKET + bool "socket API" + +config LWIP_LIB_NETCONN + bool "netconn API" + +config LWIP_LIB_MEM_SIZE + int "mem size" + default 1600 + range 1 4096 + help + MEM_SIZE: the size of the heap memory. If the application will send + a lot of data that needs to be copied, this should be set high. + +config LWIP_LIB_PBUF_LINK_HLEN + int "pbuf link hlen" + default 14 + range 4 1024 + help + PBUF_LINK_HLEN: the number of bytes that should be allocated for a + link level header. The default is 14, the standard value for Ethernet. +endmenu + +endmenu diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile new file mode 100644 index 0000000000..35f34d7afa --- /dev/null +++ b/lib/lwip/Makefile @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + +LWIPDIR=lwip-external/src + +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip + +obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \ + $(LWIPDIR)/core/def.o \ + $(LWIPDIR)/core/dns.o \ + $(LWIPDIR)/core/inet_chksum.o \ + $(LWIPDIR)/core/ip.o \ + $(LWIPDIR)/core/mem.o \ + $(LWIPDIR)/core/memp.o \ + $(LWIPDIR)/core/netif.o \ + $(LWIPDIR)/core/pbuf.o \ + $(LWIPDIR)/core/raw.o \ + $(LWIPDIR)/core/stats.o \ + $(LWIPDIR)/core/sys.o \ + $(LWIPDIR)/core/altcp.o \ + $(LWIPDIR)/core/altcp_alloc.o \ + $(LWIPDIR)/core/altcp_tcp.o \ + $(LWIPDIR)/core/tcp.o \ + $(LWIPDIR)/core/tcp_in.o \ + $(LWIPDIR)/core/tcp_out.o \ + $(LWIPDIR)/core/timeouts.o \ + $(LWIPDIR)/core/udp.o + +# IPv4 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \ + $(LWIPDIR)/core/ipv4/autoip.o \ + $(LWIPDIR)/core/ipv4/dhcp.o \ + $(LWIPDIR)/core/ipv4/etharp.o \ + $(LWIPDIR)/core/ipv4/icmp.o \ + $(LWIPDIR)/core/ipv4/igmp.o \ + $(LWIPDIR)/core/ipv4/ip4_frag.o \ + $(LWIPDIR)/core/ipv4/ip4.o \ + $(LWIPDIR)/core/ipv4/ip4_addr.o +# IPv6 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \ + $(LWIPDIR)/core/ipv6/ethip6.o \ + $(LWIPDIR)/core/ipv6/icmp6.o \ + $(LWIPDIR)/core/ipv6/inet6.o \ + $(LWIPDIR)/core/ipv6/ip6.o \ + $(LWIPDIR)/core/ipv6/ip6_addr.o \ + $(LWIPDIR)/core/ipv6/ip6_frag.o \ + $(LWIPDIR)/core/ipv6/mld6.o \ + $(LWIPDIR)/core/ipv6/nd6.o +# API +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \ + $(LWIPDIR)/api/api_msg.o \ + $(LWIPDIR)/api/err.o \ + $(LWIPDIR)/api/if_api.o \ + $(LWIPDIR)/api/netbuf.o \ + $(LWIPDIR)/api/netdb.o \ + $(LWIPDIR)/api/netifapi.o \ + $(LWIPDIR)/api/sockets.o \ + $(LWIPDIR)/api/tcpip.o + +# Netdevs +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o + +obj-$(CONFIG_NET) += port/if.o +obj-$(CONFIG_NET) += port/sys-arch.o diff --git a/net/Kconfig b/net/Kconfig index 4215889127..c3f4a7cae7 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,6 +5,7 @@ menuconfig NET bool "Networking support" default y + select LWIP_LIB
if NET
diff --git a/net/net.c b/net/net.c index 43abbac7c3..d98e51cb80 100644 --- a/net/net.c +++ b/net/net.c @@ -125,6 +125,7 @@ #endif #include "dhcpv6.h" #include "net_rand.h" +#include "../lib/lwip/ulwip.h"
/** BOOTP EXTENTIONS **/
@@ -452,7 +453,11 @@ int net_loop(enum proto_t protocol) #endif
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); +#if defined(CONFIG_LWIP_LIB) + if (!ulwip_enabled() || !ulwip_in_loop()) +#endif net_init(); + if (eth_is_on_demand_init()) { eth_halt(); eth_set_current(); @@ -649,6 +654,18 @@ restart: */ eth_rx();
+#if defined(CONFIG_LWIP_LIB) + if (ulwip_enabled()) { + net_set_state(NETLOOP_CONTINUE); + if (!ulwip_in_loop()) { + if (ulwip_app_get_err()) + net_set_state(NETLOOP_FAIL); + else + net_set_state(NETLOOP_SUCCESS); + goto done; + } + } +#endif /* * Abort if ctrl-c was pressed. */ @@ -1213,6 +1230,13 @@ void net_process_received_packet(uchar *in_packet, int len) if (len < ETHER_HDR_SIZE) return;
+#if defined(CONFIG_LWIP_LIB) + if (ulwip_enabled()) { + uboot_lwip_poll(); + return; + } +#endif + #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) if (push_packet) { (*push_packet)(in_packet, len);

Hi Maxim,
On Wed, 2 Aug 2023 at 08:09, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Please can you add a commit message in each case?
lib/Kconfig | 2 ++ lib/Makefile | 3 +++ lib/lwip/Kconfig | 67 +++++++++++++++++++++++++++++++++++++++++++++++ lib/lwip/Makefile | 66 ++++++++++++++++++++++++++++++++++++++++++++++ net/Kconfig | 1 + net/net.c | 24 +++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 lib/lwip/Kconfig create mode 100644 lib/lwip/Makefile
diff --git a/lib/Kconfig b/lib/Kconfig index 3926652db6..79f7d5bc5d 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1112,3 +1112,5 @@ menu "FWU Multi Bank Updates" source lib/fwu_updates/Kconfig
endmenu
+source lib/lwip/Kconfig diff --git a/lib/Makefile b/lib/Makefile index 8d8ccc8bbc..598b5755dd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/ obj-$(CONFIG_LZMA) += lzma/ +obj-$(CONFIG_LWIP_LIB) += lwip/
Do we need the _LIB ?
obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_FIT) += libfdt/ obj-$(CONFIG_OF_LIVE) += of_live.o @@ -92,6 +93,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
+obj-y += 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/Kconfig b/lib/lwip/Kconfig new file mode 100644 index 0000000000..5d2603701c --- /dev/null +++ b/lib/lwip/Kconfig @@ -0,0 +1,67 @@ +menu "LWIP" +config LWIP_LIB
bool "Support LWIP library"
help
This option will enable the lwIP library code with
s/will enable/enables/
or even
s/This option will enable/Enable /
all dependencies (cmd commands implemented with lwIP
library. This option is automatically enabled if CONFIG_NET=y.
lwIP library (https://git.savannah.nongnu.org/git/lwip.git) provides
network stack and application code for U-Boot cmd commands.
Please see doc/... for more information
+menu "LWIP options"
+config LWIP_LIB_DEBUG
bool "enable debug"
default n
+config LWIP_LIB_NOASSERT
bool "disable asserts"
default y
help
Disabling asserts reduces binary size on 16k.
by 16K ?
+config LWIP_LIB_TCP
bool "tcp"
default y
+config LWIP_LIB_UDP
bool "udp"
default y
need help
+config LWIP_LIB_DNS
bool "dns"
default y
+config LWIP_LIB_DHCP
bool "dhcp"
default y
+config LWIP_LIB_LOOPBACK
bool "loopback"
help
Increases size on 1k.
by 1K
+config LWIP_LIB_SOCKET
bool "socket API"
+config LWIP_LIB_NETCONN
bool "netconn API"
+config LWIP_LIB_MEM_SIZE
int "mem size"
default 1600
range 1 4096
help
MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high.
Can you add more detail? What does it mean to copy data??
+config LWIP_LIB_PBUF_LINK_HLEN
int "pbuf link hlen"
default 14
range 4 1024
help
PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. The default is 14, the standard value for Ethernet.
Why would you change it? Please add a little more detail
+endmenu
+endmenu diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile new file mode 100644 index 0000000000..35f34d7afa --- /dev/null +++ b/lib/lwip/Makefile @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
+LWIPDIR=lwip-external/src
+ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip
+obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \
$(LWIPDIR)/core/def.o \
$(LWIPDIR)/core/dns.o \
$(LWIPDIR)/core/inet_chksum.o \
$(LWIPDIR)/core/ip.o \
$(LWIPDIR)/core/mem.o \
$(LWIPDIR)/core/memp.o \
$(LWIPDIR)/core/netif.o \
$(LWIPDIR)/core/pbuf.o \
$(LWIPDIR)/core/raw.o \
$(LWIPDIR)/core/stats.o \
$(LWIPDIR)/core/sys.o \
$(LWIPDIR)/core/altcp.o \
$(LWIPDIR)/core/altcp_alloc.o \
$(LWIPDIR)/core/altcp_tcp.o \
$(LWIPDIR)/core/tcp.o \
$(LWIPDIR)/core/tcp_in.o \
$(LWIPDIR)/core/tcp_out.o \
$(LWIPDIR)/core/timeouts.o \
$(LWIPDIR)/core/udp.o
+# IPv4 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \
$(LWIPDIR)/core/ipv4/autoip.o \
$(LWIPDIR)/core/ipv4/dhcp.o \
$(LWIPDIR)/core/ipv4/etharp.o \
$(LWIPDIR)/core/ipv4/icmp.o \
$(LWIPDIR)/core/ipv4/igmp.o \
$(LWIPDIR)/core/ipv4/ip4_frag.o \
$(LWIPDIR)/core/ipv4/ip4.o \
$(LWIPDIR)/core/ipv4/ip4_addr.o
+# IPv6 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \
$(LWIPDIR)/core/ipv6/ethip6.o \
$(LWIPDIR)/core/ipv6/icmp6.o \
$(LWIPDIR)/core/ipv6/inet6.o \
$(LWIPDIR)/core/ipv6/ip6.o \
$(LWIPDIR)/core/ipv6/ip6_addr.o \
$(LWIPDIR)/core/ipv6/ip6_frag.o \
$(LWIPDIR)/core/ipv6/mld6.o \
$(LWIPDIR)/core/ipv6/nd6.o
+# API +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \
$(LWIPDIR)/api/api_msg.o \
$(LWIPDIR)/api/err.o \
$(LWIPDIR)/api/if_api.o \
$(LWIPDIR)/api/netbuf.o \
$(LWIPDIR)/api/netdb.o \
$(LWIPDIR)/api/netifapi.o \
$(LWIPDIR)/api/sockets.o \
$(LWIPDIR)/api/tcpip.o
+# Netdevs +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
+obj-$(CONFIG_NET) += port/if.o +obj-$(CONFIG_NET) += port/sys-arch.o diff --git a/net/Kconfig b/net/Kconfig index 4215889127..c3f4a7cae7 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,6 +5,7 @@ menuconfig NET bool "Networking support" default y
select LWIP_LIB
I agree this is best in the long term, but 'imply' might be safer until we are happy to delete the old code.
if NET
diff --git a/net/net.c b/net/net.c index 43abbac7c3..d98e51cb80 100644 --- a/net/net.c +++ b/net/net.c @@ -125,6 +125,7 @@ #endif #include "dhcpv6.h" #include "net_rand.h" +#include "../lib/lwip/ulwip.h"
/** BOOTP EXTENTIONS **/
@@ -452,7 +453,11 @@ int net_loop(enum proto_t protocol) #endif
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
+#if defined(CONFIG_LWIP_LIB)
if (!ulwip_enabled() || !ulwip_in_loop())
+#endif net_init();
if (eth_is_on_demand_init()) { eth_halt(); eth_set_current();
@@ -649,6 +654,18 @@ restart: */ eth_rx();
+#if defined(CONFIG_LWIP_LIB)
if ()
if (ulwip_enabled()) {
net_set_state(NETLOOP_CONTINUE);
if (!ulwip_in_loop()) {
if (ulwip_app_get_err())
net_set_state(NETLOOP_FAIL);
else
net_set_state(NETLOOP_SUCCESS);
goto done;
}
}
+#endif /* * Abort if ctrl-c was pressed. */ @@ -1213,6 +1230,13 @@ void net_process_received_packet(uchar *in_packet, int len) if (len < ETHER_HDR_SIZE) return;
+#if defined(CONFIG_LWIP_LIB)
same
if (ulwip_enabled()) {
uboot_lwip_poll();
do we need the uboot_ prefix?
return;
}
+#endif
#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) if (push_packet) { (*push_packet)(in_packet, len); -- 2.30.2
Regards, Simon

On Thu, 3 Aug 2023 at 03:31, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Wed, 2 Aug 2023 at 08:09, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Please can you add a commit message in each case?
lib/Kconfig | 2 ++ lib/Makefile | 3 +++ lib/lwip/Kconfig | 67 +++++++++++++++++++++++++++++++++++++++++++++++ lib/lwip/Makefile | 66 ++++++++++++++++++++++++++++++++++++++++++++++ net/Kconfig | 1 + net/net.c | 24 +++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 lib/lwip/Kconfig create mode 100644 lib/lwip/Makefile
diff --git a/lib/Kconfig b/lib/Kconfig index 3926652db6..79f7d5bc5d 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1112,3 +1112,5 @@ menu "FWU Multi Bank Updates" source lib/fwu_updates/Kconfig
endmenu
+source lib/lwip/Kconfig diff --git a/lib/Makefile b/lib/Makefile index 8d8ccc8bbc..598b5755dd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/ obj-$(CONFIG_LZMA) += lzma/ +obj-$(CONFIG_LWIP_LIB) += lwip/
Do we need the _LIB ?
Yea, _LIB can be removed.
obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_FIT) += libfdt/ obj-$(CONFIG_OF_LIVE) += of_live.o @@ -92,6 +93,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
+obj-y += 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/Kconfig b/lib/lwip/Kconfig new file mode 100644 index 0000000000..5d2603701c --- /dev/null +++ b/lib/lwip/Kconfig @@ -0,0 +1,67 @@ +menu "LWIP" +config LWIP_LIB
bool "Support LWIP library"
help
This option will enable the lwIP library code with
s/will enable/enables/
or even
s/This option will enable/Enable /
all dependencies (cmd commands implemented with lwIP
library. This option is automatically enabled if CONFIG_NET=y.
lwIP library (https://git.savannah.nongnu.org/git/lwip.git)
provides
network stack and application code for U-Boot cmd commands.
Please see doc/... for more information
+menu "LWIP options"
+config LWIP_LIB_DEBUG
bool "enable debug"
default n
+config LWIP_LIB_NOASSERT
bool "disable asserts"
default y
help
Disabling asserts reduces binary size on 16k.
by 16K ?
+config LWIP_LIB_TCP
bool "tcp"
default y
+config LWIP_LIB_UDP
bool "udp"
default y
need help
+config LWIP_LIB_DNS
bool "dns"
default y
+config LWIP_LIB_DHCP
bool "dhcp"
default y
+config LWIP_LIB_LOOPBACK
bool "loopback"
help
Increases size on 1k.
by 1K
+config LWIP_LIB_SOCKET
bool "socket API"
+config LWIP_LIB_NETCONN
bool "netconn API"
+config LWIP_LIB_MEM_SIZE
int "mem size"
default 1600
range 1 4096
help
MEM_SIZE: the size of the heap memory. If the application
will send
a lot of data that needs to be copied, this should be set
high.
Can you add more detail? What does it mean to copy data??
Actually currently this option is not used. There are 2 ways to define mem pool memory: 1. MEM_USE_POOLS (place on the stack). 2. use malloc (or use lwip variant of malloc with alignments.). Now I use malloc to simplify current integration. But I expect then later we will want to optimize for speed and need some dma friendly memory and will use MEM_USE_POOLS. To simplify settings I think it's reasonable to drop it for now from Kconfig.
+config LWIP_LIB_PBUF_LINK_HLEN
int "pbuf link hlen"
default 14
range 4 1024
help
PBUF_LINK_HLEN: the number of bytes that should be allocated
for a
link level header. The default is 14, the standard value for
Ethernet.
Why would you change it? Please add a little more detail
I think I will remove it from here. I tried to add more options to Kconfig to customize lwip and that was really helpful to measure size. This exact option can be 14 or 16 or 18, according to other code and examples. I think we don't need to change this value in our config. And then less configuration numbers we will have, then it's better for us.
/**
* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
* link level header. The default is 14, the standard value for
* Ethernet.
*/
#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__
#if (defined LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP) && !defined __DOXYGEN__
#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE)
#else /* LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP */
#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE)
#endif /* LWIP_HOOK_VLAN_SET || LWIP_VLAN_PCP */
#endif
+endmenu
+endmenu diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile new file mode 100644 index 0000000000..35f34d7afa --- /dev/null +++ b/lib/lwip/Makefile @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
+LWIPDIR=lwip-external/src
+ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include
-I$(srctree)/lib/lwip
+obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \
$(LWIPDIR)/core/def.o \
$(LWIPDIR)/core/dns.o \
$(LWIPDIR)/core/inet_chksum.o \
$(LWIPDIR)/core/ip.o \
$(LWIPDIR)/core/mem.o \
$(LWIPDIR)/core/memp.o \
$(LWIPDIR)/core/netif.o \
$(LWIPDIR)/core/pbuf.o \
$(LWIPDIR)/core/raw.o \
$(LWIPDIR)/core/stats.o \
$(LWIPDIR)/core/sys.o \
$(LWIPDIR)/core/altcp.o \
$(LWIPDIR)/core/altcp_alloc.o \
$(LWIPDIR)/core/altcp_tcp.o \
$(LWIPDIR)/core/tcp.o \
$(LWIPDIR)/core/tcp_in.o \
$(LWIPDIR)/core/tcp_out.o \
$(LWIPDIR)/core/timeouts.o \
$(LWIPDIR)/core/udp.o
+# IPv4 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \
$(LWIPDIR)/core/ipv4/autoip.o \
$(LWIPDIR)/core/ipv4/dhcp.o \
$(LWIPDIR)/core/ipv4/etharp.o \
$(LWIPDIR)/core/ipv4/icmp.o \
$(LWIPDIR)/core/ipv4/igmp.o \
$(LWIPDIR)/core/ipv4/ip4_frag.o \
$(LWIPDIR)/core/ipv4/ip4.o \
$(LWIPDIR)/core/ipv4/ip4_addr.o
+# IPv6 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \
$(LWIPDIR)/core/ipv6/ethip6.o \
$(LWIPDIR)/core/ipv6/icmp6.o \
$(LWIPDIR)/core/ipv6/inet6.o \
$(LWIPDIR)/core/ipv6/ip6.o \
$(LWIPDIR)/core/ipv6/ip6_addr.o \
$(LWIPDIR)/core/ipv6/ip6_frag.o \
$(LWIPDIR)/core/ipv6/mld6.o \
$(LWIPDIR)/core/ipv6/nd6.o
+# API +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \
$(LWIPDIR)/api/api_msg.o \
$(LWIPDIR)/api/err.o \
$(LWIPDIR)/api/if_api.o \
$(LWIPDIR)/api/netbuf.o \
$(LWIPDIR)/api/netdb.o \
$(LWIPDIR)/api/netifapi.o \
$(LWIPDIR)/api/sockets.o \
$(LWIPDIR)/api/tcpip.o
+# Netdevs +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
+obj-$(CONFIG_NET) += port/if.o +obj-$(CONFIG_NET) += port/sys-arch.o diff --git a/net/Kconfig b/net/Kconfig index 4215889127..c3f4a7cae7 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,6 +5,7 @@ menuconfig NET bool "Networking support" default y
select LWIP_LIB
I agree this is best in the long term, but 'imply' might be safer until we are happy to delete the old code.
I agree.
if NET
diff --git a/net/net.c b/net/net.c index 43abbac7c3..d98e51cb80 100644 --- a/net/net.c +++ b/net/net.c @@ -125,6 +125,7 @@ #endif #include "dhcpv6.h" #include "net_rand.h" +#include "../lib/lwip/ulwip.h"
/** BOOTP EXTENTIONS **/
@@ -452,7 +453,11 @@ int net_loop(enum proto_t protocol) #endif
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
+#if defined(CONFIG_LWIP_LIB)
if (!ulwip_enabled() || !ulwip_in_loop())
+#endif net_init();
if (eth_is_on_demand_init()) { eth_halt(); eth_set_current();
@@ -649,6 +654,18 @@ restart: */ eth_rx();
+#if defined(CONFIG_LWIP_LIB)
if ()
if (ulwip_enabled()) {
net_set_state(NETLOOP_CONTINUE);
if (!ulwip_in_loop()) {
if (ulwip_app_get_err())
net_set_state(NETLOOP_FAIL);
else
net_set_state(NETLOOP_SUCCESS);
goto done;
}
}
+#endif /* * Abort if ctrl-c was pressed. */ @@ -1213,6 +1230,13 @@ void net_process_received_packet(uchar
*in_packet, int len)
if (len < ETHER_HDR_SIZE) return;
+#if defined(CONFIG_LWIP_LIB)
same
if (ulwip_enabled()) {
uboot_lwip_poll();
do we need the uboot_ prefix?
lwip has lwip_ prefix. U-Boot doesn't have a prefix. I named the connecting code between U-Boot and lwip as ulwip_ for several functions. Here it's also has to be ulwip_
return;
}
+#endif
#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) if (push_packet) { (*push_packet)(in_packet, len); -- 2.30.2
Regards, Simon
Other comments are valuable, thanks, fixed.

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/Makefile | 2 ++ lib/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++ lib/lwip/apps/dns/lwip-dns.h | 3 +++ 3 files changed, 51 insertions(+) create mode 100644 lib/lwip/apps/dns/lwip-dns.c create mode 100644 lib/lwip/apps/dns/lwip-dns.h
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 35f34d7afa..2815662093 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o + +obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/lib/lwip/apps/dns/lwip-dns.c b/lib/lwip/apps/dns/lwip-dns.c new file mode 100644 index 0000000000..04fd53bfcb --- /dev/null +++ b/lib/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include <lwip/dns.h> +#include <lwip/ip_addr.h> + +#include "../../../lwip/ulwip.h" + +static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{ + char *varname = (char *)callback_arg; + + if (varname) + env_set(varname, ip4addr_ntoa(ipaddr)); + + printf("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr)); + ulwip_exit(0); +} + +int ulwip_dns(char *name, char *varname) +{ + int err; + ip_addr_t ipaddr; /* not used */ + ip_addr_t dns1; + ip_addr_t dns2; + + ipaddr_aton(env_get("dnsip"), &dns1); + ipaddr_aton(env_get("dnsip2"), &dns2); + + dns_init(); + dns_setserver(0, &dns1); + dns_setserver(1, &dns2); + + err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname); + if (err == ERR_OK) + dns_found_cb(name, &ipaddr, varname); + + return err; +} diff --git a/lib/lwip/apps/dns/lwip-dns.h b/lib/lwip/apps/dns/lwip-dns.h new file mode 100644 index 0000000000..c59f99e099 --- /dev/null +++ b/lib/lwip/apps/dns/lwip-dns.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +int ulwip_dns(char *name, char *varname);

Hi Maxim,
On Wed, 2 Aug 2023 at 08:09, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 2 ++ lib/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++ lib/lwip/apps/dns/lwip-dns.h | 3 +++ 3 files changed, 51 insertions(+) create mode 100644 lib/lwip/apps/dns/lwip-dns.c create mode 100644 lib/lwip/apps/dns/lwip-dns.h
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 35f34d7afa..2815662093 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/lib/lwip/apps/dns/lwip-dns.c b/lib/lwip/apps/dns/lwip-dns.c new file mode 100644 index 0000000000..04fd53bfcb --- /dev/null +++ b/lib/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include <lwip/dns.h> +#include <lwip/ip_addr.h>
+#include "../../../lwip/ulwip.h"
Can those headers go in include/ so we don't have this problem?
+static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{
char *varname = (char *)callback_arg;
if (varname)
env_set(varname, ip4addr_ntoa(ipaddr));
printf("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr));
ulwip_exit(0);
+}
+int ulwip_dns(char *name, char *varname) +{
int err;
ip_addr_t ipaddr; /* not used */
ip_addr_t dns1;
ip_addr_t dns2;
ipaddr_aton(env_get("dnsip"), &dns1);
ipaddr_aton(env_get("dnsip2"), &dns2);
dns_init();
dns_setserver(0, &dns1);
dns_setserver(1, &dns2);
err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname);
if (err == ERR_OK)
dns_found_cb(name, &ipaddr, varname);
return err;
+} diff --git a/lib/lwip/apps/dns/lwip-dns.h b/lib/lwip/apps/dns/lwip-dns.h new file mode 100644 index 0000000000..c59f99e099 --- /dev/null +++ b/lib/lwip/apps/dns/lwip-dns.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0+ */
+int ulwip_dns(char *name, char *varname);
Please comment all exported functions.
-- 2.30.2
Regards, Simon

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/Makefile | 1 + lib/lwip/apps/dhcp/lwip-dhcp.c | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 2815662093..a3521a9d18 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c b/lib/lwip/apps/dhcp/lwip-dhcp.c new file mode 100644 index 0000000000..9fda43db9f --- /dev/null +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include <lwip/dhcp.h> +#include <lwip/prot/dhcp.h> + +#include "../../../lwip/ulwip.h" + +static struct dhcp dhcp; +static bool dhcp_is_set; + +static int ulwip_dhcp_tmo(void) +{ + switch (dhcp.state) { + case DHCP_STATE_BOUND: + env_set("bootfile", dhcp.boot_file_name); + 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)); + printf("DHCP client bound to address %s\n", ip4addr_ntoa(&dhcp.offered_ip_addr)); + break; + default: + return -1; + } + + return 0; +} + +int ulwip_dhcp(void) +{ + int err; + struct netif *netif; + + ulwip_set_tmo(ulwip_dhcp_tmo); + netif = netif_get_by_index(1); + + if (!dhcp_is_set) { + dhcp_set_struct(netif, &dhcp); + dhcp_is_set = true; + } + err = dhcp_start(netif); + if (err) + printf("dhcp_start error %d\n", err); + + return err; +}

Hi Maxim,
The split looks a lot easier to review!
On Wed, Aug 02, 2023 at 08:06:49PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/dhcp/lwip-dhcp.c | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 2815662093..a3521a9d18 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c b/lib/lwip/apps/dhcp/lwip-dhcp.c new file mode 100644 index 0000000000..9fda43db9f --- /dev/null +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include <lwip/dhcp.h> +#include <lwip/prot/dhcp.h>
+#include "../../../lwip/ulwip.h"
I think we had similar comments on the previous version, you need to get rid of this '../../../'
+static struct dhcp dhcp; +static bool dhcp_is_set;
+static int ulwip_dhcp_tmo(void) +{
- switch (dhcp.state) {
- case DHCP_STATE_BOUND:
env_set("bootfile", dhcp.boot_file_name);
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));
printf("DHCP client bound to address %s\n", ip4addr_ntoa(&dhcp.offered_ip_addr));
break;
- default:
return -1;
- }
- return 0;
+}
+int ulwip_dhcp(void) +{
- int err;
- struct netif *netif;
- ulwip_set_tmo(ulwip_dhcp_tmo);
- netif = netif_get_by_index(1);
- if (!dhcp_is_set) {
Why do we need dhcp_is_set? Can't we check using netif_get_client_data()?
dhcp_set_struct(netif, &dhcp);
dhcp_is_set = true;
- }
- err = dhcp_start(netif);
- if (err)
printf("dhcp_start error %d\n", err);
- return err;
+}
2.30.2

On Thu, 3 Aug 2023 at 12:26, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Maxim,
The split looks a lot easier to review!
On Wed, Aug 02, 2023 at 08:06:49PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/dhcp/lwip-dhcp.c | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 2815662093..a3521a9d18 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c
b/lib/lwip/apps/dhcp/lwip-dhcp.c
new file mode 100644 index 0000000000..9fda43db9f --- /dev/null +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include <lwip/dhcp.h> +#include <lwip/prot/dhcp.h>
+#include "../../../lwip/ulwip.h"
I think we had similar comments on the previous version, you need to get rid of this '../../../'
yes, sorry. Replaced everywhere to <ulwip.h>. Header is already in the path.
+static struct dhcp dhcp; +static bool dhcp_is_set;
+static int ulwip_dhcp_tmo(void) +{
switch (dhcp.state) {
case DHCP_STATE_BOUND:
env_set("bootfile", dhcp.boot_file_name);
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));
printf("DHCP client bound to address %s\n",
ip4addr_ntoa(&dhcp.offered_ip_addr));
break;
default:
return -1;
}
return 0;
+}
+int ulwip_dhcp(void) +{
int err;
struct netif *netif;
ulwip_set_tmo(ulwip_dhcp_tmo);
netif = netif_get_by_index(1);
if (!dhcp_is_set) {
Why do we need dhcp_is_set? Can't we check using netif_get_client_data()?
yes, that works also. changed.
dhcp_set_struct(netif, &dhcp);
dhcp_is_set = true;
}
err = dhcp_start(netif);
if (err)
printf("dhcp_start error %d\n", err);
return err;
+}
2.30.2

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/Makefile | 1 + lib/lwip/apps/tftp/Makefile | 16 +++++ lib/lwip/apps/tftp/lwip-tftp.c | 124 +++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 lib/lwip/apps/tftp/Makefile create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index a3521a9d18..1893162c1a 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ diff --git a/lib/lwip/apps/tftp/Makefile b/lib/lwip/apps/tftp/Makefile new file mode 100644 index 0000000000..299c95e9c0 --- /dev/null +++ b/lib/lwip/apps/tftp/Makefile @@ -0,0 +1,16 @@ + +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip +ccflags-y += -I$(obj) + +$(obj)/tftp.o: $(obj)/tftp.c +.PHONY: $(obj)/tftp.c +$(obj)/tftp.c: + cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/tftp.c + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h + cp $(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/tftp_example.h + +obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += lwip-tftp.o + diff --git a/lib/lwip/apps/tftp/lwip-tftp.c b/lib/lwip/apps/tftp/lwip-tftp.c new file mode 100644 index 0000000000..511d82e600 --- /dev/null +++ b/lib/lwip/apps/tftp/lwip-tftp.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h" +#include <tftp_example.h> + +#include <string.h> + +#include "../../../lwip/ulwip.h" + +#if LWIP_UDP + +static ulong daddr; +static ulong size; + +static void *tftp_open(const char *fname, const char *mode, u8_t is_write) +{ + LWIP_UNUSED_ARG(mode); + return NULL; +} + +static void tftp_close(void *handle) +{ + printf("\ndone\n"); + printf("Bytes transferred = %ld (0x%lx hex)\n", size, size); + + env_set_ulong("filesize", size); + ulwip_exit(0); +} + +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); + /* printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); */ + daddr += q->len; + size += q->len; + printf("#"); + } + + return 0; +} + +/* For TFTP client only */ +static void tftp_error(void *handle, int err, const char *msg, int size) +{ + char message[100]; + + LWIP_UNUSED_ARG(handle); + + memset(message, 0, sizeof(message)); + MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size)); + + printf("TFTP error: %d (%s)", err, message); +} + +static const struct tftp_context tftp = { + tftp_open, + tftp_close, + tftp_read, + tftp_write, + tftp_error +}; + +int lwip_tftp(ulong addr, char *fname) +{ + void *f = (void *)0x1; /*fake handle*/ + err_t err; + ip_addr_t srv; + int ret; + char *server_ip; + + if (!fname || addr == 0) + return CMD_RET_FAILURE; + + size = 0; + daddr = addr; + server_ip = env_get("serverip"); + if (!server_ip) { + printf("error: serverip variable has to be set\n"); + return CMD_RET_FAILURE; + } + + ret = ipaddr_aton(server_ip, &srv); + LWIP_ASSERT("ipaddr_aton failed", ret == 1); + + printf("TFTP from server %s; our IP address is %s\n", + server_ip, env_get("ipaddr")); + printf("Filename '%s'.\n", fname); + printf("Load address: 0x%lx\n", daddr); + printf("Loading:"); + + err = tftp_init_client(&tftp); + if (!(err == ERR_OK || err == ERR_USE)) + printf("tftp_init_client err: %d\n", err); + + err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET); + /* might return different errors, like routing problems */ + if (err != ERR_OK) { + printf("tftp_get err=%d\n", err); + } + LWIP_ASSERT("tftp_get failed", err == ERR_OK); + + env_set_hex("fileaddr", addr); + return err; +} +#else +#error "UDP has to be supported" +#endif /* LWIP_UDP */

On Wed, Aug 02, 2023 at 08:06:50PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/tftp/Makefile | 16 +++++ lib/lwip/apps/tftp/lwip-tftp.c | 124 +++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 lib/lwip/apps/tftp/Makefile create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index a3521a9d18..1893162c1a 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ diff --git a/lib/lwip/apps/tftp/Makefile b/lib/lwip/apps/tftp/Makefile new file mode 100644 index 0000000000..299c95e9c0 --- /dev/null +++ b/lib/lwip/apps/tftp/Makefile @@ -0,0 +1,16 @@
+ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip +ccflags-y += -I$(obj)
+$(obj)/tftp.o: $(obj)/tftp.c +.PHONY: $(obj)/tftp.c +$(obj)/tftp.c:
- cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/tftp.c
- cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h
- cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h
- cp $(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/tftp_example.h
+obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += lwip-tftp.o
diff --git a/lib/lwip/apps/tftp/lwip-tftp.c b/lib/lwip/apps/tftp/lwip-tftp.c new file mode 100644 index 0000000000..511d82e600 --- /dev/null +++ b/lib/lwip/apps/tftp/lwip-tftp.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h" +#include <tftp_example.h>
+#include <string.h>
+#include "../../../lwip/ulwip.h"
+#if LWIP_UDP
+static ulong daddr; +static ulong size;
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write) +{
- LWIP_UNUSED_ARG(mode);
- return NULL;
+}
+static void tftp_close(void *handle) +{
- printf("\ndone\n");
- printf("Bytes transferred = %ld (0x%lx hex)\n", size, size);
Can you replace all the printf occurences with log_XXXX ?
- env_set_ulong("filesize", size);
- ulwip_exit(0);
+}
+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);
/* printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); */
Remove all those debug comments on the next version
daddr += q->len;
size += q->len;
printf("#");
- }
- return 0;
+}
+/* For TFTP client only */ +static void tftp_error(void *handle, int err, const char *msg, int size) +{
- char message[100];
- LWIP_UNUSED_ARG(handle);
- memset(message, 0, sizeof(message));
- MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size));
Why aren't we using the native memcpy?
- printf("TFTP error: %d (%s)", err, message);
+}
+static const struct tftp_context tftp = {
- tftp_open,
- tftp_close,
- tftp_read,
- tftp_write,
- tftp_error
+};
+int lwip_tftp(ulong addr, char *fname) +{
- void *f = (void *)0x1; /*fake handle*/
If it's fake can't it just be NULL? What does 'fake' mean? is that safe to be passed around the LWIP APIs?
- err_t err;
- ip_addr_t srv;
- int ret;
- char *server_ip;
- if (!fname || addr == 0)
return CMD_RET_FAILURE;
- size = 0;
- daddr = addr;
- server_ip = env_get("serverip");
- if (!server_ip) {
printf("error: serverip variable has to be set\n");
return CMD_RET_FAILURE;
- }
- ret = ipaddr_aton(server_ip, &srv);
- LWIP_ASSERT("ipaddr_aton failed", ret == 1);
- printf("TFTP from server %s; our IP address is %s\n",
server_ip, env_get("ipaddr"));
- printf("Filename '%s'.\n", fname);
- printf("Load address: 0x%lx\n", daddr);
- printf("Loading:");
- err = tftp_init_client(&tftp);
- if (!(err == ERR_OK || err == ERR_USE))
printf("tftp_init_client err: %d\n", err);
- err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET);
- /* might return different errors, like routing problems */
- if (err != ERR_OK) {
printf("tftp_get err=%d\n", err);
- }
- LWIP_ASSERT("tftp_get failed", err == ERR_OK);
- env_set_hex("fileaddr", addr);
- return err;
+} +#else +#error "UDP has to be supported"
+#endif /* LWIP_UDP */
2.30.2

On Thu, 3 Aug 2023 at 12:42, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
On Wed, Aug 02, 2023 at 08:06:50PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/tftp/Makefile | 16 +++++ lib/lwip/apps/tftp/lwip-tftp.c | 124 +++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 lib/lwip/apps/tftp/Makefile create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index a3521a9d18..1893162c1a 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ diff --git a/lib/lwip/apps/tftp/Makefile b/lib/lwip/apps/tftp/Makefile new file mode 100644 index 0000000000..299c95e9c0 --- /dev/null +++ b/lib/lwip/apps/tftp/Makefile @@ -0,0 +1,16 @@
+ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include
-I$(srctree)/lib/lwip
+ccflags-y += -I$(obj)
+$(obj)/tftp.o: $(obj)/tftp.c +.PHONY: $(obj)/tftp.c +$(obj)/tftp.c:
cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c
$(obj)/tftp.c
cp
$(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h
cp
$(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h
cp
$(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/tftp_example.h
+obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += lwip-tftp.o
diff --git a/lib/lwip/apps/tftp/lwip-tftp.c
b/lib/lwip/apps/tftp/lwip-tftp.c
new file mode 100644 index 0000000000..511d82e600 --- /dev/null +++ b/lib/lwip/apps/tftp/lwip-tftp.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h" +#include <tftp_example.h>
+#include <string.h>
+#include "../../../lwip/ulwip.h"
+#if LWIP_UDP
+static ulong daddr; +static ulong size;
+static void *tftp_open(const char *fname, const char *mode, u8_t
is_write)
+{
LWIP_UNUSED_ARG(mode);
return NULL;
+}
+static void tftp_close(void *handle) +{
printf("\ndone\n");
printf("Bytes transferred = %ld (0x%lx hex)\n", size, size);
Can you replace all the printf occurences with log_XXXX ?
env_set_ulong("filesize", size);
ulwip_exit(0);
+}
+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);
/* printf("downloaded chunk size %d, to addr 0x%lx\n",
q->len, daddr); */
Remove all those debug comments on the next version
daddr += q->len;
size += q->len;
printf("#");
}
return 0;
+}
+/* For TFTP client only */ +static void tftp_error(void *handle, int err, const char *msg, int size) +{
char message[100];
LWIP_UNUSED_ARG(handle);
memset(message, 0, sizeof(message));
MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size));
Why aren't we using the native memcpy?
printf("TFTP error: %d (%s)", err, message);
+}
+static const struct tftp_context tftp = {
tftp_open,
tftp_close,
tftp_read,
tftp_write,
tftp_error
+};
+int lwip_tftp(ulong addr, char *fname) +{
void *f = (void *)0x1; /*fake handle*/
If it's fake can't it just be NULL? What does 'fake' mean? is that safe to be passed around the LWIP APIs?
Here I reuse a tftp example from lwIP. f here is a file handle to write output. I do write to memory and do not use this value. But there is a check that his value can not be NULL. So something needs to be passed here to not do modifications to the example code.
err_t err;
ip_addr_t srv;
int ret;
char *server_ip;
if (!fname || addr == 0)
return CMD_RET_FAILURE;
size = 0;
daddr = addr;
server_ip = env_get("serverip");
if (!server_ip) {
printf("error: serverip variable has to be set\n");
return CMD_RET_FAILURE;
}
ret = ipaddr_aton(server_ip, &srv);
LWIP_ASSERT("ipaddr_aton failed", ret == 1);
printf("TFTP from server %s; our IP address is %s\n",
server_ip, env_get("ipaddr"));
printf("Filename '%s'.\n", fname);
printf("Load address: 0x%lx\n", daddr);
printf("Loading:");
err = tftp_init_client(&tftp);
if (!(err == ERR_OK || err == ERR_USE))
printf("tftp_init_client err: %d\n", err);
err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET);
/* might return different errors, like routing problems */
if (err != ERR_OK) {
printf("tftp_get err=%d\n", err);
}
LWIP_ASSERT("tftp_get failed", err == ERR_OK);
env_set_hex("fileaddr", addr);
return err;
+} +#else +#error "UDP has to be supported"
+#endif /* LWIP_UDP */
2.30.2

On 10.08.2023 13:28, Maxim Uvarov wrote:
On Thu, 3 Aug 2023 at 12:42, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
On Wed, Aug 02, 2023 at 08:06:50PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/tftp/Makefile | 16 +++++ lib/lwip/apps/tftp/lwip-tftp.c | 124 +++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 lib/lwip/apps/tftp/Makefile create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index a3521a9d18..1893162c1a 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ diff --git a/lib/lwip/apps/tftp/Makefile b/lib/lwip/apps/tftp/Makefile new file mode 100644 index 0000000000..299c95e9c0 --- /dev/null +++ b/lib/lwip/apps/tftp/Makefile @@ -0,0 +1,16 @@
+ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include
-I$(srctree)/lib/lwip
+ccflags-y += -I$(obj)
+$(obj)/tftp.o: $(obj)/tftp.c +.PHONY: $(obj)/tftp.c +$(obj)/tftp.c:
cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c
$(obj)/tftp.c
cp
$(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h
cp
$(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h
cp
$(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/tftp_example.h
+obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += lwip-tftp.o
diff --git a/lib/lwip/apps/tftp/lwip-tftp.c
b/lib/lwip/apps/tftp/lwip-tftp.c
new file mode 100644 index 0000000000..511d82e600 --- /dev/null +++ b/lib/lwip/apps/tftp/lwip-tftp.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h" +#include <tftp_example.h>
+#include <string.h>
+#include "../../../lwip/ulwip.h"
+#if LWIP_UDP
+static ulong daddr; +static ulong size;
+static void *tftp_open(const char *fname, const char *mode, u8_t
is_write)
+{
LWIP_UNUSED_ARG(mode);
return NULL;
+}
+static void tftp_close(void *handle) +{
printf("\ndone\n");
printf("Bytes transferred = %ld (0x%lx hex)\n", size, size);
Can you replace all the printf occurences with log_XXXX ?
env_set_ulong("filesize", size);
ulwip_exit(0);
+}
+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);
/* printf("downloaded chunk size %d, to addr 0x%lx\n",
q->len, daddr); */
Remove all those debug comments on the next version
daddr += q->len;
size += q->len;
printf("#");
}
return 0;
+}
+/* For TFTP client only */ +static void tftp_error(void *handle, int err, const char *msg, int size) +{
char message[100];
LWIP_UNUSED_ARG(handle);
memset(message, 0, sizeof(message));
MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size));
Why aren't we using the native memcpy?
printf("TFTP error: %d (%s)", err, message);
+}
+static const struct tftp_context tftp = {
tftp_open,
tftp_close,
tftp_read,
tftp_write,
tftp_error
+};
+int lwip_tftp(ulong addr, char *fname) +{
void *f = (void *)0x1; /*fake handle*/
If it's fake can't it just be NULL? What does 'fake' mean? is that safe to be passed around the LWIP APIs?
Here I reuse a tftp example from lwIP. f here is a file handle to write output. I do write to memory and do not use this value. But there is a check that his value can not be NULL. So something needs to be passed here to not do modifications to the example code.
Sorry I did not have the time to follow all your patches here throgouhly enough. However, if things like this come up, please also do not hesitate to come to us (lwip developers) with ideas to make our code more easily integratable into target applications (like U-Boot here).
As I said before (to Maxim in a private mail I think), I think it would be best to start targeting this integration based on lwIP's master branch, so modifications in the upstream lwIP sources would be possible to make this work neatly.
Regards, Simon
err_t err;
ip_addr_t srv;
int ret;
char *server_ip;
if (!fname || addr == 0)
return CMD_RET_FAILURE;
size = 0;
daddr = addr;
server_ip = env_get("serverip");
if (!server_ip) {
printf("error: serverip variable has to be set\n");
return CMD_RET_FAILURE;
}
ret = ipaddr_aton(server_ip, &srv);
LWIP_ASSERT("ipaddr_aton failed", ret == 1);
printf("TFTP from server %s; our IP address is %s\n",
server_ip, env_get("ipaddr"));
printf("Filename '%s'.\n", fname);
printf("Load address: 0x%lx\n", daddr);
printf("Loading:");
err = tftp_init_client(&tftp);
if (!(err == ERR_OK || err == ERR_USE))
printf("tftp_init_client err: %d\n", err);
err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET);
/* might return different errors, like routing problems */
if (err != ERR_OK) {
printf("tftp_get err=%d\n", err);
}
LWIP_ASSERT("tftp_get failed", err == ERR_OK);
env_set_hex("fileaddr", addr);
return err;
+} +#else +#error "UDP has to be supported"
+#endif /* LWIP_UDP */
2.30.2

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/Makefile | 1 + lib/lwip/apps/http/Makefile | 13 ++++ lib/lwip/apps/http/lwip-wget.c | 130 +++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 lib/lwip/apps/http/Makefile create mode 100644 lib/lwip/apps/http/lwip-wget.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 1893162c1a..ec6b728c8e 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ +obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/lib/lwip/apps/http/Makefile b/lib/lwip/apps/http/Makefile new file mode 100644 index 0000000000..7d22817e50 --- /dev/null +++ b/lib/lwip/apps/http/Makefile @@ -0,0 +1,13 @@ +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip +ccflags-y += -I$(obj) + +$(obj)/http_clinet.o: $(obj)/http_client.c +.PHONY: $(obj)/http_client.c +$(obj)/http_client.c: + cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c $(obj)/http_client.c + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/http_client.h + +obj-$(CONFIG_CMD_WGET) += http_client.o +obj-$(CONFIG_CMD_WGET) += lwip-wget.o + diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c new file mode 100644 index 0000000000..47a77250c5 --- /dev/null +++ b/lib/lwip/apps/http/lwip-wget.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include "http_client.h" +#include <ulwip.h> + +static ulong daddr; +static httpc_connection_t settings; + +#define SERVER_NAME_SIZE 200 + +static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct pbuf *q; + LWIP_UNUSED_ARG(err); + + if (!p) + return ERR_BUF; + + for (q = p; q != NULL; q = q->next) { + memcpy((void *)daddr, q->payload, q->len); + printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); + daddr += q->len; + } + altcp_recved(pcb, p->tot_len); + pbuf_free(p); + return ERR_OK; +} + +static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, + u32_t srv_res, err_t err) +{ + if (httpc_result == HTTPC_RESULT_OK) { + printf("\n%d bytes successfully downloaded.\n", rx_content_len); + env_set_ulong("filesize", rx_content_len); + ulwip_exit(0); + } else { + printf("\nhttp eroror: %d\n", httpc_result); + ulwip_exit(-1); + } +} + +/* http://hostname:port/url */ +static int parse_url(char *url, char *host, int *port) +{ + char *p, *pp; + + p = strstr(url, "http://"); + if (!p) { + printf("err: no http://!%5Cn"); + return -1; + } + + p += strlen("http://"); + + /* parse hostname */ + pp = strchr(p, ':'); + if (pp) { +#define PORT_STR_SIZE 5 + char portstr[PORT_STR_SIZE]; + + if (pp - p >= SERVER_NAME_SIZE) + return -2; + memcpy(host, p, pp - p); + host[pp - p + 1] = '\0'; + + p = pp + 1; + pp = strchr(p, '/'); + if (!pp) { + printf("wrong url\n"); + return -3; + } + + if (pp - p >= PORT_STR_SIZE) + return -4; + memcpy(portstr, p, pp - p); + portstr[pp - p] = '\0'; + *port = atoi(portstr); + } else { + pp = strchr(p, '/'); + if (!pp) { + printf("wrong url\n"); + return -5; + } + + if (pp - p >= SERVER_NAME_SIZE) + return -6; + memcpy(host, p, pp - p); + host[pp - p + 1] = '\0'; + *port = 80; /* default */ + } + + return 0; +} + +int lwip_wget(ulong addr, char *url) +{ + err_t err; + int port; + char server_name[SERVER_NAME_SIZE]; + httpc_state_t *connection; + + daddr = addr; + + err = parse_url(url, server_name, &port); + if (err) { + printf("error parse_url\n"); + return -1; + } + + printf("downloading %s to addr 0x%lx\n", url, addr); + memset(&settings, 0, sizeof(settings)); + settings.result_fn = httpc_result; + err = httpc_get_file_dns(server_name, port, url, &settings, + httpc_recv, NULL, &connection); + if (err != ERR_OK) { + printf("httpc_init_connection failed\n"); + return err; + } + + env_set_hex("fileaddr", addr); + return 0; +}

On Wed, Aug 02, 2023 at 08:06:51PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/http/Makefile | 13 ++++ lib/lwip/apps/http/lwip-wget.c | 130 +++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 lib/lwip/apps/http/Makefile create mode 100644 lib/lwip/apps/http/lwip-wget.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 1893162c1a..ec6b728c8e 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ +obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/lib/lwip/apps/http/Makefile b/lib/lwip/apps/http/Makefile new file mode 100644 index 0000000000..7d22817e50 --- /dev/null +++ b/lib/lwip/apps/http/Makefile @@ -0,0 +1,13 @@ +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip +ccflags-y += -I$(obj)
+$(obj)/http_clinet.o: $(obj)/http_client.c +.PHONY: $(obj)/http_client.c +$(obj)/http_client.c:
- cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c $(obj)/http_client.c
- cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/http_client.h
+obj-$(CONFIG_CMD_WGET) += http_client.o +obj-$(CONFIG_CMD_WGET) += lwip-wget.o
diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c new file mode 100644 index 0000000000..47a77250c5 --- /dev/null +++ b/lib/lwip/apps/http/lwip-wget.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include "http_client.h" +#include <ulwip.h>
+static ulong daddr; +static httpc_connection_t settings;
+#define SERVER_NAME_SIZE 200
+static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) +{
- struct pbuf *q;
- LWIP_UNUSED_ARG(err);
I think it's better to use standard C instead of LWIP defined macros for things like that
- if (!p)
return ERR_BUF;
- for (q = p; q != NULL; q = q->next) {
memcpy((void *)daddr, q->payload, q->len);
printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr);
daddr += q->len;
- }
- altcp_recved(pcb, p->tot_len);
- pbuf_free(p);
- return ERR_OK;
+}
+static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len,
u32_t srv_res, err_t err)
+{
- if (httpc_result == HTTPC_RESULT_OK) {
printf("\n%d bytes successfully downloaded.\n", rx_content_len);
Switch those to a log_XXXX that makes sense
env_set_ulong("filesize", rx_content_len);
ulwip_exit(0);
- } else {
printf("\nhttp eroror: %d\n", httpc_result);
ulwip_exit(-1);
- }
+}
+/* http://hostname:port/url */ +static int parse_url(char *url, char *host, int *port) +{
- char *p, *pp;
- p = strstr(url, "http://");
- if (!p) {
printf("err: no http://!\n");
return -1;
- }
- p += strlen("http://");
- /* parse hostname */
- pp = strchr(p, ':');
- if (pp) {
+#define PORT_STR_SIZE 5
https://lore.kernel.org/u-boot/ZMJqIxmXJD4S72Ig@hades/ Do we currently support a configurable port for wget?
char portstr[PORT_STR_SIZE];
if (pp - p >= SERVER_NAME_SIZE)
return -2;
memcpy(host, p, pp - p);
host[pp - p + 1] = '\0';
p = pp + 1;
pp = strchr(p, '/');
if (!pp) {
printf("wrong url\n");
return -3;
}
if (pp - p >= PORT_STR_SIZE)
return -4;
memcpy(portstr, p, pp - p);
portstr[pp - p] = '\0';
*port = atoi(portstr);
- } else {
pp = strchr(p, '/');
if (!pp) {
printf("wrong url\n");
return -5;
}
if (pp - p >= SERVER_NAME_SIZE)
return -6;
memcpy(host, p, pp - p);
host[pp - p + 1] = '\0';
*port = 80; /* default */
- }
- return 0;
+}
+int lwip_wget(ulong addr, char *url) +{
- err_t err;
- int port;
- char server_name[SERVER_NAME_SIZE];
- httpc_state_t *connection;
- daddr = addr;
- err = parse_url(url, server_name, &port);
- if (err) {
printf("error parse_url\n");
return -1;
- }
- printf("downloading %s to addr 0x%lx\n", url, addr);
- memset(&settings, 0, sizeof(settings));
- settings.result_fn = httpc_result;
- err = httpc_get_file_dns(server_name, port, url, &settings,
httpc_recv, NULL, &connection);
- if (err != ERR_OK) {
printf("httpc_init_connection failed\n");
return err;
- }
- env_set_hex("fileaddr", addr);
- return 0;
+}
2.30.2

On Thu, 3 Aug 2023 at 12:48, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
On Wed, Aug 02, 2023 at 08:06:51PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/http/Makefile | 13 ++++ lib/lwip/apps/http/lwip-wget.c | 130 +++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 lib/lwip/apps/http/Makefile create mode 100644 lib/lwip/apps/http/lwip-wget.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 1893162c1a..ec6b728c8e 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ +obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/lib/lwip/apps/http/Makefile b/lib/lwip/apps/http/Makefile new file mode 100644 index 0000000000..7d22817e50 --- /dev/null +++ b/lib/lwip/apps/http/Makefile @@ -0,0 +1,13 @@ +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include
-I$(srctree)/lib/lwip
+ccflags-y += -I$(obj)
+$(obj)/http_clinet.o: $(obj)/http_client.c +.PHONY: $(obj)/http_client.c +$(obj)/http_client.c:
cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c
$(obj)/http_client.c
cp
$(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/http_client.h
+obj-$(CONFIG_CMD_WGET) += http_client.o +obj-$(CONFIG_CMD_WGET) += lwip-wget.o
diff --git a/lib/lwip/apps/http/lwip-wget.c
b/lib/lwip/apps/http/lwip-wget.c
new file mode 100644 index 0000000000..47a77250c5 --- /dev/null +++ b/lib/lwip/apps/http/lwip-wget.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +#include <console.h>
+#include "http_client.h" +#include <ulwip.h>
+static ulong daddr; +static httpc_connection_t settings;
+#define SERVER_NAME_SIZE 200
+static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf
*p, err_t err)
+{
struct pbuf *q;
LWIP_UNUSED_ARG(err);
I think it's better to use standard C instead of LWIP defined macros for things like that
agree no need to use lwip macro here. But what is the common practice for U-Boot for unused function args? I think compilation does not even warn about it. So naming like unused_err has to be fine here.
if (!p)
return ERR_BUF;
for (q = p; q != NULL; q = q->next) {
memcpy((void *)daddr, q->payload, q->len);
printf("downloaded chunk size %d, to addr 0x%lx\n",
q->len, daddr);
daddr += q->len;
}
altcp_recved(pcb, p->tot_len);
pbuf_free(p);
return ERR_OK;
+}
+static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t
rx_content_len,
u32_t srv_res, err_t err)
+{
if (httpc_result == HTTPC_RESULT_OK) {
printf("\n%d bytes successfully downloaded.\n",
rx_content_len);
Switch those to a log_XXXX that makes sense
yep.
env_set_ulong("filesize", rx_content_len);
ulwip_exit(0);
} else {
printf("\nhttp eroror: %d\n", httpc_result);
ulwip_exit(-1);
}
+}
+/* http://hostname:port/url */ +static int parse_url(char *url, char *host, int *port) +{
char *p, *pp;
p = strstr(url, "http://");
if (!p) {
printf("err: no http://!\n");
return -1;
}
p += strlen("http://");
/* parse hostname */
pp = strchr(p, ':');
if (pp) {
+#define PORT_STR_SIZE 5
https://lore.kernel.org/u-boot/ZMJqIxmXJD4S72Ig@hades/ Do we currently support a configurable port for wget?
I might have to reply to the previous email, then update the patch. Old wget has port inside header file and it's binded to 80. Old wget does not parse url script and uses serverip variable for the server. Old wget does not use DNS. Because of lwip variant can use a url (including DNS and IPv6) there is no need to use the server ip variable and bind to a specific port. So here we parse port, host and url and pass it to lwip http_client.c example.
char portstr[PORT_STR_SIZE];
if (pp - p >= SERVER_NAME_SIZE)
return -2;
memcpy(host, p, pp - p);
host[pp - p + 1] = '\0';
p = pp + 1;
pp = strchr(p, '/');
if (!pp) {
printf("wrong url\n");
return -3;
}
if (pp - p >= PORT_STR_SIZE)
return -4;
memcpy(portstr, p, pp - p);
portstr[pp - p] = '\0';
*port = atoi(portstr);
} else {
pp = strchr(p, '/');
if (!pp) {
printf("wrong url\n");
return -5;
}
if (pp - p >= SERVER_NAME_SIZE)
return -6;
memcpy(host, p, pp - p);
host[pp - p + 1] = '\0';
*port = 80; /* default */
}
return 0;
+}
+int lwip_wget(ulong addr, char *url) +{
err_t err;
int port;
char server_name[SERVER_NAME_SIZE];
httpc_state_t *connection;
daddr = addr;
err = parse_url(url, server_name, &port);
if (err) {
printf("error parse_url\n");
return -1;
}
printf("downloading %s to addr 0x%lx\n", url, addr);
memset(&settings, 0, sizeof(settings));
settings.result_fn = httpc_result;
err = httpc_get_file_dns(server_name, port, url, &settings,
httpc_recv, NULL, &connection);
if (err != ERR_OK) {
printf("httpc_init_connection failed\n");
return err;
}
env_set_hex("fileaddr", addr);
return 0;
+}
2.30.2

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/Makefile | 1 + lib/lwip/apps/ping/Makefile | 11 ++++++++++ lib/lwip/apps/ping/lwip_ping.c | 37 ++++++++++++++++++++++++++++++++++ lib/lwip/apps/ping/lwip_ping.h | 24 ++++++++++++++++++++++ lib/lwip/apps/ping/ping.h | 35 ++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 lib/lwip/apps/ping/Makefile create mode 100644 lib/lwip/apps/ping/lwip_ping.c create mode 100644 lib/lwip/apps/ping/lwip_ping.h create mode 100644 lib/lwip/apps/ping/ping.h
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index ec6b728c8e..87ed99a230 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,5 +67,6 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_PING) += apps/ping/ obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/lib/lwip/apps/ping/Makefile b/lib/lwip/apps/ping/Makefile new file mode 100644 index 0000000000..0d0a811336 --- /dev/null +++ b/lib/lwip/apps/ping/Makefile @@ -0,0 +1,11 @@ +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip +ccflags-y += -I$(obj) + +.PHONY: $(obj)/ping.c +$(obj)/ping.o: $(obj)/ping.c +$(obj)/ping.c: + cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c $(obj)/ping.c + +obj-$(CONFIG_CMD_PING) += ping.o +obj-$(CONFIG_CMD_PING) += lwip_ping.o diff --git a/lib/lwip/apps/ping/lwip_ping.c b/lib/lwip/apps/ping/lwip_ping.c new file mode 100644 index 0000000000..40658ab6fd --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "ping.h" + +#include <ulwip.h> + +static ip_addr_t ip_target; + +static int ulwip_ping_tmo(void) +{ + + printf("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target)); + return 0; +} + +int lwip_ping_init(char *ping_addr) +{ + int err; + + err = ipaddr_aton(ping_addr, &ip_target); + if (err == 0) { + printf("wrong ping addr string "%s" \n", ping_addr); + return -1; + } + + ulwip_set_tmo(ulwip_ping_tmo); + + ping_init(&ip_target); + + return 0; +} diff --git a/lib/lwip/apps/ping/lwip_ping.h b/lib/lwip/apps/ping/lwip_ping.h new file mode 100644 index 0000000000..7f08095427 --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#ifndef LWIP_PING_H +#define LWIP_PING_H + +#include <lwip/ip_addr.h> + +/** + * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used + */ +#ifndef PING_USE_SOCKETS +#define PING_USE_SOCKETS 0 +#endif + +int lwip_ping_init(char *ping_addr); + +void ping_raw_init(void); +void ping_send_now(void); + +#endif /* LWIP_PING_H */ diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h new file mode 100644 index 0000000000..0dd4bd78c7 --- /dev/null +++ b/lib/lwip/apps/ping/ping.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include "../../../lwip/ulwip.h" + +#include "lwip/prot/ip4.h" + +#define ip4_print_parts(a, b, c, d) \ + printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d); + +#define ip4_print(ipaddr) \ + ip4_print_parts(\ + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) + + +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ +#define PING_RESULT(cond) { \ + if (cond == 1) { \ + printf("host "); \ + ip4_print(addr); \ + printf(" is alive\n"); \ + printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \ + ulwip_exit(0); \ + } else { \ + printf("ping failed; host "); \ + ip4_print(addr); \ + printf(" is not alive\n"); \ + ulwip_exit(-1); \ + } \ + } while (0); + +#include "lwip/ip_addr.h" +void ping_init(const ip_addr_t *ping_addr);

On Wed, Aug 02, 2023 at 08:06:52PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/ping/Makefile | 11 ++++++++++ lib/lwip/apps/ping/lwip_ping.c | 37 ++++++++++++++++++++++++++++++++++ lib/lwip/apps/ping/lwip_ping.h | 24 ++++++++++++++++++++++ lib/lwip/apps/ping/ping.h | 35 ++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 lib/lwip/apps/ping/Makefile create mode 100644 lib/lwip/apps/ping/lwip_ping.c create mode 100644 lib/lwip/apps/ping/lwip_ping.h create mode 100644 lib/lwip/apps/ping/ping.h
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index ec6b728c8e..87ed99a230 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,5 +67,6 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_PING) += apps/ping/ obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/lib/lwip/apps/ping/Makefile b/lib/lwip/apps/ping/Makefile new file mode 100644 index 0000000000..0d0a811336 --- /dev/null +++ b/lib/lwip/apps/ping/Makefile @@ -0,0 +1,11 @@ +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip +ccflags-y += -I$(obj)
+.PHONY: $(obj)/ping.c +$(obj)/ping.o: $(obj)/ping.c +$(obj)/ping.c:
- cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c $(obj)/ping.c
+obj-$(CONFIG_CMD_PING) += ping.o +obj-$(CONFIG_CMD_PING) += lwip_ping.o diff --git a/lib/lwip/apps/ping/lwip_ping.c b/lib/lwip/apps/ping/lwip_ping.c new file mode 100644 index 0000000000..40658ab6fd --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "ping.h"
+#include <ulwip.h>
+static ip_addr_t ip_target;
+static int ulwip_ping_tmo(void) +{
- printf("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target));
- return 0;
Shouldnt this return != 0? Also why do we need this? Looking at ping_raw_init() it ets timeout and print fail messages
+}
+int lwip_ping_init(char *ping_addr) +{
- int err;
- err = ipaddr_aton(ping_addr, &ip_target);
- if (err == 0) {
printf("wrong ping addr string \"%s\" \n", ping_addr);
return -1;
- }
- ulwip_set_tmo(ulwip_ping_tmo);
- ping_init(&ip_target);
- return 0;
+} diff --git a/lib/lwip/apps/ping/lwip_ping.h b/lib/lwip/apps/ping/lwip_ping.h new file mode 100644 index 0000000000..7f08095427 --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#ifndef LWIP_PING_H +#define LWIP_PING_H
+#include <lwip/ip_addr.h>
+/**
- PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used
- */
Is there any support for sockets in the current series? IOW if someome sets this to 1 will it work? If not get rid of it completely
+#ifndef PING_USE_SOCKETS +#define PING_USE_SOCKETS 0 +#endif
+int lwip_ping_init(char *ping_addr);
+void ping_raw_init(void); +void ping_send_now(void);
+#endif /* LWIP_PING_H */ diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h new file mode 100644 index 0000000000..0dd4bd78c7 --- /dev/null +++ b/lib/lwip/apps/ping/ping.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+#include "../../../lwip/ulwip.h"
Again, find a away to include this normally, without all the ../../ uglyness
+#include "lwip/prot/ip4.h"
+#define ip4_print_parts(a, b, c, d) \
- printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d);
+#define ip4_print(ipaddr) \
- ip4_print_parts(\
(u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \
(u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \
(u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \
(u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0))
+#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ +#define PING_RESULT(cond) { \
- if (cond == 1) { \
printf("host "); \
ip4_print(addr); \
printf(" is alive\n"); \
printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
ulwip_exit(0); \
- } else { \
printf("ping failed; host "); \
ip4_print(addr); \
printf(" is not alive\n"); \
ulwip_exit(-1); \
- } \
} while (0);
+#include "lwip/ip_addr.h"
+void ping_init(const ip_addr_t *ping_addr);
2.30.2
Thanks /Ilias

On Thu, 3 Aug 2023 at 15:32, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
On Wed, Aug 02, 2023 at 08:06:52PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 1 + lib/lwip/apps/ping/Makefile | 11 ++++++++++ lib/lwip/apps/ping/lwip_ping.c | 37 ++++++++++++++++++++++++++++++++++ lib/lwip/apps/ping/lwip_ping.h | 24 ++++++++++++++++++++++ lib/lwip/apps/ping/ping.h | 35 ++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 lib/lwip/apps/ping/Makefile create mode 100644 lib/lwip/apps/ping/lwip_ping.c create mode 100644 lib/lwip/apps/ping/lwip_ping.h create mode 100644 lib/lwip/apps/ping/ping.h
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index ec6b728c8e..87ed99a230 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -67,5 +67,6 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_PING) += apps/ping/ obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/lib/lwip/apps/ping/Makefile b/lib/lwip/apps/ping/Makefile new file mode 100644 index 0000000000..0d0a811336 --- /dev/null +++ b/lib/lwip/apps/ping/Makefile @@ -0,0 +1,11 @@ +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include
-I$(srctree)/lib/lwip
+ccflags-y += -I$(obj)
+.PHONY: $(obj)/ping.c +$(obj)/ping.o: $(obj)/ping.c +$(obj)/ping.c:
cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c
$(obj)/ping.c
+obj-$(CONFIG_CMD_PING) += ping.o +obj-$(CONFIG_CMD_PING) += lwip_ping.o diff --git a/lib/lwip/apps/ping/lwip_ping.c
b/lib/lwip/apps/ping/lwip_ping.c
new file mode 100644 index 0000000000..40658ab6fd --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "ping.h"
+#include <ulwip.h>
+static ip_addr_t ip_target;
+static int ulwip_ping_tmo(void) +{
printf("ping failed; host %s is not alive\n",
ipaddr_ntoa(&ip_target));
return 0;
Shouldnt this return != 0?
Yes.
Also why do we need this? Looking at ping_raw_init() it ets timeout and print fail messages
No, it doesn't print error messages. And I wanted to print exactly the
same message as the original ping does to pass validation tests. => lwip ping 1.1.1.1 Using virtio-net#30 device pinging addr: 1.1.1.1 ping failed; host 1.1.1.1 is not alive =>
+}
+int lwip_ping_init(char *ping_addr) +{
int err;
err = ipaddr_aton(ping_addr, &ip_target);
if (err == 0) {
printf("wrong ping addr string \"%s\" \n", ping_addr);
return -1;
}
ulwip_set_tmo(ulwip_ping_tmo);
ping_init(&ip_target);
return 0;
+} diff --git a/lib/lwip/apps/ping/lwip_ping.h
b/lib/lwip/apps/ping/lwip_ping.h
new file mode 100644 index 0000000000..7f08095427 --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#ifndef LWIP_PING_H +#define LWIP_PING_H
+#include <lwip/ip_addr.h>
+/**
- PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is
used
- */
Is there any support for sockets in the current series? IOW if someome sets this to 1 will it work? If not get rid of it completely
Thanks, get rid of it completely. Btw sockets can be implemented, maybe we will enable them later.
+#ifndef PING_USE_SOCKETS +#define PING_USE_SOCKETS 0 +#endif
+int lwip_ping_init(char *ping_addr);
+void ping_raw_init(void); +void ping_send_now(void);
+#endif /* LWIP_PING_H */ diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h new file mode 100644 index 0000000000..0dd4bd78c7 --- /dev/null +++ b/lib/lwip/apps/ping/ping.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+#include "../../../lwip/ulwip.h"
Again, find a away to include this normally, without all the ../../ uglyness
yea, fixed everywhere now.
+#include "lwip/prot/ip4.h"
+#define ip4_print_parts(a, b, c, d) \
printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d);
+#define ip4_print(ipaddr) \
ip4_print_parts(\
(u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) :
0), \
(u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) :
0), \
(u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) :
0), \
(u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) :
0))
+#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ +#define PING_RESULT(cond) { \
if (cond == 1) { \
printf("host "); \
ip4_print(addr); \
printf(" is alive\n"); \
printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
ulwip_exit(0); \
} else { \
printf("ping failed; host "); \
ip4_print(addr); \
printf(" is not alive\n"); \
ulwip_exit(-1); \
} \
} while (0);
+#include "lwip/ip_addr.h"
+void ping_init(const ip_addr_t *ping_addr);
2.30.2
Thanks /Ilias

lwip configuration can be tuned with header file.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/lwipopts.h | 203 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 lib/lwip/lwipopts.h
diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h new file mode 100644 index 0000000000..7f99a536ee --- /dev/null +++ b/lib/lwip/lwipopts.h @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +#include "lwipopts.h" + +#if defined(CONFIG_LWIP_LIB_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_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_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_LIB_NOASSERT) +#define LWIP_NOASSERT 1 +#define LWIP_ASSERT(message, assertion) +#endif + +#include "lwip/debug.h" + +#define SYS_LIGHTWEIGHT_PROT 0 +#define NO_SYS 0 + +#define MEM_ALIGNMENT 1 +#define MEM_SIZE CONFIG_LWIP_LIB_MEM_SIZE + +#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 IP_FORWARD 0 +#define IP_OPTIONS_ALLOWED 1 +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#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 1 + +#define LWIP_RAW 1 + +#if defined(CONFIG_LWIP_LIB_DHCP) +#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_LWIP_LIB_DNS) +#define LWIP_DNS 1 +#else +#define LWIP_DNS 0 +#endif + +#if defined(CONFIG_LWIP_LIB_TCP) +#define LWIP_UDP 1 +#else +#define LWIP_UDP 0 +#endif + +#if defined(CONFIG_LWIP_LIB_TCP) +#define LWIP_TCP 1 +#else +#define LWIP_TCP 0 +#endif + +#define LWIP_LISTEN_BACKLOG 0 + +#define PBUF_LINK_HLEN CONFIG_LWIP_LIB_PBUF_LINK_HLEN +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN) + +#define LWIP_HAVE_LOOPIF 0 + +#if defined(CONFIG_LWIP_LIB_NETCONN) +#define LWIP_NETCONN 1 +#else +#define LWIP_NETCONN 0 +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1 +#endif + +#if defined(CONFIG_LWIP_LIB_SOCKET) +#define LWIP_SOCKET 1 + +#define SO_REUSE 1 +#else +#define LWIP_SOCKET 0 +#define SO_REUSE 0 +#endif + +#define LWIP_STATS 0 + +#define PPP_SUPPORT 0 + +#define LWIP_TCPIP_CORE_LOCKING 0 + +#if defined(CONFIG_LWIP_LIB_LOOPBACK) +#define LWIP_NETIF_LOOPBACK 1 +#else +#define LWIP_NETIF_LOOPBACK 0 +#endif +/* use malloc instead of pool */ +#define MEMP_MEM_MALLOC 1 +#define MEMP_MEM_INIT 1 +#define MEM_LIBC_MALLOC 1 + +#endif /* LWIP_LWIPOPTS_H */

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/port/if.c | 256 ++++++++++++++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ 5 files changed, 381 insertions(+) create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c
diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c new file mode 100644 index 0000000000..2ed59a0c4e --- /dev/null +++ b/lib/lwip/port/if.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +extern int eth_init(void); /* net.h */ +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* net.h */ +extern struct in_addr net_ip; +extern u8 net_ethaddr[6]; + +#include "lwip/debug.h" +#include "lwip/arch.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h" + +#include "lwip/ip.h" + +#define IFNAME0 'e' +#define IFNAME1 '0' + +static struct pbuf *low_level_input(struct netif *netif); +static int uboot_net_use_lwip; + +int ulwip_enabled(void) +{ + return uboot_net_use_lwip; +} + +/* 1 - in loop + * 0 - no loop + */ +static int loop_lwip; + +/* ret 1 - in loop + * 0 - no loop + */ +int ulwip_in_loop(void) +{ + return loop_lwip; +} + +void ulwip_loop_set(int loop) +{ + loop_lwip = loop; +} + +static int ulwip_app_err; + +void ulwip_exit(int err) +{ + ulwip_app_err = err; + ulwip_loop_set(0); +} + +int ulwip_app_get_err(void) +{ + return ulwip_app_err; +} + +struct uboot_lwip_if { +}; + +static struct netif uboot_netif; + +#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0) + +extern uchar *net_rx_packet; +extern int net_rx_packet_len; + +int uboot_lwip_poll(void) +{ + struct pbuf *p; + int err; + + p = low_level_input(&uboot_netif); + if (!p) { + printf("error p = low_level_input = NULL\n"); + return 0; + } + + err = ethernet_input(p, &uboot_netif); + if (err) + printf("ip4_input err %d\n", err); + + return 0; +} + +static struct pbuf *low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + u16_t len = net_rx_packet_len; + uchar *data = net_rx_packet; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p) { +#if ETH_PAD_SIZE + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ +#endif + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. + */ + for (q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + MEMCPY(q->payload, data, q->len); + data += q->len; + } + //acknowledge that packet has been read(); + +#if ETH_PAD_SIZE + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + LINK_STATS_INC(link.recv); + } else { + //drop packet(); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +static int ethernetif_input(struct pbuf *p, struct netif *netif) +{ + struct ethernetif *ethernetif; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + + /* if no packet could be read, silently ignore this */ + if (p) { + /* pass all packets to ethernet_input, which decides what packets it supports */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", __func__)); + pbuf_free(p); + p = NULL; + } + } + return 0; +} + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + int err; + + err = eth_send(p->payload, p->len); + if (err != 0) { + printf("eth_send error %d\n", err); + return ERR_ABRT; + } + return ERR_OK; +} + +err_t uboot_lwip_if_init(struct netif *netif) +{ + struct uboot_lwip_if *uif = (struct uboot_lwip_if *)malloc(sizeof(struct uboot_lwip_if)); + + if (!uif) { + printf("uboot_lwip_if: out of memory\n"); + return ERR_MEM; + } + netif->state = uif; + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + + netif->hwaddr_len = ETHARP_HWADDR_LEN; + string_to_enetaddr(env_get("ethaddr"), netif->hwaddr); +#if defined(CONFIG_LWIP_LIB_DEBUG) + printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], + netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); +#endif + +#if LWIP_IPV4 + netif->output = etharp_output; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + eth_init(); /* activate u-boot eth dev */ + + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { + printf("Initialized LWIP stack\n"); + } + + return ERR_OK; +} + +int uboot_lwip_init(void) +{ + ip4_addr_t ipaddr, netmask, gw; + + if (uboot_net_use_lwip) + return CMD_RET_SUCCESS; + + ip4_addr_set_zero(&gw); + ip4_addr_set_zero(&ipaddr); + ip4_addr_set_zero(&netmask); + + ipaddr_aton(env_get("ipaddr"), &ipaddr); + ipaddr_aton(env_get("ipaddr"), &netmask); + + LWIP_PORT_INIT_NETMASK(&netmask); + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { + printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr)); + printf(" GW: %s\n", ip4addr_ntoa(&gw)); + printf(" mask: %s\n", ip4addr_ntoa(&netmask)); + } + + if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw, + &uboot_netif, uboot_lwip_if_init, ethernetif_input)) + printf("err: netif_add failed!\n"); + + netif_set_up(&uboot_netif); + netif_set_link_up(&uboot_netif); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&uboot_netif, 1); + printf(" IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0))); +#endif /* LWIP_IPV6 */ + + uboot_net_use_lwip = 1; + + return CMD_RET_SUCCESS; +} + +/* placeholder, not used now */ +void uboot_lwip_destroy(void) +{ + uboot_net_use_lwip = 0; +} diff --git a/lib/lwip/port/include/arch/cc.h b/lib/lwip/port/include/arch/cc.h new file mode 100644 index 0000000000..db30d7614e --- /dev/null +++ b/lib/lwip/port/include/arch/cc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * (C) Copyright 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> + +#define LWIP_ERRNO_INCLUDE <errno.h> + +#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1 + +extern unsigned int lwip_port_rand(void); +#define LWIP_RAND() (lwip_port_rand()) + +/* 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) + +static inline int atoi(const char *str) +{ + int r = 0; + int i; + + for (i = 0; str[i] != '\0'; ++i) + r = r * 10 + str[i] - '0'; + + return r; +} + +#define LWIP_ERR_T int + +#endif /* LWIP_ARCH_CC_H */ diff --git a/lib/lwip/port/include/arch/sys_arch.h b/lib/lwip/port/include/arch/sys_arch.h new file mode 100644 index 0000000000..8d95146275 --- /dev/null +++ b/lib/lwip/port/include/arch/sys_arch.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +#include "lwip/opt.h" +#include "lwip/arch.h" +#include "lwip/err.h" + +#define ERR_NEED_SCHED 123 + +void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms) + +#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#include <errno.h> + +#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL + +typedef u32_t sys_prot_t; + +struct sys_sem; +typedef struct sys_sem *sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = NULL; }} while (0) + +/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 +#define LWIP_COMPAT_MUTEX_ALLOWED 1 + +struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = NULL; }} while (0) + +struct sys_thread; +typedef struct sys_thread *sys_thread_t; + +static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + return 0; +}; + +static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + return 0; +}; + +#define sys_sem_signal(s) + +#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/lib/lwip/port/include/limits.h b/lib/lwip/port/include/limits.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c new file mode 100644 index 0000000000..609eeccf8c --- /dev/null +++ b/lib/lwip/port/sys-arch.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <rand.h> +#include "lwip/opt.h" + +u32_t sys_now(void) +{ + return get_timer(0); +} + +u32_t lwip_port_rand(void) +{ + return (u32_t)rand(); +} +

Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
subject: U-Boot
commit message please (throughout series)
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/port/if.c | 256 ++++++++++++++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ 5 files changed, 381 insertions(+) create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c
I wonder if this port/ directory should go away and this code should be in net/ ? It feels a bit odd, as lib/ code suggests it is for libraries, not the integration with them.
diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c new file mode 100644 index 0000000000..2ed59a0c4e --- /dev/null +++ b/lib/lwip/port/if.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +extern int eth_init(void); /* net.h */ +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* net.h */ +extern struct in_addr net_ip; +extern u8 net_ethaddr[6];
Can that go in a header file?
+#include "lwip/debug.h" +#include "lwip/arch.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h"
+#include "lwip/ip.h"
+#define IFNAME0 'e' +#define IFNAME1 '0'
+static struct pbuf *low_level_input(struct netif *netif); +static int uboot_net_use_lwip;
Can we put this stuff in the UCLASS_ETH private data instead of using statics? They require BSS which is typically not available in SPL builds.
+int ulwip_enabled(void) +{
return uboot_net_use_lwip;
+}
+/* 1 - in loop
- 0 - no loop
- */
+static int loop_lwip;
+/* ret 1 - in loop
0 - no loop
??
This all needs some more detail in the comments
- */
+int ulwip_in_loop(void) +{
return loop_lwip;
+}
+void ulwip_loop_set(int loop) +{
loop_lwip = loop;
+}
+static int ulwip_app_err;
+void ulwip_exit(int err) +{
ulwip_app_err = err;
ulwip_loop_set(0);
+}
+int ulwip_app_get_err(void) +{
return ulwip_app_err;
+}
+struct uboot_lwip_if { +};
+static struct netif uboot_netif;
+#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0)
+extern uchar *net_rx_packet; +extern int net_rx_packet_len;
header file please
+int uboot_lwip_poll(void) +{
struct pbuf *p;
int err;
p = low_level_input(&uboot_netif);
if (!p) {
printf("error p = low_level_input = NULL\n");
return 0;
}
err = ethernet_input(p, &uboot_netif);
if (err)
printf("ip4_input err %d\n", err);
log_err() ?
But what is going on here? Just return the error code, rather than suppressing it, then the caller can handle it.
return 0;
+}
+static struct pbuf *low_level_input(struct netif *netif) +{
struct pbuf *p, *q;
u16_t len = net_rx_packet_len;
uchar *data = net_rx_packet;
+#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
Please find a way to drop any use of #if
This can be defined to 0 if not needed, for example. Or you could have a static inline eth_pad_size() in the header file (where #if is permitted)
+#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p) {
+#if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */
+#endif
/* We iterate over the pbuf chain until we have read the entire
* packet into the pbuf.
*/
for (q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
Comment style
/* * Read
* available data in the pbuf is given by the q->len
* variable.
* This does not necessarily have to be a memcpy, you can also preallocate
* pbufs for a DMA-enabled MAC and after receiving truncate it to the
* actually received size. In this case, ensure the tot_len member of the
* pbuf is the sum of the chained pbuf len members.
*/
MEMCPY(q->payload, data, q->len);
data += q->len;
}
//acknowledge that packet has been read();
Space after // (please fix throughout)
+#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
LINK_STATS_INC(link.recv);
} else {
//drop packet();
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
+}
+static int ethernetif_input(struct pbuf *p, struct netif *netif) +{
struct ethernetif *ethernetif;
ethernetif = netif->state;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* if no packet could be read, silently ignore this */
if (p) {
/* pass all packets to ethernet_input, which decides what packets it supports */
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", __func__));
pbuf_free(p);
p = NULL;
}
}
blank line before final return
return 0;
+}
+static err_t low_level_output(struct netif *netif, struct pbuf *p) +{
int err;
err = eth_send(p->payload, p->len);
if (err != 0) {
if (err)
printf("eth_send error %d\n", err);
return ERR_ABRT;
}
return ERR_OK;
+}
+err_t uboot_lwip_if_init(struct netif *netif) +{
struct uboot_lwip_if *uif = (struct uboot_lwip_if *)malloc(sizeof(struct uboot_lwip_if));
if (!uif) {
printf("uboot_lwip_if: out of memory\n");
return ERR_MEM;
}
netif->state = uif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
string_to_enetaddr(env_get("ethaddr"), netif->hwaddr);
+#if defined(CONFIG_LWIP_LIB_DEBUG)
printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);
+#endif
+#if LWIP_IPV4
netif->output = etharp_output;
+#endif /* LWIP_IPV4 */ +#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
You may need to add accessors in the header file (as global_data.h) so you don't need the #if
netif->linkoutput = low_level_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
eth_init(); /* activate u-boot eth dev */
if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
printf("Initialized LWIP stack\n");
}
return ERR_OK;
+}
+int uboot_lwip_init(void) +{
ip4_addr_t ipaddr, netmask, gw;
if (uboot_net_use_lwip)
return CMD_RET_SUCCESS;
ip4_addr_set_zero(&gw);
ip4_addr_set_zero(&ipaddr);
ip4_addr_set_zero(&netmask);
ipaddr_aton(env_get("ipaddr"), &ipaddr);
ipaddr_aton(env_get("ipaddr"), &netmask);
LWIP_PORT_INIT_NETMASK(&netmask);
if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr));
printf(" GW: %s\n", ip4addr_ntoa(&gw));
printf(" mask: %s\n", ip4addr_ntoa(&netmask));
}
if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw,
&uboot_netif, uboot_lwip_if_init, ethernetif_input))
printf("err: netif_add failed!\n");
netif_set_up(&uboot_netif);
netif_set_link_up(&uboot_netif);
+#if LWIP_IPV6
if ()
netif_create_ip6_linklocal_address(&uboot_netif, 1);
printf(" IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0)));
+#endif /* LWIP_IPV6 */
uboot_net_use_lwip = 1;
return CMD_RET_SUCCESS;
+}
+/* placeholder, not used now */ +void uboot_lwip_destroy(void) +{
uboot_net_use_lwip = 0;
+} diff --git a/lib/lwip/port/include/arch/cc.h b/lib/lwip/port/include/arch/cc.h new file mode 100644 index 0000000000..db30d7614e --- /dev/null +++ b/lib/lwip/port/include/arch/cc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
It would help to have a little one-line comment as to what these files are for.
- (C) Copyright 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>
+#define LWIP_ERRNO_INCLUDE <errno.h>
+#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1
+extern unsigned int lwip_port_rand(void); +#define LWIP_RAND() (lwip_port_rand())
+/* 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)
+static inline int atoi(const char *str)
Can we use U-Boot's version?
+{
int r = 0;
int i;
for (i = 0; str[i] != '\0'; ++i)
r = r * 10 + str[i] - '0';
return r;
+}
+#define LWIP_ERR_T int
+#endif /* LWIP_ARCH_CC_H */ diff --git a/lib/lwip/port/include/arch/sys_arch.h b/lib/lwip/port/include/arch/sys_arch.h new file mode 100644 index 0000000000..8d95146275 --- /dev/null +++ b/lib/lwip/port/include/arch/sys_arch.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H
+#include "lwip/opt.h" +#include "lwip/arch.h" +#include "lwip/err.h"
+#define ERR_NEED_SCHED 123
+void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms)
+#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */
+#include <errno.h>
+#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL
+typedef u32_t sys_prot_t;
+struct sys_sem; +typedef struct sys_sem *sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = NULL; }} while (0)
+/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 +#define LWIP_COMPAT_MUTEX_ALLOWED 1
+struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = NULL; }} while (0)
+struct sys_thread; +typedef struct sys_thread *sys_thread_t;
+static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{
return 0;
+};
+static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{
return 0;
+};
+#define sys_sem_signal(s)
+#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/lib/lwip/port/include/limits.h b/lib/lwip/port/include/limits.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c new file mode 100644 index 0000000000..609eeccf8c --- /dev/null +++ b/lib/lwip/port/sys-arch.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <rand.h> +#include "lwip/opt.h"
+u32_t sys_now(void) +{
return get_timer(0);
+}
+u32_t lwip_port_rand(void) +{
return (u32_t)rand();
+}
-- 2.30.2
Regards, Simon

On Thu, 3 Aug 2023 at 03:32, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
subject: U-Boot
commit message please (throughout series)
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/port/if.c | 256 ++++++++++++++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ 5 files changed, 381 insertions(+) create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c
I wonder if this port/ directory should go away and this code should be in net/ ? It feels a bit odd, as lib/ code suggests it is for libraries, not the integration with them.
diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c new file mode 100644 index 0000000000..2ed59a0c4e --- /dev/null +++ b/lib/lwip/port/if.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +extern int eth_init(void); /* net.h */ +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /*
net.h */
+extern struct in_addr net_ip; +extern u8 net_ethaddr[6];
Can that go in a header file?
I tried to do as minimal changes as I could. In general these are definitions from include/net.h. And the problem that net.h has not only ethernet things, but also protocol defines which overlaps with lwip protocol defines and data structures. More clean fix will be to clean up net.h and move ip to net/ip.h udp to net/udp.h and so on. So here we can include <net.h> to get eth_init() and friends accessed.
+#include "lwip/debug.h" +#include "lwip/arch.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h"
+#include "lwip/ip.h"
+#define IFNAME0 'e' +#define IFNAME1 '0'
+static struct pbuf *low_level_input(struct netif *netif); +static int uboot_net_use_lwip;
Can we put this stuff in the UCLASS_ETH private data instead of using statics? They require BSS which is typically not available in SPL builds.
yes, that will work. I expect this flag to be used for compatibility mode. I.e. if it's set before cmd then lwip controls net_loop(), if not set then an original code controls net_loop(). I can even add an argument to eth_init(). But because there are too many eth_init() calls I think I will add an entry to uclass.
+int ulwip_enabled(void) +{
return uboot_net_use_lwip;
+}
+/* 1 - in loop
- 0 - no loop
- */
+static int loop_lwip;
+/* ret 1 - in loop
0 - no loop
??
This all needs some more detail in the comments
Yes, maybe with UCLASS_ETH some of that will go away.
- */
+int ulwip_in_loop(void) +{
return loop_lwip;
+}
+void ulwip_loop_set(int loop) +{
loop_lwip = loop;
+}
+static int ulwip_app_err;
+void ulwip_exit(int err) +{
ulwip_app_err = err;
ulwip_loop_set(0);
+}
+int ulwip_app_get_err(void) +{
return ulwip_app_err;
+}
+struct uboot_lwip_if { +};
+static struct netif uboot_netif;
+#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0)
+extern uchar *net_rx_packet; +extern int net_rx_packet_len;
header file please
ok, the same thing here, it's from net.h
+int uboot_lwip_poll(void) +{
struct pbuf *p;
int err;
p = low_level_input(&uboot_netif);
if (!p) {
printf("error p = low_level_input = NULL\n");
return 0;
}
err = ethernet_input(p, &uboot_netif);
if (err)
printf("ip4_input err %d\n", err);
log_err() ?
But what is going on here? Just return the error code, rather than suppressing it, then the caller can handle it.
Looked more detail - current version ethernet_input() (lwip master) always returns ERR_OK (0). When I wrote I added a return code check for non function. So I expect that it can be considered as a bug if some time later we receive something non 0.
But in general the poll() function has to be void. I will correct it.
return 0;
+}
+static struct pbuf *low_level_input(struct netif *netif) +{
struct pbuf *p, *q;
u16_t len = net_rx_packet_len;
uchar *data = net_rx_packet;
+#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
Please find a way to drop any use of #if
This can be defined to 0 if not needed, for example. Or you could have a static inline eth_pad_size() in the header file (where #if is permitted)
+#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p) {
+#if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding
word */
+#endif
/* We iterate over the pbuf chain until we have read the
entire
* packet into the pbuf.
*/
for (q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the
chain. The
Comment style
/*
- Read
* available data in the pbuf is given by the
q->len
* variable.
* This does not necessarily have to be a
memcpy, you can also preallocate
* pbufs for a DMA-enabled MAC and after
receiving truncate it to the
* actually received size. In this case, ensure
the tot_len member of the
* pbuf is the sum of the chained pbuf len
members.
*/
MEMCPY(q->payload, data, q->len);
data += q->len;
}
//acknowledge that packet has been read();
Space after // (please fix throughout)
+#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding
word */
+#endif
LINK_STATS_INC(link.recv);
} else {
//drop packet();
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
+}
+static int ethernetif_input(struct pbuf *p, struct netif *netif) +{
struct ethernetif *ethernetif;
ethernetif = netif->state;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* if no packet could be read, silently ignore this */
if (p) {
/* pass all packets to ethernet_input, which decides
what packets it supports */
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input
error\n", __func__));
pbuf_free(p);
p = NULL;
}
}
blank line before final return
return 0;
+}
+static err_t low_level_output(struct netif *netif, struct pbuf *p) +{
int err;
err = eth_send(p->payload, p->len);
if (err != 0) {
if (err)
printf("eth_send error %d\n", err);
return ERR_ABRT;
}
return ERR_OK;
+}
+err_t uboot_lwip_if_init(struct netif *netif) +{
struct uboot_lwip_if *uif = (struct uboot_lwip_if
*)malloc(sizeof(struct uboot_lwip_if));
if (!uif) {
printf("uboot_lwip_if: out of memory\n");
return ERR_MEM;
}
netif->state = uif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
string_to_enetaddr(env_get("ethaddr"), netif->hwaddr);
+#if defined(CONFIG_LWIP_LIB_DEBUG)
printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);
+#endif
+#if LWIP_IPV4
netif->output = etharp_output;
+#endif /* LWIP_IPV4 */ +#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
You may need to add accessors in the header file (as global_data.h) so you don't need the #if
netif->linkoutput = low_level_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
NETIF_FLAG_LINK_UP;
eth_init(); /* activate u-boot eth dev */
if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
printf("Initialized LWIP stack\n");
}
return ERR_OK;
+}
+int uboot_lwip_init(void) +{
ip4_addr_t ipaddr, netmask, gw;
if (uboot_net_use_lwip)
return CMD_RET_SUCCESS;
ip4_addr_set_zero(&gw);
ip4_addr_set_zero(&ipaddr);
ip4_addr_set_zero(&netmask);
ipaddr_aton(env_get("ipaddr"), &ipaddr);
ipaddr_aton(env_get("ipaddr"), &netmask);
LWIP_PORT_INIT_NETMASK(&netmask);
if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr));
printf(" GW: %s\n", ip4addr_ntoa(&gw));
printf(" mask: %s\n",
ip4addr_ntoa(&netmask));
}
if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw,
&uboot_netif, uboot_lwip_if_init,
ethernetif_input))
printf("err: netif_add failed!\n");
netif_set_up(&uboot_netif);
netif_set_link_up(&uboot_netif);
+#if LWIP_IPV6
if ()
netif_create_ip6_linklocal_address(&uboot_netif, 1);
printf(" IPv6: %s\n",
ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0)));
+#endif /* LWIP_IPV6 */
uboot_net_use_lwip = 1;
return CMD_RET_SUCCESS;
+}
+/* placeholder, not used now */ +void uboot_lwip_destroy(void) +{
uboot_net_use_lwip = 0;
+} diff --git a/lib/lwip/port/include/arch/cc.h
b/lib/lwip/port/include/arch/cc.h
new file mode 100644 index 0000000000..db30d7614e --- /dev/null +++ b/lib/lwip/port/include/arch/cc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
It would help to have a little one-line comment as to what these files are for.
- (C) Copyright 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>
+#define LWIP_ERRNO_INCLUDE <errno.h>
+#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1
+extern unsigned int lwip_port_rand(void); +#define LWIP_RAND() (lwip_port_rand())
+/* 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)
+static inline int atoi(const char *str)
Can we use U-Boot's version?
+{
int r = 0;
int i;
for (i = 0; str[i] != '\0'; ++i)
r = r * 10 + str[i] - '0';
return r;
+}
+#define LWIP_ERR_T int
+#endif /* LWIP_ARCH_CC_H */ diff --git a/lib/lwip/port/include/arch/sys_arch.h
b/lib/lwip/port/include/arch/sys_arch.h
new file mode 100644 index 0000000000..8d95146275 --- /dev/null +++ b/lib/lwip/port/include/arch/sys_arch.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H
+#include "lwip/opt.h" +#include "lwip/arch.h" +#include "lwip/err.h"
+#define ERR_NEED_SCHED 123
+void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms)
+#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */
+#include <errno.h>
+#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL
+typedef u32_t sys_prot_t;
+struct sys_sem; +typedef struct sys_sem *sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) =
NULL; }} while (0)
+/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 +#define LWIP_COMPAT_MUTEX_ALLOWED 1
+struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) =
NULL; }} while (0)
+struct sys_thread; +typedef struct sys_thread *sys_thread_t;
+static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{
return 0;
+};
+static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{
return 0;
+};
+#define sys_sem_signal(s)
+#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/lib/lwip/port/include/limits.h
b/lib/lwip/port/include/limits.h
new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c new file mode 100644 index 0000000000..609eeccf8c --- /dev/null +++ b/lib/lwip/port/sys-arch.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <rand.h> +#include "lwip/opt.h"
+u32_t sys_now(void) +{
return get_timer(0);
+}
+u32_t lwip_port_rand(void) +{
return (u32_t)rand();
+}
-- 2.30.2
Regards, Simon

On Thu, 3 Aug 2023 at 22:21, Maxim Uvarov maxim.uvarov@linaro.org wrote:
On Thu, 3 Aug 2023 at 03:32, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
subject: U-Boot
commit message please (throughout series)
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/port/if.c | 256 ++++++++++++++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ 5 files changed, 381 insertions(+) create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c
I wonder if this port/ directory should go away and this code should be in net/ ? It feels a bit odd, as lib/ code suggests it is for libraries, not the integration with them.
In all lwIP examples I was port/ directory with specific files for the platform. And here I also planned to follow the same rule. And yes, I think it's better to move all this code to net/ and cmd/.
diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c new file mode 100644 index 0000000000..2ed59a0c4e --- /dev/null +++ b/lib/lwip/port/if.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <command.h> +extern int eth_init(void); /* net.h */ +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
/* net.h */
+extern struct in_addr net_ip; +extern u8 net_ethaddr[6];
Can that go in a header file?
I tried to do as minimal changes as I could. In general these are definitions from include/net.h. And the problem that net.h has not only ethernet things, but also protocol defines which overlaps with lwip protocol defines and data structures. More clean fix will be to clean up net.h and move ip to net/ip.h udp to net/udp.h and so on. So here we can include <net.h> to get eth_init() and friends accessed.
+#include "lwip/debug.h" +#include "lwip/arch.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h"
+#include "lwip/ip.h"
+#define IFNAME0 'e' +#define IFNAME1 '0'
+static struct pbuf *low_level_input(struct netif *netif); +static int uboot_net_use_lwip;
Can we put this stuff in the UCLASS_ETH private data instead of using statics? They require BSS which is typically not available in SPL builds.
yes, that will work. I expect this flag to be used for compatibility mode. I.e. if it's set before cmd then lwip controls net_loop(), if not set then an original code controls net_loop(). I can even add an argument to eth_init(). But because there are too many eth_init() calls I think I will add an entry to uclass.
moved to UCLASS_ETH with split net.h on net.h, eth.h and arp.h. And I like how it looks now, thanks!
+int ulwip_enabled(void) +{
return uboot_net_use_lwip;
+}
+/* 1 - in loop
- 0 - no loop
- */
+static int loop_lwip;
+/* ret 1 - in loop
0 - no loop
??
This all needs some more detail in the comments
Yes, maybe with UCLASS_ETH some of that will go away.
Yes, that goes away after moving.
- */
+int ulwip_in_loop(void) +{
return loop_lwip;
+}
+void ulwip_loop_set(int loop) +{
loop_lwip = loop;
+}
+static int ulwip_app_err;
+void ulwip_exit(int err) +{
ulwip_app_err = err;
ulwip_loop_set(0);
+}
+int ulwip_app_get_err(void) +{
return ulwip_app_err;
+}
+struct uboot_lwip_if { +};
+static struct netif uboot_netif;
+#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255,
+extern uchar *net_rx_packet; +extern int net_rx_packet_len;
header file please
ok, the same thing here, it's from net.h
+int uboot_lwip_poll(void) +{
struct pbuf *p;
int err;
p = low_level_input(&uboot_netif);
if (!p) {
printf("error p = low_level_input = NULL\n");
return 0;
}
err = ethernet_input(p, &uboot_netif);
if (err)
printf("ip4_input err %d\n", err);
log_err() ?
But what is going on here? Just return the error code, rather than suppressing it, then the caller can handle it.
Looked more detail - current version ethernet_input() (lwip master) always returns ERR_OK (0). When I wrote I added a return code check for non function. So I expect that it can be considered as a bug if some time later we receive something non 0.
But in general the poll() function has to be void. I will correct it.
return 0;
+}
+static struct pbuf *low_level_input(struct netif *netif) +{
struct pbuf *p, *q;
u16_t len = net_rx_packet_len;
uchar *data = net_rx_packet;
+#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
Please find a way to drop any use of #if
This can be defined to 0 if not needed, for example. Or you could have a static inline eth_pad_size() in the header file (where #if is permitted)
let's drop for n
+#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p) {
+#if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the
padding word */
+#endif
/* We iterate over the pbuf chain until we have read
the entire
* packet into the pbuf.
*/
for (q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the
chain. The
Comment style
/*
- Read
* available data in the pbuf is given by the
q->len
* variable.
* This does not necessarily have to be a
memcpy, you can also preallocate
* pbufs for a DMA-enabled MAC and after
receiving truncate it to the
* actually received size. In this case, ensure
the tot_len member of the
* pbuf is the sum of the chained pbuf len
members.
*/
MEMCPY(q->payload, data, q->len);
data += q->len;
}
//acknowledge that packet has been read();
Space after // (please fix throughout)
+#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the
padding word */
+#endif
LINK_STATS_INC(link.recv);
} else {
//drop packet();
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
return p;
+}
+static int ethernetif_input(struct pbuf *p, struct netif *netif) +{
struct ethernetif *ethernetif;
ethernetif = netif->state;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* if no packet could be read, silently ignore this */
if (p) {
/* pass all packets to ethernet_input, which decides
what packets it supports */
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input
error\n", __func__));
pbuf_free(p);
p = NULL;
}
}
blank line before final return
return 0;
+}
+static err_t low_level_output(struct netif *netif, struct pbuf *p) +{
int err;
err = eth_send(p->payload, p->len);
if (err != 0) {
if (err)
printf("eth_send error %d\n", err);
return ERR_ABRT;
}
return ERR_OK;
+}
+err_t uboot_lwip_if_init(struct netif *netif) +{
struct uboot_lwip_if *uif = (struct uboot_lwip_if
*)malloc(sizeof(struct uboot_lwip_if));
if (!uif) {
printf("uboot_lwip_if: out of memory\n");
return ERR_MEM;
}
netif->state = uif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
string_to_enetaddr(env_get("ethaddr"), netif->hwaddr);
+#if defined(CONFIG_LWIP_LIB_DEBUG)
printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);
+#endif
+#if LWIP_IPV4
netif->output = etharp_output;
+#endif /* LWIP_IPV4 */ +#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
You may need to add accessors in the header file (as global_data.h) so you don't need the #if
I did not understand the comment about global_data.h. lwiIP as I understand can work in 3 modes 1. ipv4 2.ipv6 3. ipv4+ipv6. If we want optimization for size I think we need to pass this to Kconfig because lwip has some structs under ifdefs.
netif->linkoutput = low_level_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
NETIF_FLAG_LINK_UP;
eth_init(); /* activate u-boot eth dev */
if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
printf("Initialized LWIP stack\n");
}
return ERR_OK;
+}
+int uboot_lwip_init(void) +{
ip4_addr_t ipaddr, netmask, gw;
if (uboot_net_use_lwip)
return CMD_RET_SUCCESS;
ip4_addr_set_zero(&gw);
ip4_addr_set_zero(&ipaddr);
ip4_addr_set_zero(&netmask);
ipaddr_aton(env_get("ipaddr"), &ipaddr);
ipaddr_aton(env_get("ipaddr"), &netmask);
LWIP_PORT_INIT_NETMASK(&netmask);
if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
printf("Starting lwIP, IP: %s\n",
ip4addr_ntoa(&ipaddr));
printf(" GW: %s\n", ip4addr_ntoa(&gw));
printf(" mask: %s\n",
ip4addr_ntoa(&netmask));
}
if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw,
&uboot_netif, uboot_lwip_if_init,
ethernetif_input))
printf("err: netif_add failed!\n");
netif_set_up(&uboot_netif);
netif_set_link_up(&uboot_netif);
+#if LWIP_IPV6
if ()
No, we are using lwip header files. it will not work if LWIP_IPV6 set to 0.
netif_create_ip6_linklocal_address(&uboot_netif, 1);
printf(" IPv6: %s\n",
ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0)));
+#endif /* LWIP_IPV6 */
uboot_net_use_lwip = 1;
return CMD_RET_SUCCESS;
+}
+/* placeholder, not used now */ +void uboot_lwip_destroy(void) +{
uboot_net_use_lwip = 0;
+} diff --git a/lib/lwip/port/include/arch/cc.h
b/lib/lwip/port/include/arch/cc.h
new file mode 100644 index 0000000000..db30d7614e --- /dev/null +++ b/lib/lwip/port/include/arch/cc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
It would help to have a little one-line comment as to what these files are for.
- (C) Copyright 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>
+#define LWIP_ERRNO_INCLUDE <errno.h>
+#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1
+extern unsigned int lwip_port_rand(void); +#define LWIP_RAND() (lwip_port_rand())
+/* 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)
+static inline int atoi(const char *str)
Can we use U-Boot's version?
#include <stdlib.h> /* getenv, atoi */ compiles but generates error on linking. I guess there is no atoi in U-Boot.
+{
int r = 0;
int i;
for (i = 0; str[i] != '\0'; ++i)
r = r * 10 + str[i] - '0';
return r;
+}
+#define LWIP_ERR_T int
+#endif /* LWIP_ARCH_CC_H */ diff --git a/lib/lwip/port/include/arch/sys_arch.h
b/lib/lwip/port/include/arch/sys_arch.h
new file mode 100644 index 0000000000..8d95146275 --- /dev/null +++ b/lib/lwip/port/include/arch/sys_arch.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H
+#include "lwip/opt.h" +#include "lwip/arch.h" +#include "lwip/err.h"
+#define ERR_NEED_SCHED 123
+void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms)
+#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */
+#include <errno.h>
+#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL
+typedef u32_t sys_prot_t;
+struct sys_sem; +typedef struct sys_sem *sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) =
NULL; }} while (0)
+/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 +#define LWIP_COMPAT_MUTEX_ALLOWED 1
+struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox)
= NULL; }} while (0)
+struct sys_thread; +typedef struct sys_thread *sys_thread_t;
+static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{
return 0;
+};
+static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{
return 0;
+};
+#define sys_sem_signal(s)
+#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/lib/lwip/port/include/limits.h
b/lib/lwip/port/include/limits.h
new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c new file mode 100644 index 0000000000..609eeccf8c --- /dev/null +++ b/lib/lwip/port/sys-arch.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0
+/*
- (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
- */
+#include <common.h> +#include <rand.h> +#include "lwip/opt.h"
+u32_t sys_now(void) +{
return get_timer(0);
+}
+u32_t lwip_port_rand(void) +{
return (u32_t)rand();
+}
-- 2.30.2
Regards, Simon

Hi Maxim,
On Tue, 8 Aug 2023 at 04:07, Maxim Uvarov maxim.uvarov@linaro.org wrote:
On Thu, 3 Aug 2023 at 22:21, Maxim Uvarov maxim.uvarov@linaro.org wrote:
On Thu, 3 Aug 2023 at 03:32, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
subject: U-Boot
commit message please (throughout series)
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/port/if.c | 256 ++++++++++++++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ 5 files changed, 381 insertions(+) create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c
[..]
+#if LWIP_IPV4
netif->output = etharp_output;
+#endif /* LWIP_IPV4 */ +#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
You may need to add accessors in the header file (as global_data.h) so you don't need the #if
I did not understand the comment about global_data.h. lwiIP as I understand can work in 3 modes 1. ipv4 2.ipv6 3. ipv4+ipv6. If we want optimization for size I think we need to pass this to Kconfig because lwip has some structs under ifdefs.
I mean that you can follow what global_data.h does.
gd_malloc_start() is an example of using a header-file construct to avoid #ifdef in the source.
[..]
+#if LWIP_IPV6
if ()
No, we are using lwip header files. it will not work if LWIP_IPV6 set to 0.
In general we should always include all header files needed for the source, and this should be harmless. We don't normally #ifdef header files.
netif_create_ip6_linklocal_address(&uboot_netif, 1);
printf(" IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0)));
+#endif /* LWIP_IPV6 */
uboot_net_use_lwip = 1;
return CMD_RET_SUCCESS;
+}
+/* placeholder, not used now */ +void uboot_lwip_destroy(void) +{
uboot_net_use_lwip = 0;
+} diff --git a/lib/lwip/port/include/arch/cc.h b/lib/lwip/port/include/arch/cc.h new file mode 100644 index 0000000000..db30d7614e --- /dev/null +++ b/lib/lwip/port/include/arch/cc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+/*
It would help to have a little one-line comment as to what these files are for.
- (C) Copyright 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>
+#define LWIP_ERRNO_INCLUDE <errno.h>
+#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1
+extern unsigned int lwip_port_rand(void); +#define LWIP_RAND() (lwip_port_rand())
+/* 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)
+static inline int atoi(const char *str)
Can we use U-Boot's version?
#include <stdlib.h> /* getenv, atoi */ compiles but generates error on linking. I guess there is no atoi in U-Boot.
No...simple_strtoul() is similar so you could call that from your atoi().
Regards, Simon

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/.gitignore b/.gitignore index 3a4d056edf..9f2935f917 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,12 @@ __pycache__
# moveconfig database /moveconfig.db + +lib/lwip/lwip-external +lib/lwip/apps/ping/ping.c +lib/lwip/apps/http/http_client.c +lib/lwip/apps/http/http_client.h +lib/lwip/apps/tftp/tftp.c +lib/lwip/apps/tftp/tftp_client.h +lib/lwip/apps/tftp/tftp_common.h +lib/lwip/apps/tftp/tftp_example.h

Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
.gitignore | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/.gitignore b/.gitignore index 3a4d056edf..9f2935f917 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,12 @@ __pycache__
# moveconfig database /moveconfig.db
+lib/lwip/lwip-external +lib/lwip/apps/ping/ping.c +lib/lwip/apps/http/http_client.c +lib/lwip/apps/http/http_client.h +lib/lwip/apps/tftp/tftp.c +lib/lwip/apps/tftp/tftp_client.h +lib/lwip/apps/tftp/tftp_common.h +lib/lwip/apps/tftp/tftp_example.h
Would it be OK to put these in lib/lwip/.gitignore ?
-- 2.30.2
Regards, Simon

Hi Maxim
On Wed, 2 Aug 2023 at 17:09, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
You need to try and be a bit more formal. This is past the RFC stage, you need commit messages that make sense.
Thanks /Ilias
.gitignore | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/.gitignore b/.gitignore index 3a4d056edf..9f2935f917 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,12 @@ __pycache__
# moveconfig database /moveconfig.db
+lib/lwip/lwip-external +lib/lwip/apps/ping/ping.c +lib/lwip/apps/http/http_client.c +lib/lwip/apps/http/http_client.h +lib/lwip/apps/tftp/tftp.c +lib/lwip/apps/tftp/tftp_client.h +lib/lwip/apps/tftp/tftp_common.h
+lib/lwip/apps/tftp/tftp_example.h
2.30.2

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- lib/lwip/Makefile | 2 + lib/lwip/cmd-lwip.c | 308 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 lib/lwip/cmd-lwip.c
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile index 87ed99a230..25299377cd 100644 --- a/lib/lwip/Makefile +++ b/lib/lwip/Makefile @@ -65,6 +65,8 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_NET) += cmd-lwip.o + obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o obj-$(CONFIG_CMD_PING) += apps/ping/ diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c new file mode 100644 index 0000000000..86b35ccff8 --- /dev/null +++ b/lib/lwip/cmd-lwip.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Maxim Uvarov, maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <console.h> +#include <display_options.h> +#include <memalign.h> +#include <net.h> +#include <image.h> + +#include "apps/dns/lwip-dns.h" +#include "apps/ping/lwip_ping.h" +#include "ulwip.h" + +extern int uboot_lwip_init(void); +extern int uboot_lwip_loop_is_done(void); + +static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + printf("TBD: %s\n", __func__); + return CMD_RET_SUCCESS; +} + +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (!uboot_lwip_init()) + return CMD_RET_SUCCESS; + return CMD_RET_FAILURE; +} + +static int lwip_empty_tmo(void) { return 0; }; +int (*ulwip_tmo)(void) = lwip_empty_tmo; +void ulwip_set_tmo(int (*tmo)(void)) +{ + ulwip_tmo = tmo; +} + +static void ulwip_clear_tmo(void) +{ + ulwip_tmo = lwip_empty_tmo; +} + +static void ulwip_timeout_handler(void) +{ + eth_halt(); + ulwip_tmo(); + net_set_state(NETLOOP_FAIL); /* we did not get the reply */ + ulwip_loop_set(0); +} + +static int ulwip_loop(void) +{ + ulwip_loop_set(1); + if (net_loop(LWIP) < 0) { + ulwip_loop_set(0); + return CMD_RET_FAILURE; + } + ulwip_loop_set(0); + return CMD_RET_SUCCESS; +} + +#if defined(CONFIG_CMD_PING) +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (argc < 2) { + printf("argc = %d, error\n", argc); + return CMD_RET_USAGE; + } + + uboot_lwip_init(); + + eth_init(); /* activate u-boot eth dev */ + + printf("Using %s device\n", eth_get_name()); + printf("pinging addr: %s\n", argv[1]); + + net_set_timeout_handler(1000UL, ulwip_timeout_handler); + + if (lwip_ping_init(argv[1])) { + printf("ping init fail\n"); + return CMD_RET_FAILURE; + } + + ping_send_now(); + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_PING */ + +#if defined(CONFIG_CMD_WGET) +extern int lwip_wget(ulong addr, char *url); + +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *url; + + if (argc < 2) { + printf("argc = %d, error\n", argc); + return CMD_RET_USAGE; + } + url = argv[1]; + + uboot_lwip_init(); + + eth_init(); /* activate u-boot eth dev */ + + lwip_wget(image_load_addr, url); + + return ulwip_loop(); +} +#endif + +#if defined(CONFIG_CMD_TFTPBOOT) +extern int lwip_tftp(ulong addr, char *filename); + +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *filename; + ulong addr; + char *end; + int ret; + + switch (argc) { + case 1: + filename = 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; + filename = env_get("bootfile"); + } else { + filename = argv[1]; + } + break; + case 3: + image_load_addr = hextoul(argv[1], NULL); + filename = argv[2]; + break; + default: + return CMD_RET_USAGE; + } + + uboot_lwip_init(); + + eth_init(); /* activate u-boot eth dev */ + + ret = lwip_tftp(image_load_addr, filename); + if (ret) + return ret; + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_TFTPBOOT */ + +#if defined(CONFIG_CMD_DHCP) +extern int ulwip_dhcp(void); + +int do_lwip_dhcp(void) +{ + int ret; + char *filename; + + uboot_lwip_init(); + + ret = ulwip_dhcp(); + + net_set_timeout_handler(2000UL, ulwip_timeout_handler); + + ulwip_loop(); + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) { + ulwip_clear_tmo(); + + filename = env_get("bootfile"); + if (!filename) { + printf("no bootfile\n"); + return CMD_RET_FAILURE; + } + + eth_init(); /* activate u-boot eth dev */ + net_set_timeout_handler(20000UL, ulwip_timeout_handler); + lwip_tftp(image_load_addr, filename); + + ret = ulwip_loop(); + } + + return ret; +} + +static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + return do_lwip_dhcp(); +} +#endif /* CONFIG_CMD_DHCP */ + +#if defined(CONFIG_CMD_DNS) +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + char *name; + char *varname; + int LWIP_ERR_INPROGRESS = -5; + + if (argc == 1) + return CMD_RET_USAGE; + + name = argv[1]; + + if (argc == 3) + varname = argv[2]; + else + varname = NULL; + + uboot_lwip_init(); + + ret = ulwip_dns(name, varname); + if (ret == 0) + return CMD_RET_SUCCESS; + if (ret != LWIP_ERR_INPROGRESS) + return CMD_RET_FAILURE; + + net_set_timeout_handler(1000UL, ulwip_timeout_handler); + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_DNS */ + +static struct cmd_tbl cmds[] = { + U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""), + U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, + "initialize lwip stack", ""), +#if defined(CONFIG_CMD_LWIP_PING) + U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, + "send ICMP ECHO_REQUEST to network host", + "pingAddress"), +#endif +#if defined(CONFIG_CMD_WGET) + U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""), +#endif +#if defined(CONFIG_CMD_TFTPBOOT) + U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp, + "boot image via network using TFTP protocol\n", + "[loadAddress] [[hostIPaddr:]bootfilename]"), +#endif +#if defined(CONFIG_CMD_DHCP) + U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp, + "boot image via network using DHCP/TFTP protocol", + ""), +#endif +#if defined(CONFIG_CMD_DNS) + U_BOOT_CMD_MKENT(dns, 3, 0, do_lwip_dns, + "lookup dns name [and store address at variable]", + ""), +#endif +}; + +static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct cmd_tbl *cp; + + cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds)); + + argc--; + argv++; + + if (cp == NULL || 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( + lwip, 4, 1, do_ops, + "LWIP sub system", + "info - display info\n" + "init - init LWIP\n" + "ping addr - pingAddress\n" + "wget http://IPadress/url/%5Cn" + "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n" + "dhcp - boot image via network using DHCP/TFTP protocol\n" + ); + +/* Old command kept for compatibility. Same as 'mmc info' */ +U_BOOT_CMD( + lwipinfo, 1, 0, do_lwip_info, + "display LWIP info", + "- display LWIP stack info" +);

On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 2 + lib/lwip/cmd-lwip.c | 308 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 lib/lwip/cmd-lwip.c
Reviewed-by: Simon Glass sjg@chromium.org
But this should go in cmd/

Hi Maxim
On Wed, Aug 02, 2023 at 08:06:56PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 2 +
+#include "apps/dns/lwip-dns.h" +#include "apps/ping/lwip_ping.h" +#include "ulwip.h"
+extern int uboot_lwip_init(void); +extern int uboot_lwip_loop_is_done(void);
Can't we have these properly defined in .h files?
+static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- printf("TBD: %s\n", __func__);
This is not an RFC, what's missing from fetching at least something meaningful? E.g the lwip version?
- return CMD_RET_SUCCESS;
+}
+static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- if (!uboot_lwip_init())
return CMD_RET_SUCCESS;
- return CMD_RET_FAILURE;
+}
+static int lwip_empty_tmo(void) { return 0; }; +int (*ulwip_tmo)(void) = lwip_empty_tmo; +void ulwip_set_tmo(int (*tmo)(void)) +{
- ulwip_tmo = tmo;
+}
+static void ulwip_clear_tmo(void) +{
- ulwip_tmo = lwip_empty_tmo;
+}
+static void ulwip_timeout_handler(void) +{
- eth_halt();
- ulwip_tmo();
- net_set_state(NETLOOP_FAIL); /* we did not get the reply */
I am not sure what I am reading here. You use callbacks a few lines above to set a timeout function. But only set it for dhcp. On top of that the function for DHCP has a case for a *successful* asignment of ip addresses. Why are we setting the state to fail? And why are we complicating this by assigning and removing callbacks if it's only used for dhcp?
- ulwip_loop_set(0);
+}
+static int ulwip_loop(void) +{
- ulwip_loop_set(1);
- if (net_loop(LWIP) < 0) {
ulwip_loop_set(0);
return CMD_RET_FAILURE;
- }
- ulwip_loop_set(0);
both of the cases are using ulwip_loop_set(0). Rewrite this with a ret value and dont duplicate the function calls
- return CMD_RET_SUCCESS;
+}
+#if defined(CONFIG_CMD_PING) +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- if (argc < 2) {
printf("argc = %d, error\n", argc);
return CMD_RET_USAGE;
- }
- uboot_lwip_init();
- eth_init(); /* activate u-boot eth dev */
eth_init() can fail
- printf("Using %s device\n", eth_get_name());
- printf("pinging addr: %s\n", argv[1]);
- net_set_timeout_handler(1000UL, ulwip_timeout_handler);
I think it's cleaner to use timeout functions per case instead of carryi ng around that callback mess
- if (lwip_ping_init(argv[1])) {
printf("ping init fail\n");
return CMD_RET_FAILURE;
- }
- ping_send_now();
- return ulwip_loop();
+} +#endif /* CONFIG_CMD_PING */
+#if defined(CONFIG_CMD_WGET) +extern int lwip_wget(ulong addr, char *url);
+int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- char *url;
- if (argc < 2) {
printf("argc = %d, error\n", argc);
return CMD_RET_USAGE;
- }
- url = argv[1];
- uboot_lwip_init();
uboot_lwip_init() needs a rework here. It prints error messages and doesn't return an error code. You need error checking on the entire function
- eth_init(); /* activate u-boot eth dev */
- lwip_wget(image_load_addr, url);
- return ulwip_loop();
+} +#endif
+#if defined(CONFIG_CMD_TFTPBOOT) +extern int lwip_tftp(ulong addr, char *filename);
+int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- char *filename;
- ulong addr;
- char *end;
- int ret;
- switch (argc) {
- case 1:
filename = 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;
filename = env_get("bootfile");
} else {
filename = argv[1];
}
break;
- case 3:
image_load_addr = hextoul(argv[1], NULL);
filename = argv[2];
break;
- default:
return CMD_RET_USAGE;
- }
- uboot_lwip_init();
- eth_init(); /* activate u-boot eth dev */
similar comments here, check return codes etc
- ret = lwip_tftp(image_load_addr, filename);
filename can be NULL
- if (ret)
return ret;
- return ulwip_loop();
+} +#endif /* CONFIG_CMD_TFTPBOOT */
+#if defined(CONFIG_CMD_DHCP) +extern int ulwip_dhcp(void);
+int do_lwip_dhcp(void) +{
- int ret;
- char *filename;
- uboot_lwip_init();
- ret = ulwip_dhcp();
- net_set_timeout_handler(2000UL, ulwip_timeout_handler);
- ulwip_loop();
- if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) {
ulwip_clear_tmo();
filename = env_get("bootfile");
if (!filename) {
printf("no bootfile\n");
return CMD_RET_FAILURE;
Why is this a failure? You just have the tftp command enabled but dont want to download anything
}
eth_init(); /* activate u-boot eth dev */
return codes etc
net_set_timeout_handler(20000UL, ulwip_timeout_handler);
lwip_tftp(image_load_addr, filename);
ret = ulwip_loop();
- }
- return ret;
+}
+static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- return do_lwip_dhcp();
+} +#endif /* CONFIG_CMD_DHCP */
+#if defined(CONFIG_CMD_DNS) +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- int ret;
- char *name;
- char *varname;
- int LWIP_ERR_INPROGRESS = -5;
This should be a define in lwip somewhere if its a documented value. If not drop the caps
- if (argc == 1)
return CMD_RET_USAGE;
- name = argv[1];
- if (argc == 3)
varname = argv[2];
- else
varname = NULL;
- uboot_lwip_init();
- ret = ulwip_dns(name, varname);
- if (ret == 0)
return CMD_RET_SUCCESS;
- if (ret != LWIP_ERR_INPROGRESS)
return CMD_RET_FAILURE;
- net_set_timeout_handler(1000UL, ulwip_timeout_handler);
- return ulwip_loop();
+} +#endif /* CONFIG_CMD_DNS */
+static struct cmd_tbl cmds[] = {
- U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""),
- U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init,
"initialize lwip stack", ""),
+#if defined(CONFIG_CMD_LWIP_PING)
- U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping,
"send ICMP ECHO_REQUEST to network host",
"pingAddress"),
+#endif +#if defined(CONFIG_CMD_WGET)
- U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""),
+#endif +#if defined(CONFIG_CMD_TFTPBOOT)
- U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp,
"boot image via network using TFTP protocol\n",
"[loadAddress] [[hostIPaddr:]bootfilename]"),
+#endif +#if defined(CONFIG_CMD_DHCP)
- U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp,
"boot image via network using DHCP/TFTP protocol",
""),
+#endif +#if defined(CONFIG_CMD_DNS)
- U_BOOT_CMD_MKENT(dns, 3, 0, do_lwip_dns,
"lookup dns name [and store address at variable]",
""),
+#endif +};
+static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- struct cmd_tbl *cp;
- cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds));
- argc--;
- argv++;
- if (cp == NULL || 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(
- lwip, 4, 1, do_ops,
- "LWIP sub system",
- "info - display info\n"
- "init - init LWIP\n"
- "ping addr - pingAddress\n"
- "wget http://IPadress/url/%5Cn"
- "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n"
- "dhcp - boot image via network using DHCP/TFTP protocol\n"
- );
+/* Old command kept for compatibility. Same as 'mmc info' */ +U_BOOT_CMD(
- lwipinfo, 1, 0, do_lwip_info,
- "display LWIP info",
- "- display LWIP stack info"
+);
2.30.2
Regards /Ilias

On Thu, 3 Aug 2023 at 14:56, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Maxim
On Wed, Aug 02, 2023 at 08:06:56PM +0600, Maxim Uvarov wrote:
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
lib/lwip/Makefile | 2 +
+#include "apps/dns/lwip-dns.h" +#include "apps/ping/lwip_ping.h" +#include "ulwip.h"
+extern int uboot_lwip_init(void); +extern int uboot_lwip_loop_is_done(void);
Can't we have these properly defined in .h files?
+static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
printf("TBD: %s\n", __func__);
This is not an RFC, what's missing from fetching at least something meaningful? E.g the lwip version?
LWIP has statistics if it's enabled. (If compiled in.) So I think there might be a version, configured IP addresses, statistics, or some configuration (bond, bridge, vlan, ppp). Might be some network apps running in background (netcon server, htttp server). Maybe for the first version it's reasonable to drop an empty function and then add it with some function.
return CMD_RET_SUCCESS;
+}
+static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
if (!uboot_lwip_init())
return CMD_RET_SUCCESS;
return CMD_RET_FAILURE;
+}
+static int lwip_empty_tmo(void) { return 0; }; +int (*ulwip_tmo)(void) = lwip_empty_tmo; +void ulwip_set_tmo(int (*tmo)(void)) +{
ulwip_tmo = tmo;
+}
+static void ulwip_clear_tmo(void) +{
ulwip_tmo = lwip_empty_tmo;
+}
+static void ulwip_timeout_handler(void) +{
eth_halt();
ulwip_tmo();
net_set_state(NETLOOP_FAIL); /* we did not get the reply */
I am not sure what I am reading here. You use callbacks a few lines above to set a timeout function. But only set it for dhcp. On top of that the function for DHCP has a case for a *successful* asignment of ip addresses. Why are we setting the state to fail? And why are we complicating this by assigning and removing callbacks if it's only used for dhcp?
I need two time out callbacks here: 1. Trap rx polling loop if lwip application works too long. It is used when code goes to net_loop() code to poll rx packets and nobody interrupts this loop. This timeout is used for all cmds (lwip apps).
2. Trap lwip application after specific timeout and then check some state. That is case for DHCP, where LWIP DHCP does not have callback for changing state. And I need to know when to stop polling loop.
ulwip_loop_set(0);
+}
+static int ulwip_loop(void) +{
ulwip_loop_set(1);
if (net_loop(LWIP) < 0) {
ulwip_loop_set(0);
return CMD_RET_FAILURE;
}
ulwip_loop_set(0);
both of the cases are using ulwip_loop_set(0). Rewrite this with a ret value and dont duplicate the function calls
ok.
return CMD_RET_SUCCESS;
+}
+#if defined(CONFIG_CMD_PING) +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
if (argc < 2) {
printf("argc = %d, error\n", argc);
return CMD_RET_USAGE;
}
uboot_lwip_init();
eth_init(); /* activate u-boot eth dev */
eth_init() can fail
printf("Using %s device\n", eth_get_name());
printf("pinging addr: %s\n", argv[1]);
net_set_timeout_handler(1000UL, ulwip_timeout_handler);
I think it's cleaner to use timeout functions per case instead of carryi ng around that callback mess
it's timeout varian 1 which I described before.
if (lwip_ping_init(argv[1])) {
printf("ping init fail\n");
return CMD_RET_FAILURE;
}
ping_send_now();
return ulwip_loop();
+} +#endif /* CONFIG_CMD_PING */
+#if defined(CONFIG_CMD_WGET) +extern int lwip_wget(ulong addr, char *url);
+int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
char *url;
if (argc < 2) {
printf("argc = %d, error\n", argc);
return CMD_RET_USAGE;
}
url = argv[1];
uboot_lwip_init();
uboot_lwip_init() needs a rework here. It prints error messages and doesn't return an error code. You need error checking on the entire function
eth_init(); /* activate u-boot eth dev */
lwip_wget(image_load_addr, url);
return ulwip_loop();
+} +#endif
+#if defined(CONFIG_CMD_TFTPBOOT) +extern int lwip_tftp(ulong addr, char *filename);
+int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
char *filename;
ulong addr;
char *end;
int ret;
switch (argc) {
case 1:
filename = 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;
filename = env_get("bootfile");
} else {
filename = argv[1];
}
break;
case 3:
image_load_addr = hextoul(argv[1], NULL);
filename = argv[2];
break;
default:
return CMD_RET_USAGE;
}
uboot_lwip_init();
eth_init(); /* activate u-boot eth dev */
similar comments here, check return codes etc
ret = lwip_tftp(image_load_addr, filename);
filename can be NULL
if (ret)
return ret;
return ulwip_loop();
+} +#endif /* CONFIG_CMD_TFTPBOOT */
+#if defined(CONFIG_CMD_DHCP) +extern int ulwip_dhcp(void);
+int do_lwip_dhcp(void) +{
int ret;
char *filename;
uboot_lwip_init();
ret = ulwip_dhcp();
net_set_timeout_handler(2000UL, ulwip_timeout_handler);
ulwip_loop();
if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) {
ulwip_clear_tmo();
filename = env_get("bootfile");
if (!filename) {
printf("no bootfile\n");
return CMD_RET_FAILURE;
Why is this a failure? You just have the tftp command enabled but dont want to download anything
thanks, if dhcp did not return filename, but only IP, then nothing to
download. It's not an error.
}
eth_init(); /* activate u-boot eth dev */
return codes etc
net_set_timeout_handler(20000UL, ulwip_timeout_handler);
lwip_tftp(image_load_addr, filename);
ret = ulwip_loop();
}
return ret;
+}
+static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
return do_lwip_dhcp();
+} +#endif /* CONFIG_CMD_DHCP */
+#if defined(CONFIG_CMD_DNS) +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
int ret;
char *name;
char *varname;
int LWIP_ERR_INPROGRESS = -5;
This should be a define in lwip somewhere if its a documented value. If not drop the caps
lib/lwip/lwip-external/src/include/lwip/err.h /** Operation in progress */
ERR_INPROGRESS = -5,
Inside ./lib/lwip/cmd-lwip.c I do not include any lwip headers. But here I need to check the return value. The idea here is lwip can cache few dns requests. If request comes from cache then we can just exist with CMD_RET_SUCCESS. If there is cache mismatch then we need to go to ulwip_loop() to send request to the netwrok.
if (argc == 1)
return CMD_RET_USAGE;
name = argv[1];
if (argc == 3)
varname = argv[2];
else
varname = NULL;
uboot_lwip_init();
ret = ulwip_dns(name, varname);
if (ret == 0)
return CMD_RET_SUCCESS;
if (ret != LWIP_ERR_INPROGRESS)
return CMD_RET_FAILURE;
net_set_timeout_handler(1000UL, ulwip_timeout_handler);
return ulwip_loop();
+} +#endif /* CONFIG_CMD_DNS */
+static struct cmd_tbl cmds[] = {
U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""),
U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init,
"initialize lwip stack", ""),
+#if defined(CONFIG_CMD_LWIP_PING)
U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping,
"send ICMP ECHO_REQUEST to network host",
"pingAddress"),
+#endif +#if defined(CONFIG_CMD_WGET)
U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""),
+#endif +#if defined(CONFIG_CMD_TFTPBOOT)
U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp,
"boot image via network using TFTP protocol\n",
"[loadAddress] [[hostIPaddr:]bootfilename]"),
+#endif +#if defined(CONFIG_CMD_DHCP)
U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp,
"boot image via network using DHCP/TFTP protocol",
""),
+#endif +#if defined(CONFIG_CMD_DNS)
U_BOOT_CMD_MKENT(dns, 3, 0, do_lwip_dns,
"lookup dns name [and store address at variable]",
""),
+#endif +};
+static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
struct cmd_tbl *cp;
cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds));
argc--;
argv++;
if (cp == NULL || 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(
lwip, 4, 1, do_ops,
"LWIP sub system",
"info - display info\n"
"init - init LWIP\n"
"ping addr - pingAddress\n"
"wget http://IPadress/url/\n"
"tftp [loadAddress] [[hostIPaddr:]bootfilename]\n"
"dhcp - boot image via network using DHCP/TFTP protocol\n"
);
+/* Old command kept for compatibility. Same as 'mmc info' */ +U_BOOT_CMD(
lwipinfo, 1, 0, do_lwip_info,
"display LWIP info",
"- display LWIP stack info"
+);
2.30.2
Regards /Ilias
Thanks Ilias, If I did not reply for any comment/question then it means that it will be fixed in new version.
BR, Maxim.

Hi Maxim
[...]
+static int lwip_empty_tmo(void) { return 0; }; +int (*ulwip_tmo)(void) = lwip_empty_tmo; +void ulwip_set_tmo(int (*tmo)(void)) +{
ulwip_tmo = tmo;
+}
+static void ulwip_clear_tmo(void) +{
ulwip_tmo = lwip_empty_tmo;
+}
+static void ulwip_timeout_handler(void) +{
eth_halt();
ulwip_tmo();
net_set_state(NETLOOP_FAIL); /* we did not get the reply */
I am not sure what I am reading here. You use callbacks a few lines above to set a timeout function. But only set it for dhcp. On top of that the function for DHCP has a case for a *successful* asignment of ip addresses. Why are we setting the state to fail? And why are we complicating this by assigning and removing callbacks if it's only used for dhcp?
I need two time out callbacks here:
- Trap rx polling loop if lwip application works too long. It is used when
code goes to net_loop() code to poll rx packets and nobody interrupts this loop. This timeout is used for all cmds (lwip apps).
- Trap lwip application after specific timeout and then check some state.
That is case for DHCP, where LWIP DHCP does not have callback for changing state. And I need to know when to stop polling loop.
Yes but is there a reason to reassing those callback to a function ptr? Just define them and use them
[...]
ret = ulwip_dhcp();
net_set_timeout_handler(2000UL, ulwip_timeout_handler);
ulwip_loop();
if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) {
ulwip_clear_tmo();
filename = env_get("bootfile");
if (!filename) {
printf("no bootfile\n");
return CMD_RET_FAILURE;
Why is this a failure? You just have the tftp command enabled but dont want to download anything
thanks, if dhcp did not return filename, but only IP, then nothing to
download. It's not an error.
Yes but downloading a file is not mandatory, it depends on a DHCP option. If you want to emulate this behaviour, you need to fail only if 'bootfile' is set but cant be downloaded.
}
Regards /Ilias

On Wed, 9 Aug 2023 at 00:13, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Maxim
[...]
+static int lwip_empty_tmo(void) { return 0; }; +int (*ulwip_tmo)(void) = lwip_empty_tmo; +void ulwip_set_tmo(int (*tmo)(void)) +{
ulwip_tmo = tmo;
+}
+static void ulwip_clear_tmo(void) +{
ulwip_tmo = lwip_empty_tmo;
+}
+static void ulwip_timeout_handler(void) +{
eth_halt();
ulwip_tmo();
net_set_state(NETLOOP_FAIL); /* we did not get the reply */
I am not sure what I am reading here. You use callbacks a few lines
above
to set a timeout function. But only set it for dhcp. On top of that
the
function for DHCP has a case for a *successful* asignment of ip
addresses.
Why are we setting the state to fail? And why are we complicating this
by
assigning and removing callbacks if it's only used for dhcp?
I need two time out callbacks here:
- Trap rx polling loop if lwip application works too long. It is used
when
code goes to net_loop() code to poll rx packets and nobody interrupts this loop. This timeout is used for all cmds (lwip apps).
- Trap lwip application after specific timeout and then check some
state.
That is case for DHCP, where LWIP DHCP does not have callback for changing state. And I need to know when to stop polling
loop.
Yes but is there a reason to reassing those callback to a function ptr? Just define them and use them
I added a more detailed description to this time out function for the next version. The reason here is the following - there is no scheduler. cmd just starts lwip application. But in fact it does only initialization and in most cases you need to go to the polling loop. Then after polling loop you need to return to 1. back to U-boot console. or 2. back to lwip application to print some message, or get some lwip state or run something else. This return is done with this timeout callback. Which looks logical to me to have a timeout callback in the same file as application code.
[...]
ret = ulwip_dhcp();
net_set_timeout_handler(2000UL, ulwip_timeout_handler);
ulwip_loop();
if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) {
ulwip_clear_tmo();
filename = env_get("bootfile");
if (!filename) {
printf("no bootfile\n");
return CMD_RET_FAILURE;
Why is this a failure? You just have the tftp command enabled but dont want to download anything
thanks, if dhcp did not return filename, but only IP, then nothing to
download. It's not an error.
Yes but downloading a file is not mandatory, it depends on a DHCP option. If you want to emulate this behaviour, you need to fail only if 'bootfile' is set but cant be downloaded.
}
Regards /Ilias

Replace original commands: ping, tftp, dhcp and wget.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- boot/bootmeth_efi.c | 2 +- boot/bootmeth_pxe.c | 2 +- cmd/net.c | 86 +++++---------------------------------------- cmd/pxe.c | 2 +- include/net.h | 8 +++-- include/net/lwip.h | 5 +++ lib/Makefile | 2 -- lib/lwip/ulwip.h | 9 +++++ 8 files changed, 31 insertions(+), 85 deletions(-) create mode 100644 include/net/lwip.h create mode 100644 lib/lwip/ulwip.h
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index af31fbfc85..83334991bb 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -340,7 +340,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (!bflow->fdt_fname) return log_msg_ret("fil", -ENOMEM);
- if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) { + if (!do_lwip_tftp(&cmdtp, 0, 3, tftp_argv)) { bflow->fdt_size = env_get_hex("filesize", 0); bflow->fdt_addr = fdt_addr; } else { diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index ce986bd260..881d2167a6 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -123,7 +123,7 @@ static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow, tftp_argv[1] = file_addr; tftp_argv[2] = (void *)file_path;
- if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(&size); if (ret) diff --git a/cmd/net.c b/cmd/net.c index d407d8320a..dc5a114309 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -22,6 +22,7 @@ #include <net/udp.h> #include <net/sntp.h> #include <net/ncsi.h> +#include <net/lwip.h>
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
@@ -40,19 +41,9 @@ U_BOOT_CMD( #endif
#ifdef CONFIG_CMD_TFTPBOOT -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - int ret; - - bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); - ret = netboot_common(TFTPGET, cmdtp, argc, argv); - bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); - return ret; -} - #if IS_ENABLED(CONFIG_IPV6) U_BOOT_CMD( - tftpboot, 4, 1, do_tftpb, + tftpboot, 4, 1, do_lwip_tftp, "boot image via network using TFTP protocol\n" "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " "with [] brackets", @@ -60,7 +51,7 @@ U_BOOT_CMD( ); #else U_BOOT_CMD( - tftpboot, 3, 1, do_tftpb, + tftpboot, 3, 1, do_lwip_tftp, "load file via network using TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]" ); @@ -139,7 +130,7 @@ U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6, static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - return netboot_common(DHCP, cmdtp, argc, argv); + return do_lwip_dhcp(); }
U_BOOT_CMD( @@ -196,13 +187,11 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_WGET) -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) -{ - return netboot_common(WGET, cmdtp, argc, argv); -} +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]);
U_BOOT_CMD( - wget, 3, 1, do_wget, + wget, 3, 1, do_lwip_wget, "boot image via network using HTTP protocol", "[loadAddress] [[hostIPaddr:]path and image name]" ); @@ -456,28 +445,8 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, }
#if defined(CONFIG_CMD_PING) -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (argc < 2) - return CMD_RET_USAGE; - - net_ping_ip = string_to_ip(argv[1]); - if (net_ping_ip.s_addr == 0) - return CMD_RET_USAGE; - - if (net_loop(PING) < 0) { - printf("ping failed; host %s is not alive\n", argv[1]); - return CMD_RET_FAILURE; - } - - printf("host %s is alive\n", argv[1]); - - return CMD_RET_SUCCESS; -} - U_BOOT_CMD( - ping, 2, 1, do_ping, + ping, 2, 1, do_lwip_ping, "send ICMP ECHO_REQUEST to network host", "pingAddress" ); @@ -601,45 +570,8 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_DNS) -int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - if (argc == 1) - return CMD_RET_USAGE; - - /* - * We should check for a valid hostname: - * - Each label must be between 1 and 63 characters long - * - the entire hostname has a maximum of 255 characters - * - only the ASCII letters 'a' through 'z' (case-insensitive), - * the digits '0' through '9', and the hyphen - * - cannot begin or end with a hyphen - * - no other symbols, punctuation characters, or blank spaces are - * permitted - * but hey - this is a minimalist implmentation, so only check length - * and let the name server deal with things. - */ - if (strlen(argv[1]) >= 255) { - printf("dns error: hostname too long\n"); - return CMD_RET_FAILURE; - } - - net_dns_resolve = argv[1]; - - if (argc == 3) - net_dns_env_var = argv[2]; - else - net_dns_env_var = NULL; - - if (net_loop(DNS) < 0) { - printf("dns lookup of %s failed, check setup\n", argv[1]); - return CMD_RET_FAILURE; - } - - return CMD_RET_SUCCESS; -} - U_BOOT_CMD( - dns, 3, 1, do_dns, + dns, 3, 1, do_lwip_dns, "lookup the IP of a hostname", "hostname [envvar]" ); diff --git a/cmd/pxe.c b/cmd/pxe.c index 677142520b..a31fbd7e40 100644 --- a/cmd/pxe.c +++ b/cmd/pxe.c @@ -42,7 +42,7 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path, num_args = 3; }
- if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv)) + if (do_lwip_tftp(ctx->cmdtp, 0, num_args, tftp_argv)) return -ENOENT;
ret = pxe_get_file_size(sizep); diff --git a/include/net.h b/include/net.h index e254df7d7f..de7baeb121 100644 --- a/include/net.h +++ b/include/net.h @@ -54,8 +54,10 @@ struct in_addr { __be32 s_addr; };
+int do_lwip_dhcp(void); + /** - * do_tftpb - Run the tftpboot command + * do_lwip_tftp - Run the tftpboot command * * @cmdtp: Command information for tftpboot * @flag: Command flags (CMD_FLAG_...) @@ -63,7 +65,7 @@ struct in_addr { * @argv: List of arguments * Return: result (see enum command_ret_t) */ -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
/** * dhcp_run() - Run DHCP on the current ethernet device @@ -514,7 +516,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP, - WOL, UDP, NCSI, WGET, RS + WOL, UDP, NCSI, WGET, RS, LWIP };
extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..6686a52bfc --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,5 @@ + +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); diff --git a/lib/Makefile b/lib/Makefile index 598b5755dd..414f171e74 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -93,8 +93,6 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
-obj-y += 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/ulwip.h b/lib/lwip/ulwip.h new file mode 100644 index 0000000000..11ca52aa1f --- /dev/null +++ b/lib/lwip/ulwip.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +int ulwip_enabled(void); +int ulwip_in_loop(void); +int ulwip_loop_set(int loop); +int ulwip_exit(int err); +int uboot_lwip_poll(void); +int ulwip_app_get_err(void); +void ulwip_set_tmo(int (*tmo)(void));

Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Replace original commands: ping, tftp, dhcp and wget.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
boot/bootmeth_efi.c | 2 +- boot/bootmeth_pxe.c | 2 +- cmd/net.c | 86 +++++---------------------------------------- cmd/pxe.c | 2 +- include/net.h | 8 +++-- include/net/lwip.h | 5 +++ lib/Makefile | 2 -- lib/lwip/ulwip.h | 9 +++++ 8 files changed, 31 insertions(+), 85 deletions(-) create mode 100644 include/net/lwip.h create mode 100644 lib/lwip/ulwip.h
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index af31fbfc85..83334991bb 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -340,7 +340,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (!bflow->fdt_fname) return log_msg_ret("fil", -ENOMEM);
if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
if (!do_lwip_tftp(&cmdtp, 0, 3, tftp_argv)) {
For these two (efi and pxe) I would really like to avoid passing a command, as you can probably tell. Is there a direct function we can call with the appropriate ages?
bflow->fdt_size = env_get_hex("filesize", 0); bflow->fdt_addr = fdt_addr; } else {
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index ce986bd260..881d2167a6 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -123,7 +123,7 @@ static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow, tftp_argv[1] = file_addr; tftp_argv[2] = (void *)file_path;
if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(&size); if (ret)
diff --git a/cmd/net.c b/cmd/net.c index d407d8320a..dc5a114309 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -22,6 +22,7 @@ #include <net/udp.h> #include <net/sntp.h> #include <net/ncsi.h> +#include <net/lwip.h>
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
@@ -40,19 +41,9 @@ U_BOOT_CMD( #endif
#ifdef CONFIG_CMD_TFTPBOOT -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{
int ret;
bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
ret = netboot_common(TFTPGET, cmdtp, argc, argv);
bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
Please don't remove these...we need the timing
return ret;
-}
#if IS_ENABLED(CONFIG_IPV6) U_BOOT_CMD(
tftpboot, 4, 1, do_tftpb,
tftpboot, 4, 1, do_lwip_tftp, "boot image via network using TFTP protocol\n" "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " "with [] brackets",
@@ -60,7 +51,7 @@ U_BOOT_CMD( ); #else U_BOOT_CMD(
tftpboot, 3, 1, do_tftpb,
tftpboot, 3, 1, do_lwip_tftp, "load file via network using TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]"
); @@ -139,7 +130,7 @@ U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6, static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
return netboot_common(DHCP, cmdtp, argc, argv);
return do_lwip_dhcp();
}
U_BOOT_CMD( @@ -196,13 +187,11 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_WGET) -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) -{
return netboot_common(WGET, cmdtp, argc, argv);
-} +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
U_BOOT_CMD(
wget, 3, 1, do_wget,
wget, 3, 1, do_lwip_wget, "boot image via network using HTTP protocol", "[loadAddress] [[hostIPaddr:]path and image name]"
); @@ -456,28 +445,8 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, }
#if defined(CONFIG_CMD_PING) -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
-{
if (argc < 2)
return CMD_RET_USAGE;
net_ping_ip = string_to_ip(argv[1]);
if (net_ping_ip.s_addr == 0)
return CMD_RET_USAGE;
if (net_loop(PING) < 0) {
printf("ping failed; host %s is not alive\n", argv[1]);
return CMD_RET_FAILURE;
}
printf("host %s is alive\n", argv[1]);
Does lwip print the same messages? That would be useful information for the commit message.
return CMD_RET_SUCCESS;
-}
U_BOOT_CMD(
ping, 2, 1, do_ping,
ping, 2, 1, do_lwip_ping, "send ICMP ECHO_REQUEST to network host", "pingAddress"
); @@ -601,45 +570,8 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_DNS) -int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{
if (argc == 1)
return CMD_RET_USAGE;
/*
* We should check for a valid hostname:
* - Each label must be between 1 and 63 characters long
* - the entire hostname has a maximum of 255 characters
* - only the ASCII letters 'a' through 'z' (case-insensitive),
* the digits '0' through '9', and the hyphen
* - cannot begin or end with a hyphen
* - no other symbols, punctuation characters, or blank spaces are
* permitted
* but hey - this is a minimalist implmentation, so only check length
* and let the name server deal with things.
*/
if (strlen(argv[1]) >= 255) {
printf("dns error: hostname too long\n");
return CMD_RET_FAILURE;
}
Some info in the commit message would be helpful here. People are left to guess why you have removed this code.
net_dns_resolve = argv[1];
if (argc == 3)
net_dns_env_var = argv[2];
else
net_dns_env_var = NULL;
if (net_loop(DNS) < 0) {
printf("dns lookup of %s failed, check setup\n", argv[1]);
return CMD_RET_FAILURE;
}
return CMD_RET_SUCCESS;
-}
U_BOOT_CMD(
dns, 3, 1, do_dns,
dns, 3, 1, do_lwip_dns, "lookup the IP of a hostname", "hostname [envvar]"
); diff --git a/cmd/pxe.c b/cmd/pxe.c index 677142520b..a31fbd7e40 100644 --- a/cmd/pxe.c +++ b/cmd/pxe.c @@ -42,7 +42,7 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path, num_args = 3; }
if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv))
if (do_lwip_tftp(ctx->cmdtp, 0, num_args, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(sizep);
diff --git a/include/net.h b/include/net.h index e254df7d7f..de7baeb121 100644 --- a/include/net.h +++ b/include/net.h @@ -54,8 +54,10 @@ struct in_addr { __be32 s_addr; };
+int do_lwip_dhcp(void);
/**
- do_tftpb - Run the tftpboot command
- do_lwip_tftp - Run the tftpboot command
- @cmdtp: Command information for tftpboot
- @flag: Command flags (CMD_FLAG_...)
@@ -63,7 +65,7 @@ struct in_addr {
- @argv: List of arguments
- Return: result (see enum command_ret_t)
*/ -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
comment!! Also please can you add a direct function that doesn't need to parse args? Basically we want to be able to turn of CONFIG_CMDLINE and have things still work.
/**
- dhcp_run() - Run DHCP on the current ethernet device
@@ -514,7 +516,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP,
WOL, UDP, NCSI, WGET, RS
WOL, UDP, NCSI, WGET, RS, LWIP
};
extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..6686a52bfc --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,5 @@
+int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
diff --git a/lib/Makefile b/lib/Makefile index 598b5755dd..414f171e74 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -93,8 +93,6 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
-obj-y += 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/ulwip.h b/lib/lwip/ulwip.h new file mode 100644 index 0000000000..11ca52aa1f --- /dev/null +++ b/lib/lwip/ulwip.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+int ulwip_enabled(void); +int ulwip_in_loop(void);
Please add a full comment for each exported function.
+int ulwip_loop_set(int loop); +int ulwip_exit(int err); +int uboot_lwip_poll(void); +int ulwip_app_get_err(void);
+void ulwip_set_tmo(int (*tmo)(void));
2.30.2
Regards, Simon

On Thu, 3 Aug 2023 at 03:32, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Replace original commands: ping, tftp, dhcp and wget.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
boot/bootmeth_efi.c | 2 +- boot/bootmeth_pxe.c | 2 +- cmd/net.c | 86 +++++---------------------------------------- cmd/pxe.c | 2 +- include/net.h | 8 +++-- include/net/lwip.h | 5 +++ lib/Makefile | 2 -- lib/lwip/ulwip.h | 9 +++++ 8 files changed, 31 insertions(+), 85 deletions(-) create mode 100644 include/net/lwip.h create mode 100644 lib/lwip/ulwip.h
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index af31fbfc85..83334991bb 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -340,7 +340,7 @@ static int distro_efi_read_bootflow_net(struct
bootflow *bflow)
if (!bflow->fdt_fname) return log_msg_ret("fil", -ENOMEM);
if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
if (!do_lwip_tftp(&cmdtp, 0, 3, tftp_argv)) {
For these two (efi and pxe) I would really like to avoid passing a command, as you can probably tell. Is there a direct function we can call with the appropriate ages?
yes, just lwip_tftp(addr, name) make code simpler here. If that's ok to replace, then I will do that.
bflow->fdt_size = env_get_hex("filesize", 0); bflow->fdt_addr = fdt_addr; } else {
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index ce986bd260..881d2167a6 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -123,7 +123,7 @@ static int extlinux_pxe_read_file(struct udevice
*dev, struct bootflow *bflow,
tftp_argv[1] = file_addr; tftp_argv[2] = (void *)file_path;
if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(&size); if (ret)
diff --git a/cmd/net.c b/cmd/net.c index d407d8320a..dc5a114309 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -22,6 +22,7 @@ #include <net/udp.h> #include <net/sntp.h> #include <net/ncsi.h> +#include <net/lwip.h>
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char *
const []);
@@ -40,19 +41,9 @@ U_BOOT_CMD( #endif
#ifdef CONFIG_CMD_TFTPBOOT -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const
argv[])
-{
int ret;
bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
ret = netboot_common(TFTPGET, cmdtp, argc, argv);
bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
Please don't remove these...we need the timing
bootstage_mark_name() is needed only for tft cmd? I.e. add this to function which parses arguments. Or it's also need to account time in pxe and efi?
return ret;
-}
#if IS_ENABLED(CONFIG_IPV6) U_BOOT_CMD(
tftpboot, 4, 1, do_tftpb,
tftpboot, 4, 1, do_lwip_tftp, "boot image via network using TFTP protocol\n" "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " "with [] brackets",
@@ -60,7 +51,7 @@ U_BOOT_CMD( ); #else U_BOOT_CMD(
tftpboot, 3, 1, do_tftpb,
tftpboot, 3, 1, do_lwip_tftp, "load file via network using TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]"
); @@ -139,7 +130,7 @@ U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6, static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) {
return netboot_common(DHCP, cmdtp, argc, argv);
return do_lwip_dhcp();
}
U_BOOT_CMD( @@ -196,13 +187,11 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_WGET) -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char *
const argv[])
-{
return netboot_common(WGET, cmdtp, argc, argv);
-} +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
U_BOOT_CMD(
wget, 3, 1, do_wget,
wget, 3, 1, do_lwip_wget, "boot image via network using HTTP protocol", "[loadAddress] [[hostIPaddr:]path and image name]"
); @@ -456,28 +445,8 @@ static int netboot_common(enum proto_t proto,
struct cmd_tbl *cmdtp, int argc,
}
#if defined(CONFIG_CMD_PING) -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
-{
if (argc < 2)
return CMD_RET_USAGE;
net_ping_ip = string_to_ip(argv[1]);
if (net_ping_ip.s_addr == 0)
return CMD_RET_USAGE;
if (net_loop(PING) < 0) {
printf("ping failed; host %s is not alive\n", argv[1]);
return CMD_RET_FAILURE;
}
printf("host %s is alive\n", argv[1]);
Does lwip print the same messages? That would be useful information for the commit message.
I tried to make messages 1 to 1 with original to pass validation tests.
return CMD_RET_SUCCESS;
-}
U_BOOT_CMD(
ping, 2, 1, do_ping,
ping, 2, 1, do_lwip_ping, "send ICMP ECHO_REQUEST to network host", "pingAddress"
); @@ -601,45 +570,8 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_DNS) -int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const
argv[])
-{
if (argc == 1)
return CMD_RET_USAGE;
/*
* We should check for a valid hostname:
* - Each label must be between 1 and 63 characters long
* - the entire hostname has a maximum of 255 characters
* - only the ASCII letters 'a' through 'z' (case-insensitive),
* the digits '0' through '9', and the hyphen
* - cannot begin or end with a hyphen
* - no other symbols, punctuation characters, or blank spaces
are
* permitted
* but hey - this is a minimalist implmentation, so only check
length
* and let the name server deal with things.
*/
if (strlen(argv[1]) >= 255) {
printf("dns error: hostname too long\n");
return CMD_RET_FAILURE;
}
Some info in the commit message would be helpful here. People are left to guess why you have removed this code.
ok.
net_dns_resolve = argv[1];
if (argc == 3)
net_dns_env_var = argv[2];
else
net_dns_env_var = NULL;
if (net_loop(DNS) < 0) {
printf("dns lookup of %s failed, check setup\n",
argv[1]);
return CMD_RET_FAILURE;
}
return CMD_RET_SUCCESS;
-}
U_BOOT_CMD(
dns, 3, 1, do_dns,
dns, 3, 1, do_lwip_dns, "lookup the IP of a hostname", "hostname [envvar]"
); diff --git a/cmd/pxe.c b/cmd/pxe.c index 677142520b..a31fbd7e40 100644 --- a/cmd/pxe.c +++ b/cmd/pxe.c @@ -42,7 +42,7 @@ static int do_get_tftp(struct pxe_context *ctx, const
char *file_path,
num_args = 3; }
if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv))
if (do_lwip_tftp(ctx->cmdtp, 0, num_args, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(sizep);
diff --git a/include/net.h b/include/net.h index e254df7d7f..de7baeb121 100644 --- a/include/net.h +++ b/include/net.h @@ -54,8 +54,10 @@ struct in_addr { __be32 s_addr; };
+int do_lwip_dhcp(void);
/**
- do_tftpb - Run the tftpboot command
- do_lwip_tftp - Run the tftpboot command
- @cmdtp: Command information for tftpboot
- @flag: Command flags (CMD_FLAG_...)
@@ -63,7 +65,7 @@ struct in_addr {
- @argv: List of arguments
- Return: result (see enum command_ret_t)
*/ -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const
argv[]);
+int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const
argv[]);
comment!! Also please can you add a direct function that doesn't need to parse args? Basically we want to be able to turn of CONFIG_CMDLINE and have things still work.
Yes, sure. There will be do_lwip_tftp() which parses args, and lwip_tftp(addr, name) without parsing args.
/**
- dhcp_run() - Run DHCP on the current ethernet device
@@ -514,7 +516,7 @@ extern int net_restart_wrap; /* Tried
all network devices */
enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS,
CDP,
NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP,
FASTBOOT_TCP,
WOL, UDP, NCSI, WGET, RS
WOL, UDP, NCSI, WGET, RS, LWIP
};
extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..6686a52bfc --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,5 @@
+int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
diff --git a/lib/Makefile b/lib/Makefile index 598b5755dd..414f171e74 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -93,8 +93,6 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
-obj-y += 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/ulwip.h b/lib/lwip/ulwip.h new file mode 100644 index 0000000000..11ca52aa1f --- /dev/null +++ b/lib/lwip/ulwip.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+int ulwip_enabled(void); +int ulwip_in_loop(void);
Please add a full comment for each exported function.
yes, sure.
+int ulwip_loop_set(int loop); +int ulwip_exit(int err); +int uboot_lwip_poll(void); +int ulwip_app_get_err(void);
+void ulwip_set_tmo(int (*tmo)(void));
2.30.2
Regards, Simon

Hi Maxim,
On Tue, 8 Aug 2023 at 08:06, Maxim Uvarov maxim.uvarov@linaro.org wrote:
On Thu, 3 Aug 2023 at 03:32, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Wed, 2 Aug 2023 at 08:11, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Replace original commands: ping, tftp, dhcp and wget.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
boot/bootmeth_efi.c | 2 +- boot/bootmeth_pxe.c | 2 +- cmd/net.c | 86 +++++---------------------------------------- cmd/pxe.c | 2 +- include/net.h | 8 +++-- include/net/lwip.h | 5 +++ lib/Makefile | 2 -- lib/lwip/ulwip.h | 9 +++++ 8 files changed, 31 insertions(+), 85 deletions(-) create mode 100644 include/net/lwip.h create mode 100644 lib/lwip/ulwip.h
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index af31fbfc85..83334991bb 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -340,7 +340,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (!bflow->fdt_fname) return log_msg_ret("fil", -ENOMEM);
if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
if (!do_lwip_tftp(&cmdtp, 0, 3, tftp_argv)) {
For these two (efi and pxe) I would really like to avoid passing a command, as you can probably tell. Is there a direct function we can call with the appropriate ages?
yes, just lwip_tftp(addr, name) make code simpler here. If that's ok to replace, then I will do that.
Yes please.
bflow->fdt_size = env_get_hex("filesize", 0); bflow->fdt_addr = fdt_addr; } else {
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index ce986bd260..881d2167a6 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -123,7 +123,7 @@ static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow, tftp_argv[1] = file_addr; tftp_argv[2] = (void *)file_path;
if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(&size); if (ret)
diff --git a/cmd/net.c b/cmd/net.c index d407d8320a..dc5a114309 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -22,6 +22,7 @@ #include <net/udp.h> #include <net/sntp.h> #include <net/ncsi.h> +#include <net/lwip.h>
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
@@ -40,19 +41,9 @@ U_BOOT_CMD( #endif
#ifdef CONFIG_CMD_TFTPBOOT -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{
int ret;
bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
ret = netboot_common(TFTPGET, cmdtp, argc, argv);
bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
Please don't remove these...we need the timing
bootstage_mark_name() is needed only for tft cmd? I.e. add this to function which parses arguments. Or it's also need to account time in pxe and efi?
We should really account for all time, as you say.
[..]
if (net_loop(PING) < 0) {
printf("ping failed; host %s is not alive\n", argv[1]);
return CMD_RET_FAILURE;
}
printf("host %s is alive\n", argv[1]);
Does lwip print the same messages? That would be useful information for the commit message.
I tried to make messages 1 to 1 with original to pass validation tests.
OK, please can you add that to the commit message?
Regards, Simon

After which to lwip variants of working apps we need to drop old code with all dependencies. This commit drop old wget command files.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/wget.h | 22 --- net/Makefile | 1 - net/net.c | 6 - net/wget.c | 440 --------------------------------------------- 4 files changed, 469 deletions(-) delete mode 100644 include/net/wget.h delete mode 100644 net/wget.c
diff --git a/include/net/wget.h b/include/net/wget.h deleted file mode 100644 index da0920de11..0000000000 --- a/include/net/wget.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Duncan Hare Copyright 2017 - */ - -/** - * wget_start() - begin wget - */ -void wget_start(void); - -enum wget_state { - WGET_CLOSED, - WGET_CONNECTING, - WGET_CONNECTED, - WGET_TRANSFERRING, - WGET_TRANSFERRED -}; - -#define DEBUG_WGET 0 /* Set to 1 for debug messages */ -#define SERVER_PORT 80 -#define WGET_RETRY_COUNT 30 -#define WGET_TIMEOUT 2000UL diff --git a/net/Makefile b/net/Makefile index 3e2d061338..82cbfb5cc0 100644 --- a/net/Makefile +++ b/net/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.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/net.c b/net/net.c index d98e51cb80..ee4a9f845a 100644 --- a/net/net.c +++ b/net/net.c @@ -109,7 +109,6 @@ #include <linux/compiler.h> #include <test/test.h> #include <net/tcp.h> -#include <net/wget.h> #include "arp.h" #include "bootp.h" #include "cdp.h" @@ -566,11 +565,6 @@ restart: nfs_start(); break; #endif -#if defined(CONFIG_CMD_WGET) - case WGET: - wget_start(); - break; -#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); diff --git a/net/wget.c b/net/wget.c deleted file mode 100644 index 2dbfeb1a1d..0000000000 --- a/net/wget.c +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * WGET/HTTP support driver based on U-BOOT's nfs.c - * Copyright Duncan Hare dh@synoia.com 2017 - */ - -#include <command.h> -#include <common.h> -#include <display_options.h> -#include <env.h> -#include <image.h> -#include <mapmem.h> -#include <net.h> -#include <net/tcp.h> -#include <net/wget.h> - -static const char bootfile1[] = "GET "; -static const char bootfile3[] = " HTTP/1.0\r\n\r\n"; -static const char http_eom[] = "\r\n\r\n"; -static const char http_ok[] = "200"; -static const char content_len[] = "Content-Length"; -static const char linefeed[] = "\r\n"; -static struct in_addr web_server_ip; -static int our_port; -static int wget_timeout_count; - -struct pkt_qd { - uchar *pkt; - unsigned int tcp_seq_num; - unsigned int len; -}; - -/* - * This is a control structure for out of order packets received. - * The actual packet bufers are in the kernel space, and are - * expected to be overwritten by the downloaded image. - */ -static struct pkt_qd pkt_q[PKTBUFSRX / 4]; -static int pkt_q_idx; -static unsigned long content_length; -static unsigned int packets; - -static unsigned int initial_data_seq_num; - -static enum wget_state current_wget_state; - -static char *image_url; -static unsigned int wget_timeout = WGET_TIMEOUT; - -static enum net_loop_state wget_loop_state; - -/* Timeout retry parameters */ -static u8 retry_action; /* actions for TCP retry */ -static unsigned int retry_tcp_ack_num; /* TCP retry acknowledge number*/ -static unsigned int retry_tcp_seq_num; /* TCP retry sequence number */ -static int retry_len; /* TCP retry length */ - -/** - * store_block() - store block in memory - * @src: source of data - * @offset: offset - * @len: length - */ -static inline int store_block(uchar *src, unsigned int offset, unsigned int len) -{ - ulong newsize = offset + len; - uchar *ptr; - - ptr = map_sysmem(image_load_addr + offset, len); - memcpy(ptr, src, len); - unmap_sysmem(ptr); - - if (net_boot_file_size < (offset + len)) - net_boot_file_size = newsize; - - return 0; -} - -/** - * wget_send_stored() - wget response dispatcher - * - * WARNING, This, and only this, is the place in wget.c where - * SEQUENCE NUMBERS are swapped between incoming (RX) - * and outgoing (TX). - * Procedure wget_handler() is correct for RX traffic. - */ -static void wget_send_stored(void) -{ - u8 action = retry_action; - int len = retry_len; - unsigned int tcp_ack_num = retry_tcp_seq_num + (len == 0 ? 1 : len); - unsigned int tcp_seq_num = retry_tcp_ack_num; - uchar *ptr, *offset; - - switch (current_wget_state) { - case WGET_CLOSED: - debug_cond(DEBUG_WGET, "wget: send SYN\n"); - current_wget_state = WGET_CONNECTING; - net_send_tcp_packet(0, SERVER_PORT, our_port, action, - tcp_seq_num, tcp_ack_num); - packets = 0; - break; - case WGET_CONNECTING: - pkt_q_idx = 0; - net_send_tcp_packet(0, SERVER_PORT, our_port, action, - tcp_seq_num, tcp_ack_num); - - ptr = net_tx_packet + net_eth_hdr_size() + - IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; - offset = ptr; - - memcpy(offset, &bootfile1, strlen(bootfile1)); - offset += strlen(bootfile1); - - memcpy(offset, image_url, strlen(image_url)); - offset += strlen(image_url); - - memcpy(offset, &bootfile3, strlen(bootfile3)); - offset += strlen(bootfile3); - net_send_tcp_packet((offset - ptr), SERVER_PORT, our_port, - TCP_PUSH, tcp_seq_num, tcp_ack_num); - current_wget_state = WGET_CONNECTED; - break; - case WGET_CONNECTED: - case WGET_TRANSFERRING: - case WGET_TRANSFERRED: - net_send_tcp_packet(0, SERVER_PORT, our_port, action, - tcp_seq_num, tcp_ack_num); - break; - } -} - -static void wget_send(u8 action, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, int len) -{ - retry_action = action; - retry_tcp_ack_num = tcp_ack_num; - retry_tcp_seq_num = tcp_seq_num; - retry_len = len; - - wget_send_stored(); -} - -void wget_fail(char *error_message, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, u8 action) -{ - printf("wget: Transfer Fail - %s\n", error_message); - net_set_timeout_handler(0, NULL); - wget_send(action, tcp_seq_num, tcp_ack_num, 0); -} - -void wget_success(u8 action, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, int len, int packets) -{ - printf("Packets received %d, Transfer Successful\n", packets); - wget_send(action, tcp_seq_num, tcp_ack_num, len); -} - -/* - * Interfaces of U-BOOT - */ -static void wget_timeout_handler(void) -{ - if (++wget_timeout_count > WGET_RETRY_COUNT) { - puts("\nRetry count exceeded; starting again\n"); - wget_send(TCP_RST, 0, 0, 0); - net_start_again(); - } else { - puts("T "); - net_set_timeout_handler(wget_timeout + - WGET_TIMEOUT * wget_timeout_count, - wget_timeout_handler); - wget_send_stored(); - } -} - -#define PKT_QUEUE_OFFSET 0x20000 -#define PKT_QUEUE_PACKET_SIZE 0x800 - -static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, - u8 action, unsigned int tcp_ack_num, unsigned int len) -{ - uchar *pkt_in_q; - char *pos; - int hlen, i; - uchar *ptr1; - - pkt[len] = '\0'; - pos = strstr((char *)pkt, http_eom); - - if (!pos) { - debug_cond(DEBUG_WGET, - "wget: Connected, data before Header %p\n", pkt); - pkt_in_q = (void *)image_load_addr + PKT_QUEUE_OFFSET + - (pkt_q_idx * PKT_QUEUE_PACKET_SIZE); - - ptr1 = map_sysmem((phys_addr_t)pkt_in_q, len); - memcpy(ptr1, pkt, len); - unmap_sysmem(ptr1); - - pkt_q[pkt_q_idx].pkt = pkt_in_q; - pkt_q[pkt_q_idx].tcp_seq_num = tcp_seq_num; - pkt_q[pkt_q_idx].len = len; - pkt_q_idx++; - } else { - debug_cond(DEBUG_WGET, "wget: Connected HTTP Header %p\n", pkt); - /* sizeof(http_eom) - 1 is the string length of (http_eom) */ - hlen = pos - (char *)pkt + sizeof(http_eom) - 1; - pos = strstr((char *)pkt, linefeed); - if (pos > 0) - i = pos - (char *)pkt; - else - i = hlen; - printf("%.*s", i, pkt); - - current_wget_state = WGET_TRANSFERRING; - - if (strstr((char *)pkt, http_ok) == 0) { - debug_cond(DEBUG_WGET, - "wget: Connected Bad Xfer\n"); - initial_data_seq_num = tcp_seq_num + hlen; - wget_loop_state = NETLOOP_FAIL; - wget_send(action, tcp_seq_num, tcp_ack_num, len); - } else { - debug_cond(DEBUG_WGET, - "wget: Connctd pkt %p hlen %x\n", - pkt, hlen); - initial_data_seq_num = tcp_seq_num + hlen; - - pos = strstr((char *)pkt, content_len); - if (!pos) { - content_length = -1; - } else { - pos += sizeof(content_len) + 2; - strict_strtoul(pos, 10, &content_length); - debug_cond(DEBUG_WGET, - "wget: Connected Len %lu\n", - content_length); - } - - net_boot_file_size = 0; - - if (len > hlen) - store_block(pkt + hlen, 0, len - hlen); - - debug_cond(DEBUG_WGET, - "wget: Connected Pkt %p hlen %x\n", - pkt, hlen); - - for (i = 0; i < pkt_q_idx; i++) { - ptr1 = map_sysmem( - (phys_addr_t)(pkt_q[i].pkt), - pkt_q[i].len); - store_block(ptr1, - pkt_q[i].tcp_seq_num - - initial_data_seq_num, - pkt_q[i].len); - unmap_sysmem(ptr1); - debug_cond(DEBUG_WGET, - "wget: Connctd pkt Q %p len %x\n", - pkt_q[i].pkt, pkt_q[i].len); - } - } - } - wget_send(action, tcp_seq_num, tcp_ack_num, len); -} - -/** - * wget_handler() - TCP handler of wget - * @pkt: pointer to the application packet - * @dport: destination TCP port - * @sip: source IP address - * @sport: source TCP port - * @tcp_seq_num: TCP sequential number - * @tcp_ack_num: TCP acknowledgment number - * @action: TCP action (SYN, ACK, FIN, etc) - * @len: packet length - * - * In the "application push" invocation, the TCP header with all - * its information is pointed to by the packet pointer. - */ -static void wget_handler(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, - u32 tcp_seq_num, u32 tcp_ack_num, - u8 action, unsigned int len) -{ - enum tcp_state wget_tcp_state = tcp_get_tcp_state(); - - net_set_timeout_handler(wget_timeout, wget_timeout_handler); - packets++; - - switch (current_wget_state) { - case WGET_CLOSED: - debug_cond(DEBUG_WGET, "wget: Handler: Error!, State wrong\n"); - break; - case WGET_CONNECTING: - debug_cond(DEBUG_WGET, - "wget: Connecting In len=%x, Seq=%u, Ack=%u\n", - len, tcp_seq_num, tcp_ack_num); - if (!len) { - if (wget_tcp_state == TCP_ESTABLISHED) { - debug_cond(DEBUG_WGET, - "wget: Cting, send, len=%x\n", len); - wget_send(action, tcp_seq_num, tcp_ack_num, - len); - } else { - printf("%.*s", len, pkt); - wget_fail("wget: Handler Connected Fail\n", - tcp_seq_num, tcp_ack_num, action); - } - } - break; - case WGET_CONNECTED: - debug_cond(DEBUG_WGET, "wget: Connected seq=%u, len=%x\n", - tcp_seq_num, len); - if (!len) { - wget_fail("Image not found, no data returned\n", - tcp_seq_num, tcp_ack_num, action); - } else { - wget_connected(pkt, tcp_seq_num, action, tcp_ack_num, len); - } - break; - case WGET_TRANSFERRING: - debug_cond(DEBUG_WGET, - "wget: Transferring, seq=%x, ack=%x,len=%x\n", - tcp_seq_num, tcp_ack_num, len); - - if (tcp_seq_num >= initial_data_seq_num && - store_block(pkt, tcp_seq_num - initial_data_seq_num, - len) != 0) { - wget_fail("wget: store error\n", - tcp_seq_num, tcp_ack_num, action); - return; - } - - switch (wget_tcp_state) { - case TCP_FIN_WAIT_2: - wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, len); - fallthrough; - case TCP_SYN_SENT: - case TCP_SYN_RECEIVED: - case TCP_CLOSING: - case TCP_FIN_WAIT_1: - case TCP_CLOSED: - net_set_state(NETLOOP_FAIL); - break; - case TCP_ESTABLISHED: - wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, - len); - wget_loop_state = NETLOOP_SUCCESS; - break; - case TCP_CLOSE_WAIT: /* End of transfer */ - current_wget_state = WGET_TRANSFERRED; - wget_send(action | TCP_ACK | TCP_FIN, - tcp_seq_num, tcp_ack_num, len); - break; - } - break; - case WGET_TRANSFERRED: - printf("Packets received %d, Transfer Successful\n", packets); - net_set_state(wget_loop_state); - break; - } -} - -#define RANDOM_PORT_START 1024 -#define RANDOM_PORT_RANGE 0x4000 - -/** - * random_port() - make port a little random (1024-17407) - * - * Return: random port number from 1024 to 17407 - * - * This keeps the math somewhat trivial to compute, and seems to work with - * all supported protocols/clients/servers - */ -static unsigned int random_port(void) -{ - return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE); -} - -#define BLOCKSIZE 512 - -void wget_start(void) -{ - image_url = strchr(net_boot_file_name, ':'); - if (image_url > 0) { - web_server_ip = string_to_ip(net_boot_file_name); - ++image_url; - net_server_ip = web_server_ip; - } else { - web_server_ip = net_server_ip; - image_url = net_boot_file_name; - } - - debug_cond(DEBUG_WGET, - "wget: Transfer HTTP Server %pI4; our IP %pI4\n", - &web_server_ip, &net_ip); - - /* Check if we need to send across this subnet */ - if (net_gateway.s_addr && net_netmask.s_addr) { - struct in_addr our_net; - struct in_addr server_net; - - our_net.s_addr = net_ip.s_addr & net_netmask.s_addr; - server_net.s_addr = net_server_ip.s_addr & net_netmask.s_addr; - if (our_net.s_addr != server_net.s_addr) - debug_cond(DEBUG_WGET, - "wget: sending through gateway %pI4", - &net_gateway); - } - debug_cond(DEBUG_WGET, "URL '%s'\n", image_url); - - if (net_boot_file_expected_size_in_blocks) { - debug_cond(DEBUG_WGET, "wget: Size is 0x%x Bytes = ", - net_boot_file_expected_size_in_blocks * BLOCKSIZE); - print_size(net_boot_file_expected_size_in_blocks * BLOCKSIZE, - ""); - } - debug_cond(DEBUG_WGET, - "\nwget:Load address: 0x%lx\nLoading: *\b", image_load_addr); - - net_set_timeout_handler(wget_timeout, wget_timeout_handler); - tcp_set_tcp_handler(wget_handler); - - wget_timeout_count = 0; - current_wget_state = WGET_CLOSED; - - our_port = random_port(); - - /* - * Zero out server ether to force arp resolution in case - * the server ip for the previous u-boot command, for example dns - * is not the same as the web server ip. - */ - - memset(net_server_ethaddr, 0, 6); - - wget_send(TCP_SYN, 0, 0, 0); -}

On Wed, 2 Aug 2023 at 20:10, Maxim Uvarov maxim.uvarov@linaro.org wrote:
After which to lwip variants of working apps we need to drop old code with all dependencies. This commit drop old wget command files.
Oh, I had to be more careful with the descriptions. My head is faster than my hands. Will correct it in the updated version.
Maxim.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/wget.h | 22 --- net/Makefile | 1 - net/net.c | 6 - net/wget.c | 440 --------------------------------------------- 4 files changed, 469 deletions(-) delete mode 100644 include/net/wget.h delete mode 100644 net/wget.c
diff --git a/include/net/wget.h b/include/net/wget.h deleted file mode 100644 index da0920de11..0000000000 --- a/include/net/wget.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/*
- Duncan Hare Copyright 2017
- */
-/**
- wget_start() - begin wget
- */
-void wget_start(void);
-enum wget_state {
WGET_CLOSED,
WGET_CONNECTING,
WGET_CONNECTED,
WGET_TRANSFERRING,
WGET_TRANSFERRED
-};
-#define DEBUG_WGET 0 /* Set to 1 for debug messages */ -#define SERVER_PORT 80 -#define WGET_RETRY_COUNT 30 -#define WGET_TIMEOUT 2000UL diff --git a/net/Makefile b/net/Makefile index 3e2d061338..82cbfb5cc0 100644 --- a/net/Makefile +++ b/net/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.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/net.c b/net/net.c index d98e51cb80..ee4a9f845a 100644 --- a/net/net.c +++ b/net/net.c @@ -109,7 +109,6 @@ #include <linux/compiler.h> #include <test/test.h> #include <net/tcp.h> -#include <net/wget.h> #include "arp.h" #include "bootp.h" #include "cdp.h" @@ -566,11 +565,6 @@ restart: nfs_start(); break; #endif -#if defined(CONFIG_CMD_WGET)
case WGET:
wget_start();
break;
-#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); diff --git a/net/wget.c b/net/wget.c deleted file mode 100644 index 2dbfeb1a1d..0000000000 --- a/net/wget.c +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*
- WGET/HTTP support driver based on U-BOOT's nfs.c
- Copyright Duncan Hare dh@synoia.com 2017
- */
-#include <command.h> -#include <common.h> -#include <display_options.h> -#include <env.h> -#include <image.h> -#include <mapmem.h> -#include <net.h> -#include <net/tcp.h> -#include <net/wget.h>
-static const char bootfile1[] = "GET "; -static const char bootfile3[] = " HTTP/1.0\r\n\r\n"; -static const char http_eom[] = "\r\n\r\n"; -static const char http_ok[] = "200"; -static const char content_len[] = "Content-Length"; -static const char linefeed[] = "\r\n"; -static struct in_addr web_server_ip; -static int our_port; -static int wget_timeout_count;
-struct pkt_qd {
uchar *pkt;
unsigned int tcp_seq_num;
unsigned int len;
-};
-/*
- This is a control structure for out of order packets received.
- The actual packet bufers are in the kernel space, and are
- expected to be overwritten by the downloaded image.
- */
-static struct pkt_qd pkt_q[PKTBUFSRX / 4]; -static int pkt_q_idx; -static unsigned long content_length; -static unsigned int packets;
-static unsigned int initial_data_seq_num;
-static enum wget_state current_wget_state;
-static char *image_url; -static unsigned int wget_timeout = WGET_TIMEOUT;
-static enum net_loop_state wget_loop_state;
-/* Timeout retry parameters */ -static u8 retry_action; /* actions for TCP retry */ -static unsigned int retry_tcp_ack_num; /* TCP retry acknowledge number*/ -static unsigned int retry_tcp_seq_num; /* TCP retry sequence number */ -static int retry_len; /* TCP retry length */
-/**
- store_block() - store block in memory
- @src: source of data
- @offset: offset
- @len: length
- */
-static inline int store_block(uchar *src, unsigned int offset, unsigned int len) -{
ulong newsize = offset + len;
uchar *ptr;
ptr = map_sysmem(image_load_addr + offset, len);
memcpy(ptr, src, len);
unmap_sysmem(ptr);
if (net_boot_file_size < (offset + len))
net_boot_file_size = newsize;
return 0;
-}
-/**
- wget_send_stored() - wget response dispatcher
- WARNING, This, and only this, is the place in wget.c where
- SEQUENCE NUMBERS are swapped between incoming (RX)
- and outgoing (TX).
- Procedure wget_handler() is correct for RX traffic.
- */
-static void wget_send_stored(void) -{
u8 action = retry_action;
int len = retry_len;
unsigned int tcp_ack_num = retry_tcp_seq_num + (len == 0 ? 1 :
len);
unsigned int tcp_seq_num = retry_tcp_ack_num;
uchar *ptr, *offset;
switch (current_wget_state) {
case WGET_CLOSED:
debug_cond(DEBUG_WGET, "wget: send SYN\n");
current_wget_state = WGET_CONNECTING;
net_send_tcp_packet(0, SERVER_PORT, our_port, action,
tcp_seq_num, tcp_ack_num);
packets = 0;
break;
case WGET_CONNECTING:
pkt_q_idx = 0;
net_send_tcp_packet(0, SERVER_PORT, our_port, action,
tcp_seq_num, tcp_ack_num);
ptr = net_tx_packet + net_eth_hdr_size() +
IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
offset = ptr;
memcpy(offset, &bootfile1, strlen(bootfile1));
offset += strlen(bootfile1);
memcpy(offset, image_url, strlen(image_url));
offset += strlen(image_url);
memcpy(offset, &bootfile3, strlen(bootfile3));
offset += strlen(bootfile3);
net_send_tcp_packet((offset - ptr), SERVER_PORT, our_port,
TCP_PUSH, tcp_seq_num, tcp_ack_num);
current_wget_state = WGET_CONNECTED;
break;
case WGET_CONNECTED:
case WGET_TRANSFERRING:
case WGET_TRANSFERRED:
net_send_tcp_packet(0, SERVER_PORT, our_port, action,
tcp_seq_num, tcp_ack_num);
break;
}
-}
-static void wget_send(u8 action, unsigned int tcp_seq_num,
unsigned int tcp_ack_num, int len)
-{
retry_action = action;
retry_tcp_ack_num = tcp_ack_num;
retry_tcp_seq_num = tcp_seq_num;
retry_len = len;
wget_send_stored();
-}
-void wget_fail(char *error_message, unsigned int tcp_seq_num,
unsigned int tcp_ack_num, u8 action)
-{
printf("wget: Transfer Fail - %s\n", error_message);
net_set_timeout_handler(0, NULL);
wget_send(action, tcp_seq_num, tcp_ack_num, 0);
-}
-void wget_success(u8 action, unsigned int tcp_seq_num,
unsigned int tcp_ack_num, int len, int packets)
-{
printf("Packets received %d, Transfer Successful\n", packets);
wget_send(action, tcp_seq_num, tcp_ack_num, len);
-}
-/*
- Interfaces of U-BOOT
- */
-static void wget_timeout_handler(void) -{
if (++wget_timeout_count > WGET_RETRY_COUNT) {
puts("\nRetry count exceeded; starting again\n");
wget_send(TCP_RST, 0, 0, 0);
net_start_again();
} else {
puts("T ");
net_set_timeout_handler(wget_timeout +
WGET_TIMEOUT * wget_timeout_count,
wget_timeout_handler);
wget_send_stored();
}
-}
-#define PKT_QUEUE_OFFSET 0x20000 -#define PKT_QUEUE_PACKET_SIZE 0x800
-static void wget_connected(uchar *pkt, unsigned int tcp_seq_num,
u8 action, unsigned int tcp_ack_num, unsigned
int len) -{
uchar *pkt_in_q;
char *pos;
int hlen, i;
uchar *ptr1;
pkt[len] = '\0';
pos = strstr((char *)pkt, http_eom);
if (!pos) {
debug_cond(DEBUG_WGET,
"wget: Connected, data before Header %p\n",
pkt);
pkt_in_q = (void *)image_load_addr + PKT_QUEUE_OFFSET +
(pkt_q_idx * PKT_QUEUE_PACKET_SIZE);
ptr1 = map_sysmem((phys_addr_t)pkt_in_q, len);
memcpy(ptr1, pkt, len);
unmap_sysmem(ptr1);
pkt_q[pkt_q_idx].pkt = pkt_in_q;
pkt_q[pkt_q_idx].tcp_seq_num = tcp_seq_num;
pkt_q[pkt_q_idx].len = len;
pkt_q_idx++;
} else {
debug_cond(DEBUG_WGET, "wget: Connected HTTP Header %p\n",
pkt);
/* sizeof(http_eom) - 1 is the string length of (http_eom)
*/
hlen = pos - (char *)pkt + sizeof(http_eom) - 1;
pos = strstr((char *)pkt, linefeed);
if (pos > 0)
i = pos - (char *)pkt;
else
i = hlen;
printf("%.*s", i, pkt);
current_wget_state = WGET_TRANSFERRING;
if (strstr((char *)pkt, http_ok) == 0) {
debug_cond(DEBUG_WGET,
"wget: Connected Bad Xfer\n");
initial_data_seq_num = tcp_seq_num + hlen;
wget_loop_state = NETLOOP_FAIL;
wget_send(action, tcp_seq_num, tcp_ack_num, len);
} else {
debug_cond(DEBUG_WGET,
"wget: Connctd pkt %p hlen %x\n",
pkt, hlen);
initial_data_seq_num = tcp_seq_num + hlen;
pos = strstr((char *)pkt, content_len);
if (!pos) {
content_length = -1;
} else {
pos += sizeof(content_len) + 2;
strict_strtoul(pos, 10, &content_length);
debug_cond(DEBUG_WGET,
"wget: Connected Len %lu\n",
content_length);
}
net_boot_file_size = 0;
if (len > hlen)
store_block(pkt + hlen, 0, len - hlen);
debug_cond(DEBUG_WGET,
"wget: Connected Pkt %p hlen %x\n",
pkt, hlen);
for (i = 0; i < pkt_q_idx; i++) {
ptr1 = map_sysmem(
(phys_addr_t)(pkt_q[i].pkt),
pkt_q[i].len);
store_block(ptr1,
pkt_q[i].tcp_seq_num -
initial_data_seq_num,
pkt_q[i].len);
unmap_sysmem(ptr1);
debug_cond(DEBUG_WGET,
"wget: Connctd pkt Q %p len
%x\n",
pkt_q[i].pkt, pkt_q[i].len);
}
}
}
wget_send(action, tcp_seq_num, tcp_ack_num, len);
-}
-/**
- wget_handler() - TCP handler of wget
- @pkt: pointer to the application packet
- @dport: destination TCP port
- @sip: source IP address
- @sport: source TCP port
- @tcp_seq_num: TCP sequential number
- @tcp_ack_num: TCP acknowledgment number
- @action: TCP action (SYN, ACK, FIN, etc)
- @len: packet length
- In the "application push" invocation, the TCP header with all
- its information is pointed to by the packet pointer.
- */
-static void wget_handler(uchar *pkt, u16 dport,
struct in_addr sip, u16 sport,
u32 tcp_seq_num, u32 tcp_ack_num,
u8 action, unsigned int len)
-{
enum tcp_state wget_tcp_state = tcp_get_tcp_state();
net_set_timeout_handler(wget_timeout, wget_timeout_handler);
packets++;
switch (current_wget_state) {
case WGET_CLOSED:
debug_cond(DEBUG_WGET, "wget: Handler: Error!, State
wrong\n");
break;
case WGET_CONNECTING:
debug_cond(DEBUG_WGET,
"wget: Connecting In len=%x, Seq=%u, Ack=%u\n",
len, tcp_seq_num, tcp_ack_num);
if (!len) {
if (wget_tcp_state == TCP_ESTABLISHED) {
debug_cond(DEBUG_WGET,
"wget: Cting, send, len=%x\n",
len);
wget_send(action, tcp_seq_num, tcp_ack_num,
len);
} else {
printf("%.*s", len, pkt);
wget_fail("wget: Handler Connected Fail\n",
tcp_seq_num, tcp_ack_num,
action);
}
}
break;
case WGET_CONNECTED:
debug_cond(DEBUG_WGET, "wget: Connected seq=%u, len=%x\n",
tcp_seq_num, len);
if (!len) {
wget_fail("Image not found, no data returned\n",
tcp_seq_num, tcp_ack_num, action);
} else {
wget_connected(pkt, tcp_seq_num, action,
tcp_ack_num, len);
}
break;
case WGET_TRANSFERRING:
debug_cond(DEBUG_WGET,
"wget: Transferring, seq=%x, ack=%x,len=%x\n",
tcp_seq_num, tcp_ack_num, len);
if (tcp_seq_num >= initial_data_seq_num &&
store_block(pkt, tcp_seq_num - initial_data_seq_num,
len) != 0) {
wget_fail("wget: store error\n",
tcp_seq_num, tcp_ack_num, action);
return;
}
switch (wget_tcp_state) {
case TCP_FIN_WAIT_2:
wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, len);
fallthrough;
case TCP_SYN_SENT:
case TCP_SYN_RECEIVED:
case TCP_CLOSING:
case TCP_FIN_WAIT_1:
case TCP_CLOSED:
net_set_state(NETLOOP_FAIL);
break;
case TCP_ESTABLISHED:
wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num,
len);
wget_loop_state = NETLOOP_SUCCESS;
break;
case TCP_CLOSE_WAIT: /* End of transfer */
current_wget_state = WGET_TRANSFERRED;
wget_send(action | TCP_ACK | TCP_FIN,
tcp_seq_num, tcp_ack_num, len);
break;
}
break;
case WGET_TRANSFERRED:
printf("Packets received %d, Transfer Successful\n",
packets);
net_set_state(wget_loop_state);
break;
}
-}
-#define RANDOM_PORT_START 1024 -#define RANDOM_PORT_RANGE 0x4000
-/**
- random_port() - make port a little random (1024-17407)
- Return: random port number from 1024 to 17407
- This keeps the math somewhat trivial to compute, and seems to work with
- all supported protocols/clients/servers
- */
-static unsigned int random_port(void) -{
return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE);
-}
-#define BLOCKSIZE 512
-void wget_start(void) -{
image_url = strchr(net_boot_file_name, ':');
if (image_url > 0) {
web_server_ip = string_to_ip(net_boot_file_name);
++image_url;
net_server_ip = web_server_ip;
} else {
web_server_ip = net_server_ip;
image_url = net_boot_file_name;
}
debug_cond(DEBUG_WGET,
"wget: Transfer HTTP Server %pI4; our IP %pI4\n",
&web_server_ip, &net_ip);
/* Check if we need to send across this subnet */
if (net_gateway.s_addr && net_netmask.s_addr) {
struct in_addr our_net;
struct in_addr server_net;
our_net.s_addr = net_ip.s_addr & net_netmask.s_addr;
server_net.s_addr = net_server_ip.s_addr &
net_netmask.s_addr;
if (our_net.s_addr != server_net.s_addr)
debug_cond(DEBUG_WGET,
"wget: sending through gateway %pI4",
&net_gateway);
}
debug_cond(DEBUG_WGET, "URL '%s'\n", image_url);
if (net_boot_file_expected_size_in_blocks) {
debug_cond(DEBUG_WGET, "wget: Size is 0x%x Bytes = ",
net_boot_file_expected_size_in_blocks *
BLOCKSIZE);
print_size(net_boot_file_expected_size_in_blocks *
BLOCKSIZE,
"");
}
debug_cond(DEBUG_WGET,
"\nwget:Load address: 0x%lx\nLoading: *\b",
image_load_addr);
net_set_timeout_handler(wget_timeout, wget_timeout_handler);
tcp_set_tcp_handler(wget_handler);
wget_timeout_count = 0;
current_wget_state = WGET_CLOSED;
our_port = random_port();
/*
* Zero out server ether to force arp resolution in case
* the server ip for the previous u-boot command, for example dns
* is not the same as the web server ip.
*/
memset(net_server_ethaddr, 0, 6);
wget_send(TCP_SYN, 0, 0, 0);
-}
2.30.2
participants (4)
-
Ilias Apalodimas
-
Maxim Uvarov
-
Simon Glass
-
Simon Goldschmidt