All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv5 00/13] net/lwip: add lwip library for the network stack
@ 2023-08-02 14:06 Maxim Uvarov
  2023-08-02 14:06 ` [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
                   ` (12 more replies)
  0 siblings, 13 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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

-- 
2.30.2


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

* [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-02 14:06 ` [PATCHv5 02/13] net/lwip: integrate lwip library Maxim Uvarov
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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.
-- 
2.30.2


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

* [PATCHv5 02/13] net/lwip: integrate lwip library
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
  2023-08-02 14:06 ` [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-02 14:06 ` [PATCHv5 03/13] net/lwip: implement dns cmd Maxim Uvarov
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

---
 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);
-- 
2.30.2


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

* [PATCHv5 03/13] net/lwip: implement dns cmd
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
  2023-08-02 14:06 ` [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
  2023-08-02 14:06 ` [PATCHv5 02/13] net/lwip: integrate lwip library Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-02 14:06 ` [PATCHv5 04/13] net/lwip: implement dhcp cmd Maxim Uvarov
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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);
-- 
2.30.2


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

* [PATCHv5 04/13] net/lwip: implement dhcp cmd
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (2 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 03/13] net/lwip: implement dns cmd Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-03  6:26   ` Ilias Apalodimas
  2023-08-02 14:06 ` [PATCHv5 05/13] net/lwip: implement tftp cmd Maxim Uvarov
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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;
+}
-- 
2.30.2


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

* [PATCHv5 05/13] net/lwip: implement tftp cmd
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (3 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 04/13] net/lwip: implement dhcp cmd Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-03  6:42   ` Ilias Apalodimas
  2023-08-02 14:06 ` [PATCHv5 06/13] net/lwip: implement wget cmd Maxim Uvarov
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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 */
-- 
2.30.2


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

* [PATCHv5 06/13] net/lwip: implement wget cmd
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (4 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 05/13] net/lwip: implement tftp cmd Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-03  6:48   ` Ilias Apalodimas
  2023-08-02 14:06 ` [PATCHv5 07/13] net/lwip: implement ping cmd Maxim Uvarov
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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://!\n");
+		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;
+}
-- 
2.30.2


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

* [PATCHv5 07/13] net/lwip: implement ping cmd
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (5 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 06/13] net/lwip: implement wget cmd Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-03  9:32   ` Ilias Apalodimas
  2023-08-02 14:06 ` [PATCHv5 08/13] net/lwip: add lwip configuration configuration Maxim Uvarov
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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);
-- 
2.30.2


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

* [PATCHv5 08/13] net/lwip: add lwip configuration configuration
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (6 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 07/13] net/lwip: implement ping cmd Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 14:06 ` [PATCHv5 09/13] net/lwip: implement lwip port to u-boot Maxim Uvarov
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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 */
-- 
2.30.2


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

* [PATCHv5 09/13] net/lwip: implement lwip port to u-boot
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (7 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 08/13] net/lwip: add lwip configuration configuration Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-02 14:06 ` [PATCHv5 10/13] net/lwip: update .gitignore with lwip Maxim Uvarov
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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();
+}
+
-- 
2.30.2


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

* [PATCHv5 10/13] net/lwip: update .gitignore with lwip
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (8 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 09/13] net/lwip: implement lwip port to u-boot Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-03  6:01   ` Ilias Apalodimas
  2023-08-02 14:06 ` [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps Maxim Uvarov
                   ` (2 subsequent siblings)
  12 siblings, 2 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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
-- 
2.30.2


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

* [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (9 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 10/13] net/lwip: update .gitignore with lwip Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-03  8:56   ` Ilias Apalodimas
  2023-08-02 14:06 ` [PATCHv5 12/13] net/lwip: replace original net commands with lwip Maxim Uvarov
  2023-08-02 14:06 ` [PATCHv5 13/13] net/lwip: drop old net/wget Maxim Uvarov
  12 siblings, 2 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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/\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


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

* [PATCHv5 12/13] net/lwip: replace original net commands with lwip
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (10 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
  2023-08-02 14:06 ` [PATCHv5 13/13] net/lwip: drop old net/wget Maxim Uvarov
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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));
-- 
2.30.2


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

* [PATCHv5 13/13] net/lwip: drop old net/wget
  2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (11 preceding siblings ...)
  2023-08-02 14:06 ` [PATCHv5 12/13] net/lwip: replace original net commands with lwip Maxim Uvarov
@ 2023-08-02 14:06 ` Maxim Uvarov
  2023-08-02 14:19   ` Maxim Uvarov
  12 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:06 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

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);
-}
-- 
2.30.2


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

* Re: [PATCHv5 13/13] net/lwip: drop old net/wget
  2023-08-02 14:06 ` [PATCHv5 13/13] net/lwip: drop old net/wget Maxim Uvarov
@ 2023-08-02 14:19   ` Maxim Uvarov
  0 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-02 14:19 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
>
>

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

* Re: [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst
  2023-08-02 14:06 ` [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  0 siblings, 0 replies; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 02/13] net/lwip: integrate lwip library
  2023-08-02 14:06 ` [PATCHv5 02/13] net/lwip: integrate lwip library Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  2023-08-03 14:18     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 03/13] net/lwip: implement dns cmd
  2023-08-02 14:06 ` [PATCHv5 03/13] net/lwip: implement dns cmd Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  0 siblings, 0 replies; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 09/13] net/lwip: implement lwip port to u-boot
  2023-08-02 14:06 ` [PATCHv5 09/13] net/lwip: implement lwip port to u-boot Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  2023-08-03 16:21     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 10/13] net/lwip: update .gitignore with lwip
  2023-08-02 14:06 ` [PATCHv5 10/13] net/lwip: update .gitignore with lwip Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  2023-08-03  6:01   ` Ilias Apalodimas
  1 sibling, 0 replies; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps
  2023-08-02 14:06 ` [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  2023-08-03  8:56   ` Ilias Apalodimas
  1 sibling, 0 replies; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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/

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

* Re: [PATCHv5 12/13] net/lwip: replace original net commands with lwip
  2023-08-02 14:06 ` [PATCHv5 12/13] net/lwip: replace original net commands with lwip Maxim Uvarov
@ 2023-08-02 21:31   ` Simon Glass
  2023-08-08 14:05     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Simon Glass @ 2023-08-02 21:31 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 10/13] net/lwip: update .gitignore with lwip
  2023-08-02 14:06 ` [PATCHv5 10/13] net/lwip: update .gitignore with lwip Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
@ 2023-08-03  6:01   ` Ilias Apalodimas
  1 sibling, 0 replies; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-03  6:01 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
>

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

* Re: [PATCHv5 04/13] net/lwip: implement dhcp cmd
  2023-08-02 14:06 ` [PATCHv5 04/13] net/lwip: implement dhcp cmd Maxim Uvarov
@ 2023-08-03  6:26   ` Ilias Apalodimas
  2023-08-03 14:34     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-03  6:26 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
> 

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

* Re: [PATCHv5 05/13] net/lwip: implement tftp cmd
  2023-08-02 14:06 ` [PATCHv5 05/13] net/lwip: implement tftp cmd Maxim Uvarov
@ 2023-08-03  6:42   ` Ilias Apalodimas
  2023-08-10 11:28     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-03  6:42 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
> 

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

* Re: [PATCHv5 06/13] net/lwip: implement wget cmd
  2023-08-02 14:06 ` [PATCHv5 06/13] net/lwip: implement wget cmd Maxim Uvarov
@ 2023-08-03  6:48   ` Ilias Apalodimas
  2023-08-03 14:59     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-03  6:48 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
> 

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

* Re: [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps
  2023-08-02 14:06 ` [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps Maxim Uvarov
  2023-08-02 21:31   ` Simon Glass
@ 2023-08-03  8:56   ` Ilias Apalodimas
  2023-08-08 12:19     ` Maxim Uvarov
  1 sibling, 1 reply; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-03  8:56 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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/\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

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

* Re: [PATCHv5 07/13] net/lwip: implement ping cmd
  2023-08-02 14:06 ` [PATCHv5 07/13] net/lwip: implement ping cmd Maxim Uvarov
@ 2023-08-03  9:32   ` Ilias Apalodimas
  2023-08-03 15:25     ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-03  9:32 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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

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

* Re: [PATCHv5 02/13] net/lwip: integrate lwip library
  2023-08-02 21:31   ` Simon Glass
@ 2023-08-03 14:18     ` Maxim Uvarov
  0 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-03 14:18 UTC (permalink / raw)
  To: Simon Glass
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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.

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

* Re: [PATCHv5 04/13] net/lwip: implement dhcp cmd
  2023-08-03  6:26   ` Ilias Apalodimas
@ 2023-08-03 14:34     ` Maxim Uvarov
  0 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-03 14:34 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
> >
>

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

* Re: [PATCHv5 06/13] net/lwip: implement wget cmd
  2023-08-03  6:48   ` Ilias Apalodimas
@ 2023-08-03 14:59     ` Maxim Uvarov
  0 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-03 14:59 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
> >
>

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

* Re: [PATCHv5 07/13] net/lwip: implement ping cmd
  2023-08-03  9:32   ` Ilias Apalodimas
@ 2023-08-03 15:25     ` Maxim Uvarov
  0 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-03 15:25 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
>

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

* Re: [PATCHv5 09/13] net/lwip: implement lwip port to u-boot
  2023-08-02 21:31   ` Simon Glass
@ 2023-08-03 16:21     ` Maxim Uvarov
  2023-08-08 10:07       ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-03 16:21 UTC (permalink / raw)
  To: Simon Glass
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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
>

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

* Re: [PATCHv5 09/13] net/lwip: implement lwip port to u-boot
  2023-08-03 16:21     ` Maxim Uvarov
@ 2023-08-08 10:07       ` Maxim Uvarov
  2023-08-08 17:54         ` Simon Glass
  0 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-08 10:07 UTC (permalink / raw)
  To: Simon Glass
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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,
>> 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)
>>
>>
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
>>
>

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

* Re: [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps
  2023-08-03  8:56   ` Ilias Apalodimas
@ 2023-08-08 12:19     ` Maxim Uvarov
  2023-08-08 18:12       ` Ilias Apalodimas
  0 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-08 12:19 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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.

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

* Re: [PATCHv5 12/13] net/lwip: replace original net commands with lwip
  2023-08-02 21:31   ` Simon Glass
@ 2023-08-08 14:05     ` Maxim Uvarov
  2023-08-08 17:54       ` Simon Glass
  0 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-08 14:05 UTC (permalink / raw)
  To: Simon Glass
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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
>

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

* Re: [PATCHv5 12/13] net/lwip: replace original net commands with lwip
  2023-08-08 14:05     ` Maxim Uvarov
@ 2023-08-08 17:54       ` Simon Glass
  0 siblings, 0 replies; 42+ messages in thread
From: Simon Glass @ 2023-08-08 17:54 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 09/13] net/lwip: implement lwip port to u-boot
  2023-08-08 10:07       ` Maxim Uvarov
@ 2023-08-08 17:54         ` Simon Glass
  0 siblings, 0 replies; 42+ messages in thread
From: Simon Glass @ 2023-08-08 17:54 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, ilias.apalodimas, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

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

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

* Re: [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps
  2023-08-08 12:19     ` Maxim Uvarov
@ 2023-08-08 18:12       ` Ilias Apalodimas
  2023-08-09 19:29         ` Maxim Uvarov
  0 siblings, 1 reply; 42+ messages in thread
From: Ilias Apalodimas @ 2023-08-08 18:12 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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:
> 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.

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

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

* Re: [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps
  2023-08-08 18:12       ` Ilias Apalodimas
@ 2023-08-09 19:29         ` Maxim Uvarov
  0 siblings, 0 replies; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-09 19:29 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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:
> > 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.
>
> 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
>

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

* Re: [PATCHv5 05/13] net/lwip: implement tftp cmd
  2023-08-03  6:42   ` Ilias Apalodimas
@ 2023-08-10 11:28     ` Maxim Uvarov
  2023-08-10 19:23       ` Simon Goldschmidt
  0 siblings, 1 reply; 42+ messages in thread
From: Maxim Uvarov @ 2023-08-10 11:28 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

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
> >
>

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

* Re: [PATCHv5 05/13] net/lwip: implement tftp cmd
  2023-08-10 11:28     ` Maxim Uvarov
@ 2023-08-10 19:23       ` Simon Goldschmidt
  0 siblings, 0 replies; 42+ messages in thread
From: Simon Goldschmidt @ 2023-08-10 19:23 UTC (permalink / raw)
  To: Maxim Uvarov, Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini, lwip-devel



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
>>>
>>
>

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

end of thread, other threads:[~2023-08-10 19:23 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-02 14:06 [PATCHv5 00/13] net/lwip: add lwip library for the network stack Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 01/13] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-02 14:06 ` [PATCHv5 02/13] net/lwip: integrate lwip library Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-03 14:18     ` Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 03/13] net/lwip: implement dns cmd Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-02 14:06 ` [PATCHv5 04/13] net/lwip: implement dhcp cmd Maxim Uvarov
2023-08-03  6:26   ` Ilias Apalodimas
2023-08-03 14:34     ` Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 05/13] net/lwip: implement tftp cmd Maxim Uvarov
2023-08-03  6:42   ` Ilias Apalodimas
2023-08-10 11:28     ` Maxim Uvarov
2023-08-10 19:23       ` Simon Goldschmidt
2023-08-02 14:06 ` [PATCHv5 06/13] net/lwip: implement wget cmd Maxim Uvarov
2023-08-03  6:48   ` Ilias Apalodimas
2023-08-03 14:59     ` Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 07/13] net/lwip: implement ping cmd Maxim Uvarov
2023-08-03  9:32   ` Ilias Apalodimas
2023-08-03 15:25     ` Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 08/13] net/lwip: add lwip configuration configuration Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 09/13] net/lwip: implement lwip port to u-boot Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-03 16:21     ` Maxim Uvarov
2023-08-08 10:07       ` Maxim Uvarov
2023-08-08 17:54         ` Simon Glass
2023-08-02 14:06 ` [PATCHv5 10/13] net/lwip: update .gitignore with lwip Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-03  6:01   ` Ilias Apalodimas
2023-08-02 14:06 ` [PATCHv5 11/13] net/lwip: connection between cmd and lwip apps Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-03  8:56   ` Ilias Apalodimas
2023-08-08 12:19     ` Maxim Uvarov
2023-08-08 18:12       ` Ilias Apalodimas
2023-08-09 19:29         ` Maxim Uvarov
2023-08-02 14:06 ` [PATCHv5 12/13] net/lwip: replace original net commands with lwip Maxim Uvarov
2023-08-02 21:31   ` Simon Glass
2023-08-08 14:05     ` Maxim Uvarov
2023-08-08 17:54       ` Simon Glass
2023-08-02 14:06 ` [PATCHv5 13/13] net/lwip: drop old net/wget Maxim Uvarov
2023-08-02 14:19   ` Maxim Uvarov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.