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

changelog:
	v6: - fixed review comments for v5 (thanks Ilias and Simon).
	    - lwip is not under /net, so prior applying patch following
	      commit is needed to create lwIP merge into U-Boot:
	      git subtree add --prefix net/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash

	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 (14):
  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
  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: split net.h to net.h, arp.h and eth.h
  net/lwip: drop old net/wget

 boot/bootmeth_efi.c                   |  18 +-
 boot/bootmeth_pxe.c                   |  21 +-
 cmd/Makefile                          |   1 +
 cmd/net-lwip.c                        | 306 ++++++++++++++++++
 cmd/net.c                             |  86 +----
 cmd/pxe.c                             |  19 +-
 doc/develop/index.rst                 |   1 +
 doc/develop/net_lwip.rst              |  64 ++++
 include/net.h                         | 197 +-----------
 include/net/arp.h                     |   7 +
 include/net/eth.h                     | 190 +++++++++++
 include/net/lwip.h                    |  66 ++++
 include/net/ulwip.h                   |  68 ++++
 include/net/wget.h                    |  22 --
 net/Kconfig                           |   3 +
 net/Makefile                          |   2 +-
 net/eth-uclass.c                      |   8 +
 net/lwip/.gitignore                   |   8 +
 net/lwip/Kconfig                      |  60 ++++
 net/lwip/Makefile                     |  72 +++++
 net/lwip/apps/dhcp/lwip-dhcp.c        |  51 +++
 net/lwip/apps/dns/lwip-dns.c          |  46 +++
 net/lwip/apps/http/Makefile           |  13 +
 net/lwip/apps/http/lwip-wget.c        | 131 ++++++++
 net/lwip/apps/ping/Makefile           |  11 +
 net/lwip/apps/ping/lwip_ping.c        |  37 +++
 net/lwip/apps/ping/lwip_ping.h        |  15 +
 net/lwip/apps/ping/ping.h             |  19 ++
 net/lwip/apps/tftp/Makefile           |  16 +
 net/lwip/apps/tftp/lwip-tftp.c        | 129 ++++++++
 net/lwip/lwipopts.h                   | 195 ++++++++++++
 net/lwip/port/if.c                    | 260 +++++++++++++++
 net/lwip/port/include/arch/cc.h       |  39 +++
 net/lwip/port/include/arch/sys_arch.h |  56 ++++
 net/lwip/port/include/limits.h        |   0
 net/lwip/port/sys-arch.c              |  20 ++
 net/net.c                             |  26 +-
 net/wget.c                            | 440 --------------------------
 38 files changed, 1966 insertions(+), 757 deletions(-)
 create mode 100644 cmd/net-lwip.c
 create mode 100644 doc/develop/net_lwip.rst
 create mode 100644 include/net/arp.h
 create mode 100644 include/net/eth.h
 create mode 100644 include/net/lwip.h
 create mode 100644 include/net/ulwip.h
 delete mode 100644 include/net/wget.h
 create mode 100644 net/lwip/.gitignore
 create mode 100644 net/lwip/Kconfig
 create mode 100644 net/lwip/Makefile
 create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
 create mode 100644 net/lwip/apps/dns/lwip-dns.c
 create mode 100644 net/lwip/apps/http/Makefile
 create mode 100644 net/lwip/apps/http/lwip-wget.c
 create mode 100644 net/lwip/apps/ping/Makefile
 create mode 100644 net/lwip/apps/ping/lwip_ping.c
 create mode 100644 net/lwip/apps/ping/lwip_ping.h
 create mode 100644 net/lwip/apps/ping/ping.h
 create mode 100644 net/lwip/apps/tftp/Makefile
 create mode 100644 net/lwip/apps/tftp/lwip-tftp.c
 create mode 100644 net/lwip/lwipopts.h
 create mode 100644 net/lwip/port/if.c
 create mode 100644 net/lwip/port/include/arch/cc.h
 create mode 100644 net/lwip/port/include/arch/sys_arch.h
 create mode 100644 net/lwip/port/include/limits.h
 create mode 100644 net/lwip/port/sys-arch.c
 delete mode 100644 net/wget.c

-- 
2.30.2


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

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

Add initial documentation of lwIP network IP stack integration
to the U-Boot (net_lwip.rst).

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 doc/develop/index.rst    |  1 +
 doc/develop/net_lwip.rst | 64 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 doc/develop/net_lwip.rst

diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index 5b230d0321..4764990f25 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -48,6 +48,7 @@ Implementation
    spl
    falcon
    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..bdd2c921b3
--- /dev/null
+++ b/doc/develop/net_lwip.rst
@@ -0,0 +1,64 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+LWIP IP stack intergation for U-Boot
+====================================
+
+Intro
+-----
+
+LWIP is a library implementing 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 registered
+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] 49+ messages in thread

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

Define Makefile and Kconfig to build lwIP inside the U-Boot. We compile
lwIP the same as the main code, plus we can do optimization for size at
compile time with disabling not needed debug asserts, or not used protocols.
So we can tune lwIP configuration specially for U-Boot environments.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 net/Kconfig       |  3 +++
 net/Makefile      |  1 +
 net/lwip/Kconfig  | 60 ++++++++++++++++++++++++++++++++++++++++++
 net/lwip/Makefile | 66 +++++++++++++++++++++++++++++++++++++++++++++++
 net/net.c         | 20 ++++++++++++++
 5 files changed, 150 insertions(+)
 create mode 100644 net/lwip/Kconfig
 create mode 100644 net/lwip/Makefile

diff --git a/net/Kconfig b/net/Kconfig
index 4215889127..34c1e43c87 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -5,9 +5,12 @@
 menuconfig NET
 	bool "Networking support"
 	default y
+	imply LWIP
 
 if NET
 
+source net/lwip/Kconfig
+
 config ARP_TIMEOUT
 	int "Milliseconds before trying ARP again"
 	default 5000
diff --git a/net/Makefile b/net/Makefile
index 3e2d061338..61930c244e 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_CMD_WOL)  += wol.o
 obj-$(CONFIG_PROT_UDP) += udp.o
 obj-$(CONFIG_PROT_TCP) += tcp.o
 obj-$(CONFIG_CMD_WGET) += wget.o
+obj-$(CONFIG_LWIP) += lwip/
 
 # Disable this warning as it is triggered by:
 # sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/lwip/Kconfig b/net/lwip/Kconfig
new file mode 100644
index 0000000000..233c6c532d
--- /dev/null
+++ b/net/lwip/Kconfig
@@ -0,0 +1,60 @@
+menu "LWIP"
+config LWIP
+	bool "Support LWIP library"
+	help
+          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.
+	  Please see doc/develop/net_lwip.rst for more details.
+
+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 by 16k.
+
+config LWIP_LIB_TCP
+        bool "tcp"
+        default y
+	help
+	   Compile lwIP with TCP protocol support.
+
+config LWIP_LIB_UDP
+        bool "udp"
+        default y
+	help
+	   Compile lwIP with UDP protocol support (needed for TFTP).
+
+config LWIP_LIB_DNS
+        bool "dns"
+        default y
+	help
+	   Compile lwIP with DNS protocol support.
+
+config LWIP_LIB_DHCP
+        bool "dhcp"
+        default y
+	help
+	   Compile lwIP with DHCP protocol support.
+
+config LWIP_LIB_LOOPBACK
+        bool "loopback"
+        help
+	   Increases size by 1k.
+	help
+	   Compile lwIP with loopback interface support.
+
+config LWIP_LIB_SOCKET
+        bool "socket API"
+
+endmenu
+
+endmenu
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
new file mode 100644
index 0000000000..d1161bea78
--- /dev/null
+++ b/net/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)/net/lwip/port/include
+ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/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/net.c b/net/net.c
index 43abbac7c3..7f868ee516 100644
--- a/net/net.c
+++ b/net/net.c
@@ -125,6 +125,7 @@
 #endif
 #include "dhcpv6.h"
 #include "net_rand.h"
+#include <net/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)
+	if (!ulwip_enabled() || !ulwip_in_loop())
+#endif
 	net_init();
+
 	if (eth_is_on_demand_init()) {
 		eth_halt();
 		eth_set_current();
@@ -649,6 +654,16 @@ restart:
 		 */
 		eth_rx();
 
+		if (IS_ENABLED(CONFIG_LWIP) && 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;
+			}
+		}
 		/*
 		 *	Abort if ctrl-c was pressed.
 		 */
@@ -1213,6 +1228,11 @@ void net_process_received_packet(uchar *in_packet, int len)
 	if (len < ETHER_HDR_SIZE)
 		return;
 
+	if (IS_ENABLED(CONFIG_LWIP) && ulwip_enabled()) {
+		ulwip_poll();
+		return;
+	}
+
 #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] 49+ messages in thread

* [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 01/14] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 02/14] net/lwip: integrate lwIP library Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-14 14:19   ` Ilias Apalodimas
  2023-08-14 13:32 ` [PATCHv6 04/14] net/lwip: implement dhcp cmd Maxim Uvarov
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

Implement function for dns command with lwIP variant. Usage and output is
the same as the original command. This code called by compatibility code
between U-Boot and lwIP.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 include/net/lwip.h           | 17 +++++++++++++
 net/lwip/Makefile            |  2 ++
 net/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)
 create mode 100644 include/net/lwip.h
 create mode 100644 net/lwip/apps/dns/lwip-dns.c

diff --git a/include/net/lwip.h b/include/net/lwip.h
new file mode 100644
index 0000000000..c83b5c8231
--- /dev/null
+++ b/include/net/lwip.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
+		char *const argv[]);
+
+/*
+* This function creates the DNS request to resolve a domain host name. Function
+* can return immediately if previous request was cached or it might require
+* entering the polling loop for a request to a remote server.
+*
+* @name  dns name to resolve
+* @varname (optional) U-Boot variable name to store the result
+* Return: ERR_OK(0) for fetching entry from the cache
+*         ERR_INPROGRESS(-5) success, can go to the polling loop
+*         Other value < 0, if error
+*/
+int ulwip_dns(char *name, char *varname);
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index d1161bea78..6d2c00605b 100644
--- a/net/lwip/Makefile
+++ b/net/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/net/lwip/apps/dns/lwip-dns.c b/net/lwip/apps/dns/lwip-dns.c
new file mode 100644
index 0000000000..6e205c1153
--- /dev/null
+++ b/net/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 <net/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));
+
+	log_info("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;
+}
-- 
2.30.2


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

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

Implement function for dhcp command with lwIP variant. Usage and output is
the same as the original command. This code called by compatibility code
between U-Boot and lwIP.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 include/net/lwip.h             | 10 +++++++
 net/lwip/Makefile              |  1 +
 net/lwip/apps/dhcp/lwip-dhcp.c | 51 ++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)
 create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c

diff --git a/include/net/lwip.h b/include/net/lwip.h
index c83b5c8231..2f035280eb 100644
--- a/include/net/lwip.h
+++ b/include/net/lwip.h
@@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
 *         Other value < 0, if error
 */
 int ulwip_dns(char *name, char *varname);
+
+/*
+* This function creates the DHCP request to obtain IP address. If DHCP server
+* returns file name, this file will be downloaded with tftp.  After this
+* function you need to invoke the polling loop to process network communication.
+*
+* Return: 0 if success
+*         Other value < 0, if error
+*/
+int ulwip_dhcp(void);
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index 6d2c00605b..59323fb325 100644
--- a/net/lwip/Makefile
+++ b/net/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/net/lwip/apps/dhcp/lwip-dhcp.c b/net/lwip/apps/dhcp/lwip-dhcp.c
new file mode 100644
index 0000000000..fb7431b248
--- /dev/null
+++ b/net/lwip/apps/dhcp/lwip-dhcp.c
@@ -0,0 +1,51 @@
+// 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 <net/ulwip.h>
+
+static struct dhcp dhcp;
+
+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 (!netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
+		dhcp_set_struct(netif, &dhcp);
+
+	err = dhcp_start(netif);
+	if (err)
+		printf("dhcp_start error %d\n", err);
+
+	return err;
+}
-- 
2.30.2


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

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

Implement function for dhcp command with lwIP variant. Usage and output is
the same as the original command. This code called by compatibility code
between U-Boot and lwIP.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 net/lwip/Makefile              |   1 +
 net/lwip/apps/tftp/Makefile    |  16 ++++
 net/lwip/apps/tftp/lwip-tftp.c | 129 +++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 net/lwip/apps/tftp/Makefile
 create mode 100644 net/lwip/apps/tftp/lwip-tftp.c

diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index 59323fb325..0337d82cf5 100644
--- a/net/lwip/Makefile
+++ b/net/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/net/lwip/apps/tftp/Makefile b/net/lwip/apps/tftp/Makefile
new file mode 100644
index 0000000000..0e50fcad45
--- /dev/null
+++ b/net/lwip/apps/tftp/Makefile
@@ -0,0 +1,16 @@
+
+ccflags-y += -I$(srctree)/net/lwip/port/include
+ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip
+ccflags-y += -I$(obj)
+
+$(obj)/tftp.o: $(obj)/tftp.c
+.PHONY: $(obj)/tftp.c
+$(obj)/tftp.c:
+	cp $(srctree)/net/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/tftp.c
+	cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h
+	cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h
+	cp $(srctree)/net/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/net/lwip/apps/tftp/lwip-tftp.c b/net/lwip/apps/tftp/lwip-tftp.c
new file mode 100644
index 0000000000..290229cb85
--- /dev/null
+++ b/net/lwip/apps/tftp/lwip-tftp.c
@@ -0,0 +1,129 @@
+// 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 <bootstage.h>
+
+#include "lwip/apps/tftp_client.h"
+#include "lwip/apps/tftp_server.h"
+#include <tftp_example.h>
+
+#include <string.h>
+
+#include <net/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)
+{
+	log_info("\ndone\n");
+	log_info("Bytes transferred = %ld (0x%lx hex)\n", size, size);
+
+	bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
+	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);
+		daddr += q->len;
+		size += q->len;
+		log_info("#");
+	}
+
+	return 0;
+}
+
+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));
+
+	log_info("TFTP error: %d (%s)", err, message);
+}
+
+static const struct tftp_context tftp = {
+	tftp_open,
+	tftp_close,
+	tftp_read,
+	tftp_write,
+	tftp_error
+};
+
+int ulwip_tftp(ulong addr, char *fname)
+{
+	void *f = (void *)0x1; /* unused fake file 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) {
+		log_err("error: serverip variable has to be set\n");
+		return CMD_RET_FAILURE;
+	}
+
+	ret = ipaddr_aton(server_ip, &srv);
+	if (!ret) {
+		log_err("error: ipaddr_aton\n");
+		return CMD_RET_FAILURE;
+	}
+
+	log_info("TFTP from server %s; our IP address is %s\n",
+		 server_ip, env_get("ipaddr"));
+	log_info("Filename '%s'.\n", fname);
+	log_info("Load address: 0x%lx\n", daddr);
+	log_info("Loading:");
+
+	bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
+
+	err = tftp_init_client(&tftp);
+	if (!(err == ERR_OK || err == ERR_USE))
+		log_err("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) {
+		log_err("tftp_get err=%d\n", err);
+		return CMD_RET_FAILURE;
+	}
+
+	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] 49+ messages in thread

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

Implement function for wget command with lwIP variant. Usage and output is
the same as the original command. This code called by compatibility code
 between U-Boot and lwIP.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 include/net/lwip.h             |  13 ++++
 net/lwip/Makefile              |   1 +
 net/lwip/apps/http/Makefile    |  13 ++++
 net/lwip/apps/http/lwip-wget.c | 131 +++++++++++++++++++++++++++++++++
 4 files changed, 158 insertions(+)
 create mode 100644 net/lwip/apps/http/Makefile
 create mode 100644 net/lwip/apps/http/lwip-wget.c

diff --git a/include/net/lwip.h b/include/net/lwip.h
index 2f035280eb..f1f2c94fc2 100644
--- a/include/net/lwip.h
+++ b/include/net/lwip.h
@@ -25,3 +25,16 @@ int ulwip_dns(char *name, char *varname);
 *         Other value < 0, if error
 */
 int ulwip_dhcp(void);
+
+/*
+* This function creates the HTTP request to download file from url to the address
+* specified in parameters. After this function you need to invoke the polling
+* loop to process network communication.
+*
+*
+* @addr  start address to download result
+* @url   url in format http://host[:port]/url
+* Return: 0 for success
+*         !0 if error
+*/
+int ulwip_wget(ulong addr, char *url);
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index 0337d82cf5..4c6df94807 100644
--- a/net/lwip/Makefile
+++ b/net/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/net/lwip/apps/http/Makefile b/net/lwip/apps/http/Makefile
new file mode 100644
index 0000000000..3e92b0ef1b
--- /dev/null
+++ b/net/lwip/apps/http/Makefile
@@ -0,0 +1,13 @@
+ccflags-y += -I$(srctree)/net/lwip/port/include
+ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip
+ccflags-y += -I$(obj)
+
+$(obj)/http_clinet.o: $(obj)/http_client.c
+.PHONY: $(obj)/http_client.c
+$(obj)/http_client.c:
+	cp $(srctree)/net/lwip/lwip-external/src/apps/http/http_client.c $(obj)/http_client.c
+	cp $(srctree)/net/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/net/lwip/apps/http/lwip-wget.c b/net/lwip/apps/http/lwip-wget.c
new file mode 100644
index 0000000000..73d82225a2
--- /dev/null
+++ b/net/lwip/apps/http/lwip-wget.c
@@ -0,0 +1,131 @@
+// 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 <vsprintf.h>
+
+#include "http_client.h"
+#include <net/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 unused_err)
+{
+	struct pbuf *q;
+
+	if (!p)
+		return ERR_BUF;
+
+	for (q = p; q != NULL; q = q->next) {
+		memcpy((void *)daddr, q->payload, q->len);
+		log_debug("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) {
+		log_info("\n%d bytes successfully downloaded.\n", rx_content_len);
+		env_set_ulong("filesize", rx_content_len);
+		ulwip_exit(0);
+	} else {
+		log_err("\nhttp eroror: %d\n", httpc_result);
+		ulwip_exit(-1);
+	}
+}
+
+/* http://hostname:port/url */
+static int parse_url(char *url, char *host, u16 *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 = (u16)dectoul(portstr, NULL);
+	} 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 ulwip_wget(ulong addr, char *url)
+{
+	err_t err;
+	u16 port;
+	char server_name[SERVER_NAME_SIZE];
+	httpc_state_t *connection;
+
+	daddr = addr;
+
+	err = parse_url(url, server_name, &port);
+	if (err) {
+		log_err("error parse_url\n");
+		return -1;
+	}
+
+	log_info("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) {
+		log_err("httpc_init_connection failed\n");
+		return err;
+	}
+
+	env_set_hex("fileaddr", addr);
+	return 0;
+}
-- 
2.30.2


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

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

Implement function for ping command with lwIP variant. Usage and output is
the same as the original command. This code called by compatibility code
between U-Boot and lwIP. ping uses lwIP contrib/apps/ping/ping.c code.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 include/net/lwip.h             | 28 ++++++++++++++++++++++++-
 net/lwip/Makefile              |  1 +
 net/lwip/apps/ping/Makefile    | 11 ++++++++++
 net/lwip/apps/ping/lwip_ping.c | 37 ++++++++++++++++++++++++++++++++++
 net/lwip/apps/ping/lwip_ping.h | 15 ++++++++++++++
 net/lwip/apps/ping/ping.h      | 19 +++++++++++++++++
 6 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 net/lwip/apps/ping/Makefile
 create mode 100644 net/lwip/apps/ping/lwip_ping.c
 create mode 100644 net/lwip/apps/ping/lwip_ping.h
 create mode 100644 net/lwip/apps/ping/ping.h

diff --git a/include/net/lwip.h b/include/net/lwip.h
index f1f2c94fc2..e928676b36 100644
--- a/include/net/lwip.h
+++ b/include/net/lwip.h
@@ -2,7 +2,8 @@
 
 int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
 		char *const argv[]);
-
+int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
+		 char *const argv[]);
 /*
 * This function creates the DNS request to resolve a domain host name. Function
 * can return immediately if previous request was cached or it might require
@@ -38,3 +39,28 @@ int ulwip_dhcp(void);
 *         !0 if error
 */
 int ulwip_wget(ulong addr, char *url);
+
+/**
+ * ulwip_tftp() - load file with tftp
+ *
+ * Load file with tftp to specific address
+ *
+ * @param addr - address to store downloaded file
+ * @param filename - file name on remote tftp server to download
+ *
+ *
+ * @return 0 if success, !0 if error
+ */
+int ulwip_tftp(ulong addr, const char *filename);
+
+/*
+* This function creates the ping for  address provided in parameters.
+* After this function you need to invoke the polling
+* loop to process network communication.
+*
+*
+* @ping_addr  start address to download result
+* Return: 0 for success
+*         !0 if error
+*/
+int ulwip_ping(char *ping_addr);
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index 4c6df94807..8b3e843426 100644
--- a/net/lwip/Makefile
+++ b/net/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/net/lwip/apps/ping/Makefile b/net/lwip/apps/ping/Makefile
new file mode 100644
index 0000000000..dc63feb7b5
--- /dev/null
+++ b/net/lwip/apps/ping/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -I$(srctree)/net/lwip/port/include
+ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip
+ccflags-y += -I$(obj)
+
+.PHONY: $(obj)/ping.c
+$(obj)/ping.o: $(obj)/ping.c
+$(obj)/ping.c:
+	cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c b/net/lwip/apps/ping/lwip_ping.c
new file mode 100644
index 0000000000..611fcaf591
--- /dev/null
+++ b/net/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 "lwip_ping.h"
+
+static ip_addr_t ip_target;
+
+static int ulwip_ping_tmo(void)
+{
+
+	log_err("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target));
+	return 1;
+}
+
+int ulwip_ping(char *ping_addr)
+{
+	int err;
+
+	err = ipaddr_aton(ping_addr, &ip_target);
+	if (!err) {
+		log_err("wrong ping addr string \"%s\" \n", ping_addr);
+		return -1;
+	}
+
+	ulwip_set_tmo(ulwip_ping_tmo);
+
+	ping_init(&ip_target);
+	ping_send_now();
+
+	return 0;
+}
diff --git a/net/lwip/apps/ping/lwip_ping.h b/net/lwip/apps/ping/lwip_ping.h
new file mode 100644
index 0000000000..0374f07d9e
--- /dev/null
+++ b/net/lwip/apps/ping/lwip_ping.h
@@ -0,0 +1,15 @@
+/* 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>
+
+void ping_raw_init(void);
+void ping_send_now(void);
+
+#endif /* LWIP_PING_H */
diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
new file mode 100644
index 0000000000..006a18c658
--- /dev/null
+++ b/net/lwip/apps/ping/ping.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <net/ulwip.h>
+#include "lwip/ip_addr.h"
+
+#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
+#define PING_RESULT(cond) { \
+	if (cond == 1) { \
+		printf("host %s a alive\n", ipaddr_ntoa(addr)); \
+		printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
+		ulwip_exit(0); \
+	} else { \
+		printf("ping failed; host %s in not alive\n",\
+		       ipaddr_ntoa(addr)); \
+		ulwip_exit(-1); \
+	} \
+     } while (0);
+
+void ping_init(const ip_addr_t *ping_addr);
-- 
2.30.2


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

* [PATCHv6 08/14] net/lwip: add lwIP configuration
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (6 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 07/14] net/lwip: implement ping cmd Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot Maxim Uvarov
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 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>
---
 net/lwip/lwipopts.h | 195 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 195 insertions(+)
 create mode 100644 net/lwip/lwipopts.h

diff --git a/net/lwip/lwipopts.h b/net/lwip/lwipopts.h
new file mode 100644
index 0000000000..23d87e3f65
--- /dev/null
+++ b/net/lwip/lwipopts.h
@@ -0,0 +1,195 @@
+/* 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 LWIP_IPV6			0
+
+#define MEM_ALIGNMENT                   1
+#define MEM_SIZE                        1600
+
+#define MEMP_NUM_PBUF                   4
+#define MEMP_NUM_RAW_PCB                2
+#define MEMP_NUM_UDP_PCB                4
+#define MEMP_NUM_TCP_PCB                2
+#define MEMP_NUM_TCP_PCB_LISTEN         2
+#define MEMP_NUM_TCP_SEG                16
+#define MEMP_NUM_REASSDATA              1
+#define MEMP_NUM_ARP_QUEUE              2
+#define MEMP_NUM_SYS_TIMEOUT            4
+#define MEMP_NUM_NETBUF                 2
+#define MEMP_NUM_NETCONN               32
+#define MEMP_NUM_TCPIP_MSG_API          8
+#define MEMP_NUM_TCPIP_MSG_INPKT        8
+#define PBUF_POOL_SIZE                  8
+
+#define LWIP_ARP                        1
+
+#define 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                  14
+#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN)
+
+#define LWIP_HAVE_LOOPIF                0
+
+#define LWIP_NETCONN                    0
+#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1
+
+#define LWIP_SOCKET                     0
+#define SO_REUSE                        0
+
+#define LWIP_STATS                      0
+
+#define PPP_SUPPORT                     0
+
+#define LWIP_TCPIP_CORE_LOCKING		0
+
+#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] 49+ messages in thread

* [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (7 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 08/14] net/lwip: add lwIP configuration Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-16  9:01   ` Ilias Apalodimas
  2023-08-14 13:32 ` [PATCHv6 10/14] net/lwip: update .gitignore with lwIP Maxim Uvarov
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

Implement network lwIP interface connected to the U-boot.
Keep original file structure widely used fro lwIP ports.
(i.e. port/if.c port/sys-arch.c).

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 net/eth-uclass.c                      |   8 +
 net/lwip/port/if.c                    | 260 ++++++++++++++++++++++++++
 net/lwip/port/include/arch/cc.h       |  39 ++++
 net/lwip/port/include/arch/sys_arch.h |  56 ++++++
 net/lwip/port/include/limits.h        |   0
 net/lwip/port/sys-arch.c              |  20 ++
 6 files changed, 383 insertions(+)
 create mode 100644 net/lwip/port/if.c
 create mode 100644 net/lwip/port/include/arch/cc.h
 create mode 100644 net/lwip/port/include/arch/sys_arch.h
 create mode 100644 net/lwip/port/include/limits.h
 create mode 100644 net/lwip/port/sys-arch.c

diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index c393600fab..6625f6d8a5 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
 struct eth_device_priv {
 	enum eth_state_t state;
 	bool running;
+	ulwip ulwip;
 };
 
 /**
@@ -347,6 +348,13 @@ int eth_init(void)
 	return ret;
 }
 
+struct ulwip *eth_lwip_priv(struct udevice *current)
+{
+	struct eth_device_priv *priv = dev_get_uclass_priv(current);
+
+	return &priv->ulwip;
+}
+
 void eth_halt(void)
 {
 	struct udevice *current;
diff --git a/net/lwip/port/if.c b/net/lwip/port/if.c
new file mode 100644
index 0000000000..625a9c10bf
--- /dev/null
+++ b/net/lwip/port/if.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net/eth.h>
+#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/ethip6.h"
+
+#include "lwip/ip.h"
+
+#define IFNAME0 'e'
+#define IFNAME1 '0'
+
+static struct pbuf *low_level_input(struct netif *netif);
+
+int ulwip_enabled(void)
+{
+	struct ulwip *ulwip;
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	return ulwip->init_done;
+}
+
+int ulwip_in_loop(void)
+{
+	struct ulwip *ulwip;
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	return ulwip->loop;
+}
+
+void ulwip_loop_set(int loop)
+{
+	struct ulwip *ulwip;
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	ulwip->loop = loop;
+}
+
+void ulwip_exit(int err)
+{
+	struct ulwip *ulwip;
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	ulwip->loop = 0;
+	ulwip->err = err;
+}
+
+int ulwip_app_get_err(void)
+{
+	struct ulwip *ulwip;
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	return ulwip->err;
+}
+
+struct ulwip_if {
+};
+
+#define LWIP_PORT_INIT_NETMASK(addr)  IP4_ADDR((addr), 255, 255, 255, 0)
+
+void ulwip_poll(void)
+{
+	struct pbuf *p;
+	int err;
+	struct netif *netif = netif_get_by_index(1);
+
+	p = low_level_input(netif);
+	if (!p) {
+		log_err("error p = low_level_input = NULL\n");
+		return;
+	}
+
+	/* ethernet_input always returns ERR_OK */
+	err = ethernet_input(p, netif);
+	if (err)
+		log_err("ip4_input err %d\n", err);
+
+	return;
+}
+
+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;
+
+	/* We allocate a pbuf chain of pbufs from the pool. */
+	p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+	if (p) {
+		/* 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();
+
+		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) {
+		log_err("eth_send error %d\n", err);
+		return ERR_ABRT;
+	}
+	return ERR_OK;
+}
+
+err_t ulwip_if_init(struct netif *netif)
+{
+	struct ulwip_if *uif;
+	struct ulwip *ulwip;
+
+	uif = malloc(sizeof(struct ulwip_if));
+	if (!uif) {
+		log_err("uif: 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
+#if LWIP_IPV6
+	netif->output_ip6 = ethip6_output;
+#endif
+
+	netif->linkoutput = low_level_output;
+	netif->mtu = 1500;
+	netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	ulwip->init_done = 1;
+	if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
+		log_info("Initialized LWIP stack\n");
+	}
+
+	return ERR_OK;
+}
+
+int ulwip_init(void)
+{
+	ip4_addr_t ipaddr, netmask, gw;
+	struct netif *unetif;
+	struct ulwip *ulwip;
+	int ret;
+
+	ret = eth_init();
+	if (ret) {
+		log_err("eth_init error %d\n", ret);
+		return ERR_IF;
+	}
+
+	ulwip = eth_lwip_priv(eth_get_dev());
+	if (ulwip->init_done)
+		return CMD_RET_SUCCESS;
+
+	unetif = malloc(sizeof(struct netif));
+	if (!unetif)
+		return ERR_MEM;
+	memset(unetif, 0, sizeof(struct netif));
+
+	ip4_addr_set_zero(&gw);
+	ip4_addr_set_zero(&ipaddr);
+	ip4_addr_set_zero(&netmask);
+
+	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(unetif, &ipaddr, &netmask, &gw,
+		       unetif, ulwip_if_init, ethernetif_input))
+		printf("err: netif_add failed!\n");
+
+	netif_set_up(unetif);
+	netif_set_link_up(unetif);
+#if LWIP_IPV6
+	netif_create_ip6_linklocal_address(unetif, 1);
+	printf("             IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(unetif, 0)));
+#endif /* LWIP_IPV6 */
+
+	return CMD_RET_SUCCESS;
+}
+
+/* placeholder, not used now */
+void ulwip_destroy(void)
+{
+}
diff --git a/net/lwip/port/include/arch/cc.h b/net/lwip/port/include/arch/cc.h
new file mode 100644
index 0000000000..55f7787ce1
--- /dev/null
+++ b/net/lwip/port/include/arch/cc.h
@@ -0,0 +1,39 @@
+/* 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>
+//#include <stdlib.h>    /* getenv, atoi */
+#include <vsprintf.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)
+
+#define atoi(str) (int)dectoul(str, NULL)
+
+#define LWIP_ERR_T int
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/net/lwip/port/include/arch/sys_arch.h b/net/lwip/port/include/arch/sys_arch.h
new file mode 100644
index 0000000000..92a8560d49
--- /dev/null
+++ b/net/lwip/port/include/arch/sys_arch.h
@@ -0,0 +1,56 @@
+/* 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;
+
+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;
+};
+
+#endif /* LWIP_ARCH_SYS_ARCH_H */
diff --git a/net/lwip/port/include/limits.h b/net/lwip/port/include/limits.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/net/lwip/port/sys-arch.c b/net/lwip/port/sys-arch.c
new file mode 100644
index 0000000000..609eeccf8c
--- /dev/null
+++ b/net/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] 49+ messages in thread

* [PATCHv6 10/14] net/lwip: update .gitignore with lwIP
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (8 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 11/14] net/lwip: connection between cmd and lwip apps Maxim Uvarov
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

ignore lwIP library code and reused files from the lwIP.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 net/lwip/.gitignore | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 net/lwip/.gitignore

diff --git a/net/lwip/.gitignore b/net/lwip/.gitignore
new file mode 100644
index 0000000000..7b5dacce90
--- /dev/null
+++ b/net/lwip/.gitignore
@@ -0,0 +1,8 @@
+lwip-external
+apps/ping/ping.c
+apps/http/http_client.c
+apps/http/http_client.h
+apps/tftp/tftp.c
+apps/tftp/tftp_client.h
+apps/tftp/tftp_common.h
+apps/tftp/tftp_example.h
-- 
2.30.2


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

* [PATCHv6 11/14] net/lwip: connection between cmd and lwip apps
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (9 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 10/14] net/lwip: update .gitignore with lwIP Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-16  9:12   ` Ilias Apalodimas
  2023-08-14 13:32 ` [PATCHv6 12/14] net/lwip: replace original net commands with lwip Maxim Uvarov
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 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>
---
 cmd/Makefile   |   1 +
 cmd/net-lwip.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 307 insertions(+)
 create mode 100644 cmd/net-lwip.c

diff --git a/cmd/Makefile b/cmd/Makefile
index 9bebf321c3..6ab6b16aab 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -128,6 +128,7 @@ endif
 obj-$(CONFIG_CMD_MUX) += mux.o
 obj-$(CONFIG_CMD_NAND) += nand.o
 obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NET) += net-lwip.o
 obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
 obj-$(CONFIG_CMD_ONENAND) += onenand.o
 obj-$(CONFIG_CMD_OSD) += osd.o
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
new file mode 100644
index 0000000000..46fe4f091f
--- /dev/null
+++ b/cmd/net-lwip.c
@@ -0,0 +1,306 @@
+// 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 "net/lwip.h"
+#include "net/ulwip.h"
+
+static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc,
+		      char *const argv[])
+{
+	if (!ulwip_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);
+}
+
+int ulwip_loop(void)
+{
+	int ret = CMD_RET_FAILURE;
+
+	ulwip_loop_set(1);
+	if (!net_loop(LWIP))
+		ret = CMD_RET_SUCCESS;
+	ulwip_loop_set(0);
+	return ret;
+}
+
+#if defined(CONFIG_CMD_PING)
+int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
+		 char *const argv[])
+{
+	int ret;
+
+	if (argc < 2) {
+		printf("argc = %d, error\n", argc);
+		return CMD_RET_USAGE;
+	}
+
+	ret = ulwip_init();
+	if (ret) {
+		log_err("ulwip_init err %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Using %s device\n", eth_get_name());
+	printf("pinging addr: %s\n", argv[1]);
+
+	net_set_timeout_handler(1000UL, ulwip_timeout_handler);
+
+	if (ulwip_ping(argv[1])) {
+		printf("ping init fail\n");
+		return CMD_RET_FAILURE;
+	}
+
+	return ulwip_loop();
+}
+#endif /* CONFIG_CMD_PING */
+
+#if defined(CONFIG_CMD_WGET)
+int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
+		 char *const argv[])
+{
+	char *url;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	url = argv[1];
+
+	ret = ulwip_init();
+	if (ret) {
+		log_err("ulwip_init err %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	ret = ulwip_wget(image_load_addr, url);
+	if (ret) {
+		log_err("lwip_wget err %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+
+	return ulwip_loop();
+}
+#endif
+
+#if defined(CONFIG_CMD_TFTPBOOT)
+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;
+	}
+
+	ret = ulwip_init();
+	if (ret) {
+		log_err("ulwip_init err %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	ret = ulwip_tftp(image_load_addr, filename);
+	if (ret)
+		return ret;
+
+	return ulwip_loop();
+}
+#endif /* CONFIG_CMD_TFTPBOOT */
+
+#if defined(CONFIG_CMD_DHCP)
+int do_lwip_dhcp(void)
+{
+	int ret;
+	char *filename;
+
+	ret = ulwip_init();
+	if (ret) {
+		log_err("ulwip_init err %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	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) {
+			log_notice("no bootfile\n");
+			return CMD_RET_SUCCESS;
+		}
+
+		ret = ulwip_init();
+		if (ret) {
+			log_err("ulwip_init err %d\n", ret);
+			return CMD_RET_FAILURE;
+		}
+
+		net_set_timeout_handler(20000UL, ulwip_timeout_handler);
+		ulwip_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; /* lwip/err.h */
+
+	if (argc == 1)
+		return CMD_RET_USAGE;
+
+	name = argv[1];
+
+	if (argc == 3)
+		varname = argv[2];
+	else
+		varname = NULL;
+
+	ret = ulwip_init();
+	if (ret) {
+		log_err("ulwip_init err %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	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(init, 1, 0, do_lwip_init,
+			 "initialize lwip stack", ""),
+#if defined(CONFIG_CMD_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",
+	"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"
+	);
-- 
2.30.2


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

* [PATCHv6 12/14] net/lwip: replace original net commands with lwip
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (10 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 11/14] net/lwip: connection between cmd and lwip apps Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 13/14] net/lwip: split net.h to net.h, arp.h and eth.h Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 14/14] net/lwip: drop old net/wget Maxim Uvarov
  13 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 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 | 18 +++++++---
 boot/bootmeth_pxe.c | 21 ++++++-----
 cmd/net.c           | 86 +++++----------------------------------------
 cmd/pxe.c           | 19 +++++-----
 include/net.h       |  8 +++--
 include/net/ulwip.h | 68 +++++++++++++++++++++++++++++++++++
 6 files changed, 117 insertions(+), 103 deletions(-)
 create mode 100644 include/net/ulwip.h

diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 1c9f2b1e2f..ea9f3af0f7 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -20,6 +20,8 @@
 #include <mapmem.h>
 #include <mmc.h>
 #include <net.h>
+#include <net/lwip.h>
+#include <net/ulwip.h>
 #include <pxe_utils.h>
 #include <linux/sizes.h>
 
@@ -319,9 +321,7 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
 
 static int distro_efi_read_bootflow_net(struct bootflow *bflow)
 {
-	char file_addr[17], fname[256];
-	char *tftp_argv[] = {"tftp", file_addr, fname, NULL};
-	struct cmd_tbl cmdtp = {};	/* dummy */
+	char fname[256];
 	const char *addr_str, *fdt_addr_str;
 	int ret, arch, size;
 	ulong addr, fdt_addr;
@@ -368,7 +368,6 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow)
 	if (!fdt_addr_str)
 		return log_msg_ret("fdt", -EINVAL);
 	fdt_addr = hextoul(fdt_addr_str, NULL);
-	sprintf(file_addr, "%lx", fdt_addr);
 
 	/* We only allow the first prefix with PXE */
 	ret = distro_efi_get_fdt_name(fname, sizeof(fname), 0);
@@ -379,7 +378,16 @@ 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)) {
+	ret = ulwip_init();
+	if (ret)
+		return log_msg_ret("ulwip_init", ret);
+
+	ret = ulwip_tftp(fdt_addr, fname);
+	if (ret)
+		return log_msg_ret("ulwip_tftp", ret);
+
+	ret = ulwip_loop();
+	if (!ret) {
 		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 8d489a11aa..fc6aabaa18 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -21,6 +21,8 @@
 #include <mapmem.h>
 #include <mmc.h>
 #include <net.h>
+#include <net/ulwip.h>
+#include <net/lwip.h>
 #include <pxe_utils.h>
 
 static int extlinux_pxe_getfile(struct pxe_context *ctx, const char *file_path,
@@ -116,18 +118,21 @@ static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow,
 				  const char *file_path, ulong addr,
 				  ulong *sizep)
 {
-	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
-	struct pxe_context *ctx = dev_get_priv(dev);
-	char file_addr[17];
 	ulong size;
 	int ret;
 
-	sprintf(file_addr, "%lx", addr);
-	tftp_argv[1] = file_addr;
-	tftp_argv[2] = (void *)file_path;
+	ret = ulwip_init();
+	if (ret)
+		return log_msg_ret("ulwip_init", ret);
+
+	ret = ulwip_tftp(addr, file_path);
+	if (ret)
+		return log_msg_ret("ulwip_tftp", ret);
+
+	ret = ulwip_loop();
+	if (ret)
+		return log_msg_ret("ulwip_loop", ret);
 
-	if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
-		return -ENOENT;
 	ret = pxe_get_file_size(&size);
 	if (ret)
 		return log_msg_ret("tftp", 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..d44df428d2 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -8,6 +8,7 @@
 #include <command.h>
 #include <fs.h>
 #include <net.h>
+#include <net/lwip.h>
 #include <net6.h>
 #include <malloc.h>
 
@@ -29,21 +30,19 @@ const char *pxe_default_paths[] = {
 static int do_get_tftp(struct pxe_context *ctx, const char *file_path,
 		       char *file_addr, ulong *sizep)
 {
-	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
+	ulong addr;
+	char *end;
 	int ret;
-	int num_args;
 
-	tftp_argv[1] = file_addr;
-	tftp_argv[2] = (void *)file_path;
+	addr = hextoul(file_addr, &end);
+
 	if (ctx->use_ipv6) {
-		tftp_argv[3] = USE_IP6_CMD_PARAM;
-		num_args = 4;
-	} else {
-		num_args = 3;
+		/* @todo: check and fix me, here */
 	}
 
-	if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv))
-		return -ENOENT;
+	ret = ulwip_tftp(addr, file_path);
+	if (ret)
+		return log_msg_ret("tftp", ret);
 
 	ret = pxe_get_file_size(sizep);
 	if (ret)
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/ulwip.h b/include/net/ulwip.h
new file mode 100644
index 0000000000..39d61fe446
--- /dev/null
+++ b/include/net/ulwip.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/**
+ * ulwip_init() - initialize lwIP network stack
+ *
+ * @return 0 if success, !0 if error
+ */
+int ulwip_init(void);
+
+/**
+ * ulwip_enabled() - check if lwIP network stack was initialized
+ *
+ * @return 1 lwip initialized, 0 if not yet initialized
+ */
+int ulwip_enabled(void);
+
+/**
+ * ulwip_in_loop() - lwIP controls packet net loop
+ *
+ * @return 1 lwIP owns packet loop, 0 lwip does not own packet loop
+ */
+int ulwip_in_loop(void);
+
+/**
+ * ulwip_loop_set() - make loop to be used by lwIP
+ *
+ * Function is used to make lwIP control network pool.
+ *
+ * @param loop 1. Rx packets go to lwIP 2. Rx packets go to the original stack.
+ */
+void ulwip_loop_set(int loop);
+
+/**
+ * ulwip_exit() - exit from lwIP with a return code
+ *
+ * Exit from lwIP application back to the U-Boot with specific error code.
+ *
+ * @param err error code to return
+ */
+void ulwip_exit(int err);
+
+/**
+ * ulwip_poll() - polling function to feed lwIP with ethernet packet
+ *
+ * Function takes network packet and passes it to lwIP network stack
+ */
+void ulwip_poll(void);
+
+/**
+ * ulwip_app_get_err() - return error code from lwIP application
+ *
+ * @return error code
+ */
+int ulwip_app_get_err(void);
+
+/**
+ * ulwip_set_tmo() - set application timeout function to trap lwIP application
+ *
+ * lwIP cmd compatibility code does initialization for application then gives
+ * control to the packet loop. To keep ability for control return code and
+ * application state after application work special handler can be registered
+ * with this call.
+ *
+ * @param tmo - function to call if timeout happen.
+ */
+void ulwip_set_tmo(int (*tmo)(void));
+
+int ulwip_loop(void);
-- 
2.30.2


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

* [PATCHv6 13/14] net/lwip: split net.h to net.h, arp.h and eth.h
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (11 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 12/14] net/lwip: replace original net commands with lwip Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  2023-08-14 13:32 ` [PATCHv6 14/14] net/lwip: drop old net/wget Maxim Uvarov
  13 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 UTC (permalink / raw)
  To: u-boot
  Cc: pbrobinson, ilias.apalodimas, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Maxim Uvarov

current net.h has ethernet and protocol definitions. Protocol definitions
overlap with lwIP protocol definitions and net.h can not be included from
lwIP code. Splitting on logical blocks makes that work.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 include/net.h     | 189 +--------------------------------------------
 include/net/arp.h |   7 ++
 include/net/eth.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 201 insertions(+), 185 deletions(-)
 create mode 100644 include/net/arp.h
 create mode 100644 include/net/eth.h

diff --git a/include/net.h b/include/net.h
index de7baeb121..780c51fab9 100644
--- a/include/net.h
+++ b/include/net.h
@@ -20,6 +20,7 @@
 #include <time.h>
 #include <linux/if_ether.h>
 #include <rand.h>
+#include  <net/arp.h>
 
 struct bd_info;
 struct cmd_tbl;
@@ -30,25 +31,6 @@ struct udevice;
 #define DEBUG_NET_PKT 0		/* Packets on info on the network at large */
 #define DEBUG_INT_STATE 0	/* Internal network state changes */
 
-/*
- *	The number of receive packet buffers, and the required packet buffer
- *	alignment in memory.
- *
- */
-#define PKTBUFSRX	CONFIG_SYS_RX_ETH_BUFFER
-#define PKTALIGN	ARCH_DMA_MINALIGN
-
-/* Number of packets processed together */
-#define ETH_PACKETS_BATCH_RECV	32
-
-/* ARP hardware address length */
-#define ARP_HLEN 6
-/*
- * The size of a MAC address in string form, each digit requires two chars
- * and five separator characters to form '00:00:00:00:00:00'.
- */
-#define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1)
-
 /* IPv4 addresses are always 32 bits in size */
 struct in_addr {
 	__be32 s_addr;
@@ -112,150 +94,7 @@ typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport,
  */
 typedef void	thand_f(void);
 
-enum eth_state_t {
-	ETH_STATE_INIT,
-	ETH_STATE_PASSIVE,
-	ETH_STATE_ACTIVE
-};
-
-/**
- * struct eth_pdata - Platform data for Ethernet MAC controllers
- *
- * @iobase: The base address of the hardware registers
- * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
- * @phy_interface: PHY interface to use - see PHY_INTERFACE_MODE_...
- * @max_speed: Maximum speed of Ethernet connection supported by MAC
- * @priv_pdata: device specific plat
- */
-struct eth_pdata {
-	phys_addr_t iobase;
-	unsigned char enetaddr[ARP_HLEN];
-	int phy_interface;
-	int max_speed;
-	void *priv_pdata;
-};
-
-enum eth_recv_flags {
-	/*
-	 * Check hardware device for new packets (otherwise only return those
-	 * which are already in the memory buffer ready to process)
-	 */
-	ETH_RECV_CHECK_DEVICE		= 1 << 0,
-};
-
-/**
- * struct eth_ops - functions of Ethernet MAC controllers
- *
- * start: Prepare the hardware to send and receive packets
- * send: Send the bytes passed in "packet" as a packet on the wire
- * recv: Check if the hardware received a packet. If so, set the pointer to the
- *	 packet buffer in the packetp parameter. If not, return an error or 0 to
- *	 indicate that the hardware receive FIFO is empty. If 0 is returned, the
- *	 network stack will not process the empty packet, but free_pkt() will be
- *	 called if supplied
- * free_pkt: Give the driver an opportunity to manage its packet buffer memory
- *	     when the network stack is finished processing it. This will only be
- *	     called when no error was returned from recv - optional
- * stop: Stop the hardware from looking for packets - may be called even if
- *	 state == PASSIVE
- * mcast: Join or leave a multicast group (for TFTP) - optional
- * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
- *		 on some platforms like ARM). This function expects the
- *		 eth_pdata::enetaddr field to be populated. The method can
- *		 return -ENOSYS to indicate that this is not implemented for
-		 this hardware - optional.
- * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
- *		    ROM on the board. This is how the driver should expose it
- *		    to the network stack. This function should fill in the
- *		    eth_pdata::enetaddr field - optional
- * set_promisc: Enable or Disable promiscuous mode
- * get_sset_count: Number of statistics counters
- * get_string: Names of the statistic counters
- * get_stats: The values of the statistic counters
- */
-struct eth_ops {
-	int (*start)(struct udevice *dev);
-	int (*send)(struct udevice *dev, void *packet, int length);
-	int (*recv)(struct udevice *dev, int flags, uchar **packetp);
-	int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
-	void (*stop)(struct udevice *dev);
-	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
-	int (*write_hwaddr)(struct udevice *dev);
-	int (*read_rom_hwaddr)(struct udevice *dev);
-	int (*set_promisc)(struct udevice *dev, bool enable);
-	int (*get_sset_count)(struct udevice *dev);
-	void (*get_strings)(struct udevice *dev, u8 *data);
-	void (*get_stats)(struct udevice *dev, u64 *data);
-};
-
-#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
-
-struct udevice *eth_get_dev(void); /* get the current device */
-/*
- * The devname can be either an exact name given by the driver or device tree
- * or it can be an alias of the form "eth%d"
- */
-struct udevice *eth_get_dev_by_name(const char *devname);
-unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
-
-/* Used only when NetConsole is enabled */
-int eth_is_active(struct udevice *dev); /* Test device for active state */
-int eth_init_state_only(void); /* Set active state */
-void eth_halt_state_only(void); /* Set passive state */
-
-int eth_initialize(void);		/* Initialize network subsystem */
-void eth_try_another(int first_restart);	/* Change the device */
-void eth_set_current(void);		/* set nterface to ethcur var */
-
-int eth_get_dev_index(void);		/* get the device index */
-
-/**
- * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
- *
- * This sets up an environment variable with the given MAC address (@enetaddr).
- * The environment variable to be set is defined by <@base_name><@index>addr.
- * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
- * eth1addr, etc.
- *
- * @base_name:  Base name for variable, typically "eth"
- * @index:      Index of interface being updated (>=0)
- * @enetaddr:   Pointer to MAC address to put into the variable
- * Return: 0 if OK, other value on error
- */
-int eth_env_set_enetaddr_by_index(const char *base_name, int index,
-				 uchar *enetaddr);
-
-
-/*
- * Initialize USB ethernet device with CONFIG_DM_ETH
- * Returns:
- *	0 is success, non-zero is error status.
- */
-int usb_ether_init(void);
-
-/*
- * Get the hardware address for an ethernet interface .
- * Args:
- *	base_name - base name for device (normally "eth")
- *	index - device index number (0 for first)
- *	enetaddr - returns 6 byte hardware address
- * Returns:
- *	Return true if the address is valid.
- */
-int eth_env_get_enetaddr_by_index(const char *base_name, int index,
-				 uchar *enetaddr);
-
-int eth_init(void);			/* Initialize the device */
-int eth_send(void *packet, int length);	   /* Send a packet */
-
-#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
-int eth_receive(void *packet, int length); /* Receive a packet*/
-extern void (*push_packet)(void *packet, int length);
-#endif
-int eth_rx(void);			/* Check for received packets */
-void eth_halt(void);			/* stop SCC */
-const char *eth_get_name(void);		/* get name of current device */
-int eth_mcast_join(struct in_addr mcast_addr, int join);
+#include <net/eth.h>
 
 /**********************************************************************/
 /*
@@ -495,16 +334,6 @@ extern char	net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN];	/* Our root path */
 /* Indicates whether the pxe path prefix / config file was specified in dhcp option */
 extern char *pxelinux_configfile;
 /** END OF BOOTP EXTENTIONS **/
-extern u8		net_ethaddr[ARP_HLEN];		/* Our ethernet address */
-extern u8		net_server_ethaddr[ARP_HLEN];	/* Boot server enet address */
-extern struct in_addr	net_ip;		/* Our    IP addr (0 = unknown) */
-extern struct in_addr	net_server_ip;	/* Server IP addr (0 = unknown) */
-extern uchar		*net_tx_packet;		/* THE transmit packet */
-extern uchar		*net_rx_packets[PKTBUFSRX]; /* Receive packets */
-extern uchar		*net_rx_packet;		/* Current receive packet */
-extern int		net_rx_packet_len;	/* Current rx packet length */
-extern const u8		net_bcast_ethaddr[ARP_HLEN];	/* Ethernet broadcast address */
-extern const u8		net_null_ethaddr[ARP_HLEN];
 
 #define VLAN_NONE	4095			/* untagged */
 #define VLAN_IDMASK	0x0fff			/* mask of valid vlan id */
@@ -557,6 +386,8 @@ extern struct in_addr	net_ntp_server;		/* the ip address to NTP */
 extern int net_ntp_time_offset;			/* offset time from UTC */
 #endif
 
+int eth_mcast_join(struct in_addr mcast_addr, int join);
+
 /* Initialize the network adapter */
 int net_init(void);
 int net_loop(enum proto_t);
@@ -827,18 +658,6 @@ static inline void net_random_ethaddr(uchar *addr)
 	addr[0] |= 0x02;	/* set local assignment bit (IEEE802) */
 }
 
-/**
- * string_to_enetaddr() - Parse a MAC address
- *
- * Convert a string MAC address
- *
- * Implemented in lib/net_utils.c (built unconditionally)
- *
- * @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit
- *	hex value
- * @enetaddr: Place to put MAC address (6 bytes)
- */
-void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
 
 /* Convert an IP address to a string */
 void ip_to_string(struct in_addr x, char *s);
diff --git a/include/net/arp.h b/include/net/arp.h
new file mode 100644
index 0000000000..f614f0ef78
--- /dev/null
+++ b/include/net/arp.h
@@ -0,0 +1,7 @@
+/* ARP hardware address length */
+#define ARP_HLEN 6
+/*
+ * The size of a MAC address in string form, each digit requires two chars
+ * and five separator characters to form '00:00:00:00:00:00'.
+ */
+#define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1)
diff --git a/include/net/eth.h b/include/net/eth.h
new file mode 100644
index 0000000000..17552bca81
--- /dev/null
+++ b/include/net/eth.h
@@ -0,0 +1,190 @@
+#include <net/arp.h>
+
+struct udevice;
+
+enum eth_state_t {
+	ETH_STATE_INIT,
+	ETH_STATE_PASSIVE,
+	ETH_STATE_ACTIVE
+};
+
+/**
+ * struct eth_pdata - Platform data for Ethernet MAC controllers
+ *
+ * @iobase: The base address of the hardware registers
+ * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env
+ * @phy_interface: PHY interface to use - see PHY_INTERFACE_MODE_...
+ * @max_speed: Maximum speed of Ethernet connection supported by MAC
+ * @priv_pdata: device specific plat
+ */
+struct eth_pdata {
+	phys_addr_t iobase;
+	unsigned char enetaddr[ARP_HLEN];
+	int phy_interface;
+	int max_speed;
+	void *priv_pdata;
+};
+
+enum eth_recv_flags {
+	/*
+	 * Check hardware device for new packets (otherwise only return those
+	 * which are already in the memory buffer ready to process)
+	 */
+	ETH_RECV_CHECK_DEVICE		= 1 << 0,
+};
+
+/**
+ * struct eth_ops - functions of Ethernet MAC controllers
+ *
+ * start: Prepare the hardware to send and receive packets
+ * send: Send the bytes passed in "packet" as a packet on the wire
+ * recv: Check if the hardware received a packet. If so, set the pointer to the
+ *	 packet buffer in the packetp parameter. If not, return an error or 0 to
+ *	 indicate that the hardware receive FIFO is empty. If 0 is returned, the
+ *	 network stack will not process the empty packet, but free_pkt() will be
+ *	 called if supplied
+ * free_pkt: Give the driver an opportunity to manage its packet buffer memory
+ *	     when the network stack is finished processing it. This will only be
+ *	     called when no error was returned from recv - optional
+ * stop: Stop the hardware from looking for packets - may be called even if
+ *	 state == PASSIVE
+ * mcast: Join or leave a multicast group (for TFTP) - optional
+ * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux
+ *		 on some platforms like ARM). This function expects the
+ *		 eth_pdata::enetaddr field to be populated. The method can
+ *		 return -ENOSYS to indicate that this is not implemented for
+		 this hardware - optional.
+ * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a
+ *		    ROM on the board. This is how the driver should expose it
+ *		    to the network stack. This function should fill in the
+ *		    eth_pdata::enetaddr field - optional
+ * set_promisc: Enable or Disable promiscuous mode
+ * get_sset_count: Number of statistics counters
+ * get_string: Names of the statistic counters
+ * get_stats: The values of the statistic counters
+ */
+struct eth_ops {
+	int (*start)(struct udevice *dev);
+	int (*send)(struct udevice *dev, void *packet, int length);
+	int (*recv)(struct udevice *dev, int flags, uchar **packetp);
+	int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
+	void (*stop)(struct udevice *dev);
+	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+	int (*write_hwaddr)(struct udevice *dev);
+	int (*read_rom_hwaddr)(struct udevice *dev);
+	int (*set_promisc)(struct udevice *dev, bool enable);
+	int (*get_sset_count)(struct udevice *dev);
+	void (*get_strings)(struct udevice *dev, u8 *data);
+	void (*get_stats)(struct udevice *dev, u64 *data);
+};
+
+#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
+
+struct udevice *eth_get_dev(void); /* get the current device */
+/*
+ * The devname can be either an exact name given by the driver or device tree
+ * or it can be an alias of the form "eth%d"
+ */
+struct udevice *eth_get_dev_by_name(const char *devname);
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+
+/* Used only when NetConsole is enabled */
+int eth_is_active(struct udevice *dev); /* Test device for active state */
+int eth_init_state_only(void); /* Set active state */
+void eth_halt_state_only(void); /* Set passive state */
+
+int eth_initialize(void);		/* Initialize network subsystem */
+void eth_try_another(int first_restart);	/* Change the device */
+void eth_set_current(void);		/* set nterface to ethcur var */
+
+int eth_get_dev_index(void);		/* get the device index */
+
+/**
+ * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
+ *
+ * This sets up an environment variable with the given MAC address (@enetaddr).
+ * The environment variable to be set is defined by <@base_name><@index>addr.
+ * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
+ * eth1addr, etc.
+ *
+ * @base_name:  Base name for variable, typically "eth"
+ * @index:      Index of interface being updated (>=0)
+ * @enetaddr:   Pointer to MAC address to put into the variable
+ * Return: 0 if OK, other value on error
+ */
+int eth_env_set_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
+
+
+/*
+ * Initialize USB ethernet device with CONFIG_DM_ETH
+ * Returns:
+ *	0 is success, non-zero is error status.
+ */
+int usb_ether_init(void);
+
+/*
+ * Get the hardware address for an ethernet interface .
+ * Args:
+ *	base_name - base name for device (normally "eth")
+ *	index - device index number (0 for first)
+ *	enetaddr - returns 6 byte hardware address
+ * Returns:
+ *	Return true if the address is valid.
+ */
+int eth_env_get_enetaddr_by_index(const char *base_name, int index,
+				 uchar *enetaddr);
+
+int eth_init(void);			/* Initialize the device */
+int eth_send(void *packet, int length);	   /* Send a packet */
+
+#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
+int eth_receive(void *packet, int length); /* Receive a packet*/
+extern void (*push_packet)(void *packet, int length);
+#endif
+int eth_rx(void);			/* Check for received packets */
+void eth_halt(void);			/* stop SCC */
+const char *eth_get_name(void);		/* get name of current device */
+
+/*
+ *	The number of receive packet buffers, and the required packet buffer
+ *	alignment in memory.
+ *
+ */
+#define PKTBUFSRX	CONFIG_SYS_RX_ETH_BUFFER
+#define PKTALIGN	ARCH_DMA_MINALIGN
+
+/* Number of packets processed together */
+#define ETH_PACKETS_BATCH_RECV	32
+
+extern u8		net_ethaddr[ARP_HLEN];		/* Our ethernet address */
+extern u8		net_server_ethaddr[ARP_HLEN];	/* Boot server enet address */
+extern struct in_addr	net_ip;		/* Our    IP addr (0 = unknown) */
+extern struct in_addr	net_server_ip;	/* Server IP addr (0 = unknown) */
+extern uchar		*net_tx_packet;		/* THE transmit packet */
+extern uchar		*net_rx_packets[PKTBUFSRX]; /* Receive packets */
+extern uchar		*net_rx_packet;		/* Current receive packet */
+extern int		net_rx_packet_len;	/* Current rx packet length */
+extern const u8		net_bcast_ethaddr[ARP_HLEN];	/* Ethernet broadcast address */
+extern const u8		net_null_ethaddr[ARP_HLEN];
+
+/**
+ * string_to_enetaddr() - Parse a MAC address
+ *
+ * Convert a string MAC address
+ *
+ * Implemented in lib/net_utils.c (built unconditionally)
+ *
+ * @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit
+ *	hex value
+ * @enetaddr: Place to put MAC address (6 bytes)
+ */
+void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
+
+typedef struct ulwip {
+	bool loop;
+	int err;
+	bool init_done;
+} ulwip;
+
+struct ulwip *eth_lwip_priv(struct udevice *current);
-- 
2.30.2


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

* [PATCHv6 14/14] net/lwip: drop old net/wget
  2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
                   ` (12 preceding siblings ...)
  2023-08-14 13:32 ` [PATCHv6 13/14] net/lwip: split net.h to net.h, arp.h and eth.h Maxim Uvarov
@ 2023-08-14 13:32 ` Maxim Uvarov
  13 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 13:32 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 61930c244e..eda21f988a 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
 obj-$(CONFIG_LWIP) += lwip/
 
 # Disable this warning as it is triggered by:
diff --git a/net/net.c b/net/net.c
index 7f868ee516..38d34ed5f4 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] 49+ messages in thread

* Re: [PATCHv6 01/14] net/lwip: add doc/develop/net_lwip.rst
  2023-08-14 13:32 ` [PATCHv6 01/14] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
@ 2023-08-14 14:10   ` Ilias Apalodimas
  0 siblings, 0 replies; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-14 14:10 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Simon Glass

On Mon, Aug 14, 2023 at 07:32:40PM +0600, Maxim Uvarov wrote:
> Add initial documentation of lwIP network IP stack integration
> to the U-Boot (net_lwip.rst).
> 
> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>  doc/develop/index.rst    |  1 +
>  doc/develop/net_lwip.rst | 64 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 65 insertions(+)
>  create mode 100644 doc/develop/net_lwip.rst
> 
> diff --git a/doc/develop/index.rst b/doc/develop/index.rst
> index 5b230d0321..4764990f25 100644
> --- a/doc/develop/index.rst
> +++ b/doc/develop/index.rst
> @@ -48,6 +48,7 @@ Implementation
>     spl
>     falcon
>     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..bdd2c921b3
> --- /dev/null
> +++ b/doc/develop/net_lwip.rst
> @@ -0,0 +1,64 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +LWIP IP stack intergation for U-Boot
> +====================================
> +
> +Intro
> +-----
> +
> +LWIP is a library implementing 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

You can skip the 'I' here, it's not a personal project.  Something along
the lines of 'the second variant was chosen ...' would work 
> +   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 registered

One example is the unmodified etc 

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

'That way we can leave the driver code unmodified and consume packets once
they are ready'

Thanks
/Ilias
> -- 
> 2.30.2
> 

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

* Re: [PATCHv6 02/14] net/lwip: integrate lwIP library
  2023-08-14 13:32 ` [PATCHv6 02/14] net/lwip: integrate lwIP library Maxim Uvarov
@ 2023-08-14 14:13   ` Ilias Apalodimas
  0 siblings, 0 replies; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-14 14:13 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, Aug 14, 2023 at 07:32:41PM +0600, Maxim Uvarov wrote:
> Define Makefile and Kconfig to build lwIP inside the U-Boot. We compile
> lwIP the same as the main code, plus we can do optimization for size at
> compile time with disabling not needed debug asserts, or not used protocols.
> So we can tune lwIP configuration specially for U-Boot environments.
> 
> +menu "LWIP"

[...]

> +config LWIP
> +	bool "Support LWIP library"
> +	help
> +          Enable the lwIP library code with
> +          all dependencies (cmd commands implemented with lwIP

cmd commands -> commands

> +          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/develop/net_lwip.rst for more details.
> +
> +menu "LWIP options"
> +
> 
[...]

Thanks
/Ilias

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

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

On Mon, Aug 14, 2023 at 07:32:42PM +0600, Maxim Uvarov wrote:
> Implement function for dns command with lwIP variant. Usage and output is
> the same as the original command. This code called by compatibility code
> between U-Boot and lwIP.

What's compatibility code?
I think something along the lines of 

'U-Boot recently got support for an alternative network stack using LWIP.  
Replace XXXX command with the LWIP variant while keeping the output and
error messages identical"

> +
> +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
> +		char *const argv[]);
> +
> +/*
> +* This function creates the DNS request to resolve a domain host name. Function

You need the name of the function as well.  Please have a look at how the
rest of the code is documented. 

> +* can return immediately if previous request was cached or it might require
> +* entering the polling loop for a request to a remote server.
> +*
> +* @name  dns name to resolve

@name: etc

> +* @varname (optional) U-Boot variable name to store the result
> +* Return: ERR_OK(0) for fetching entry from the cache
> +*         ERR_INPROGRESS(-5) success, can go to the polling loop
> +*         Other value < 0, if error
> +*/
> +int ulwip_dns(char *name, char *varname);
> diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> index d1161bea78..6d2c00605b 100644
> --- a/net/lwip/Makefile
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <console.h>
> +
> +#include <lwip/dns.h>
> +#include <lwip/ip_addr.h>
> +
> +#include <net/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));

Why do we have to set the varname to the resolved address?  Is this
something the dns command already does?

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

Thanks
/Ilias

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-14 13:32 ` [PATCHv6 04/14] net/lwip: implement dhcp cmd Maxim Uvarov
@ 2023-08-14 14:21   ` Ilias Apalodimas
  2023-08-14 15:18     ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-14 14:21 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> Implement function for dhcp command with lwIP variant. Usage and output is
> the same as the original command. This code called by compatibility code
> between U-Boot and lwIP.

Same as the dns command

> 
> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> ---
>  include/net/lwip.h             | 10 +++++++
>  net/lwip/Makefile              |  1 +
>  net/lwip/apps/dhcp/lwip-dhcp.c | 51 ++++++++++++++++++++++++++++++++++
>  3 files changed, 62 insertions(+)
>  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> 
> diff --git a/include/net/lwip.h b/include/net/lwip.h
> index c83b5c8231..2f035280eb 100644
> --- a/include/net/lwip.h
> +++ b/include/net/lwip.h
> @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
>  *         Other value < 0, if error
>  */
>  int ulwip_dns(char *name, char *varname);
> +
> +/*
> +* This function creates the DHCP request to obtain IP address. If DHCP server

Sphinx needs something more, please check the existing functions

> +* returns file name, this file will be downloaded with tftp.  After this
> +* function you need to invoke the polling loop to process network communication.
> +*
> +* Return: 0 if success
> +*         Other value < 0, if error
> +*/
> +int ulwip_dhcp(void);
> diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> index 6d2c00605b..59323fb325 100644
> --- a/net/lwip/Makefile
> +
> +static struct dhcp dhcp;
> +
> +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);

What's (1)?

> +
> +	if (!netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
> +		dhcp_set_struct(netif, &dhcp);
> +
> +	err = dhcp_start(netif);
> +	if (err)
> +		printf("dhcp_start error %d\n", err);
> +
> +	return err;
> +}
> -- 
> 2.30.2
> 

Thanks
/Ilias

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

* Re: [PATCHv6 05/14] net/lwip: implement tftp cmd
  2023-08-14 13:32 ` [PATCHv6 05/14] net/lwip: implement tftp cmd Maxim Uvarov
@ 2023-08-14 14:25   ` Ilias Apalodimas
  2023-08-14 18:54     ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-14 14:25 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

> +// 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 <bootstage.h>
> +
> +#include "lwip/apps/tftp_client.h"
> +#include "lwip/apps/tftp_server.h"
> +#include <tftp_example.h>
> +
> +#include <string.h>
> +
> +#include <net/ulwip.h>
> +
> +#if LWIP_UDP

Why do we have this?  I dont think it makes sense to start reasoning about
LWIP config options from within U-Boot code.  Instead U-Boot makefiles
should enable all the LWIP features we need when a command is included 

> +
> +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)
> +{
> +	log_info("\ndone\n");
> +	log_info("Bytes transferred = %ld (0x%lx hex)\n", size, size);
> +
> +	bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
> +	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);
> +		daddr += q->len;
> +		size += q->len;
> +		log_info("#");
> +	}
> +
> +	return 0;
> +}
> +
> +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));
> +
> +	log_info("TFTP error: %d (%s)", err, message);
> +}
> +
> +static const struct tftp_context tftp = {
> +	tftp_open,
> +	tftp_close,
> +	tftp_read,
> +	tftp_write,
> +	tftp_error
> +};
> +
> +int ulwip_tftp(ulong addr, char *fname)
> +{
> +	void *f = (void *)0x1; /* unused fake file 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) {
> +		log_err("error: serverip variable has to be set\n");
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	ret = ipaddr_aton(server_ip, &srv);
> +	if (!ret) {
> +		log_err("error: ipaddr_aton\n");
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	log_info("TFTP from server %s; our IP address is %s\n",
> +		 server_ip, env_get("ipaddr"));
> +	log_info("Filename '%s'.\n", fname);
> +	log_info("Load address: 0x%lx\n", daddr);
> +	log_info("Loading:");
> +
> +	bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
> +
> +	err = tftp_init_client(&tftp);
> +	if (!(err == ERR_OK || err == ERR_USE))
> +		log_err("tftp_init_client err: %d\n", err);
> +
> +	err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET);

Shouldn't this be part of tftp_read()?

> +	/* might return different errors, like routing problems */
> +	if (err != ERR_OK) {
> +		log_err("tftp_get err=%d\n", err);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	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] 49+ messages in thread

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-14 14:19   ` Ilias Apalodimas
@ 2023-08-14 15:15     ` Maxim Uvarov
  2023-08-15 12:42     ` Maxim Uvarov
  1 sibling, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 15:15 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> On Mon, Aug 14, 2023 at 07:32:42PM +0600, Maxim Uvarov wrote:
> > Implement function for dns command with lwIP variant. Usage and output is
> > the same as the original command. This code called by compatibility code
> > between U-Boot and lwIP.
>
> What's compatibility code?
> I think something along the lines of
>
> 'U-Boot recently got support for an alternative network stack using LWIP.
> Replace XXXX command with the LWIP variant while keeping the output and
> error messages identical"
>

ok, that message is a good one. By 'compatibility code' I meant code to
merge lwip applications and other U-Boot code.

So in general all net/lwip/apps/{dns,ping,wget} and etc. These applications
do not have U-Boot headers and can be compiled with
any other lwIP port. I.e. for example, you can take the linux userland port
with a tap device and directly compile these apps, run and debug.
This might be named lwIP apps code.

And code which does lwIP init, calls application initialization, then goes
to net polling loop - I named here 'a compatibility code'. Might be not the
base naming, but that was an idea.



>
> > +
> > +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
> > +             char *const argv[]);
> > +
> > +/*
> > +* This function creates the DNS request to resolve a domain host name.
> Function
>
> You need the name of the function as well.  Please have a look at how the
> rest of the code is documented.
>
> > +* can return immediately if previous request was cached or it might
> require
> > +* entering the polling loop for a request to a remote server.
> > +*
> > +* @name  dns name to resolve
>
> @name: etc
>
> > +* @varname (optional) U-Boot variable name to store the result
> > +* Return: ERR_OK(0) for fetching entry from the cache
> > +*         ERR_INPROGRESS(-5) success, can go to the polling loop
> > +*         Other value < 0, if error
> > +*/
> > +int ulwip_dns(char *name, char *varname);
> > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > index d1161bea78..6d2c00605b 100644
> > --- a/net/lwip/Makefile
> > + */
> > +
> > +#include <common.h>
> > +#include <command.h>
> > +#include <console.h>
> > +
> > +#include <lwip/dns.h>
> > +#include <lwip/ip_addr.h>
> > +
> > +#include <net/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));
>
> Why do we have to set the varname to the resolved address?  Is this
> something the dns command already does?
>
> Exactly, original  command is:

U_BOOT_CMD(
dns, 3, 1, do_dns,
"lookup the IP of a hostname",
"hostname [envvar]"
);



> > +
> > +     log_info("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;
> > +}
> > --
> > 2.30.2
> >
>
> Thanks
> /Ilias
>

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-14 14:21   ` Ilias Apalodimas
@ 2023-08-14 15:18     ` Maxim Uvarov
  2023-08-14 15:29       ` Tom Rini
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 15:18 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > Implement function for dhcp command with lwIP variant. Usage and output
> is
> > the same as the original command. This code called by compatibility code
> > between U-Boot and lwIP.
>
> Same as the dns command
>
> >
> > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > ---
> >  include/net/lwip.h             | 10 +++++++
> >  net/lwip/Makefile              |  1 +
> >  net/lwip/apps/dhcp/lwip-dhcp.c | 51 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 62 insertions(+)
> >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> >
> > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > index c83b5c8231..2f035280eb 100644
> > --- a/include/net/lwip.h
> > +++ b/include/net/lwip.h
> > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int
> argc,
> >  *         Other value < 0, if error
> >  */
> >  int ulwip_dns(char *name, char *varname);
> > +
> > +/*
> > +* This function creates the DHCP request to obtain IP address. If DHCP
> server
>
> Sphinx needs something more, please check the existing functions
>
> > +* returns file name, this file will be downloaded with tftp.  After this
> > +* function you need to invoke the polling loop to process network
> communication.
> > +*
> > +* Return: 0 if success
> > +*         Other value < 0, if error
> > +*/
> > +int ulwip_dhcp(void);
> > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > index 6d2c00605b..59323fb325 100644
> > --- a/net/lwip/Makefile
> > +
> > +static struct dhcp dhcp;
> > +
> > +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);
>
> What's (1)?
>
>
Only one lwip netif is registered. 1 - here is the index of netif. I don't
think that there is any definition for that...



> > +
> > +     if (!netif_get_client_data(netif,
> LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
> > +             dhcp_set_struct(netif, &dhcp);
> > +
> > +     err = dhcp_start(netif);
> > +     if (err)
> > +             printf("dhcp_start error %d\n", err);
> > +
> > +     return err;
> > +}
> > --
> > 2.30.2
> >
>
> Thanks
> /Ilias
>

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-14 15:18     ` Maxim Uvarov
@ 2023-08-14 15:29       ` Tom Rini
  2023-08-17 13:46         ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Tom Rini @ 2023-08-14 15:29 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, goldsimon, lwip-devel

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

On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <ilias.apalodimas@linaro.org>
> wrote:
> 
> > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > > Implement function for dhcp command with lwIP variant. Usage and output
> > is
> > > the same as the original command. This code called by compatibility code
> > > between U-Boot and lwIP.
> >
> > Same as the dns command
> >
> > >
> > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > > ---
> > >  include/net/lwip.h             | 10 +++++++
> > >  net/lwip/Makefile              |  1 +
> > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51 ++++++++++++++++++++++++++++++++++
> > >  3 files changed, 62 insertions(+)
> > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> > >
> > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > > index c83b5c8231..2f035280eb 100644
> > > --- a/include/net/lwip.h
> > > +++ b/include/net/lwip.h
> > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int
> > argc,
> > >  *         Other value < 0, if error
> > >  */
> > >  int ulwip_dns(char *name, char *varname);
> > > +
> > > +/*
> > > +* This function creates the DHCP request to obtain IP address. If DHCP
> > server
> >
> > Sphinx needs something more, please check the existing functions
> >
> > > +* returns file name, this file will be downloaded with tftp.  After this
> > > +* function you need to invoke the polling loop to process network
> > communication.
> > > +*
> > > +* Return: 0 if success
> > > +*         Other value < 0, if error
> > > +*/
> > > +int ulwip_dhcp(void);
> > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > index 6d2c00605b..59323fb325 100644
> > > --- a/net/lwip/Makefile
> > > +
> > > +static struct dhcp dhcp;
> > > +
> > > +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);
> >
> > What's (1)?
> >
> >
> Only one lwip netif is registered. 1 - here is the index of netif. I don't
> think that there is any definition for that...
> 

And there's only ever going to be one interface (even if we have ipv4
and ipv60 ? If so, define it to something please, thanks.

-- 
Tom

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

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

* Re: [PATCHv6 05/14] net/lwip: implement tftp cmd
  2023-08-14 14:25   ` Ilias Apalodimas
@ 2023-08-14 18:54     ` Maxim Uvarov
  0 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-14 18:54 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, 14 Aug 2023 at 20:25, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> > +// 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 <bootstage.h>
> > +
> > +#include "lwip/apps/tftp_client.h"
> > +#include "lwip/apps/tftp_server.h"
> > +#include <tftp_example.h>
> > +
> > +#include <string.h>
> > +
> > +#include <net/ulwip.h>
> > +
> > +#if LWIP_UDP
>
> Why do we have this?  I dont think it makes sense to start reasoning about
> LWIP config options from within U-Boot code.  Instead U-Boot makefiles
> should enable all the LWIP features we need when a command is included
>
>
That is how example used it. Agree do drop this if.


> > +
> > +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)
> > +{
> > +     log_info("\ndone\n");
> > +     log_info("Bytes transferred = %ld (0x%lx hex)\n", size, size);
> > +
> > +     bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
> > +     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);
> > +             daddr += q->len;
> > +             size += q->len;
> > +             log_info("#");
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +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));
> > +
> > +     log_info("TFTP error: %d (%s)", err, message);
> > +}
> > +
> > +static const struct tftp_context tftp = {
> > +     tftp_open,
> > +     tftp_close,
> > +     tftp_read,
> > +     tftp_write,
> > +     tftp_error
> > +};
> > +
> > +int ulwip_tftp(ulong addr, char *fname)
> > +{
> > +     void *f = (void *)0x1; /* unused fake file 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) {
> > +             log_err("error: serverip variable has to be set\n");
> > +             return CMD_RET_FAILURE;
> > +     }
> > +
> > +     ret = ipaddr_aton(server_ip, &srv);
> > +     if (!ret) {
> > +             log_err("error: ipaddr_aton\n");
> > +             return CMD_RET_FAILURE;
> > +     }
> > +
> > +     log_info("TFTP from server %s; our IP address is %s\n",
> > +              server_ip, env_get("ipaddr"));
> > +     log_info("Filename '%s'.\n", fname);
> > +     log_info("Load address: 0x%lx\n", daddr);
> > +     log_info("Loading:");
> > +
> > +     bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
> > +
> > +     err = tftp_init_client(&tftp);
> > +     if (!(err == ERR_OK || err == ERR_USE))
> > +             log_err("tftp_init_client err: %d\n", err);
> > +
> > +     err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET);
>
> Shouldn't this be part of tftp_read()?
>
>
tft_get() actually does some initialization. Then when the polling loop
works tftp_write() or tftp_read() callbacks will be called.
So here it should stay as is.


> > +     /* might return different errors, like routing problems */
> > +     if (err != ERR_OK) {
> > +             log_err("tftp_get err=%d\n", err);
> > +             return CMD_RET_FAILURE;
> > +     }
> > +
> > +     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] 49+ messages in thread

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-14 14:19   ` Ilias Apalodimas
  2023-08-14 15:15     ` Maxim Uvarov
@ 2023-08-15 12:42     ` Maxim Uvarov
  2023-08-15 14:42       ` Tom Rini
  1 sibling, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-15 12:42 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

[...]


> > +/*
> > +* This function creates the DNS request to resolve a domain host name.
> Function
>
> You need the name of the function as well.  Please have a look at how the
> rest of the code is documented.
>
> > +* can return immediately if previous request was cached or it might
> require
> > +* entering the polling loop for a request to a remote server.
> > +*
> > +* @name  dns name to resolve
>
> @name: etc
>
> > +* @varname (optional) U-Boot variable name to store the result
> > +* Return: ERR_OK(0) for fetching entry from the cache
> > +*         ERR_INPROGRESS(-5) success, can go to the polling loop
> > +*         Other value < 0, if error
> > +*/
> >
>

Is there any command to check all the files for the comments style?

[...]

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

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-15 12:42     ` Maxim Uvarov
@ 2023-08-15 14:42       ` Tom Rini
  2023-08-16 10:26         ` Ilias Apalodimas
  0 siblings, 1 reply; 49+ messages in thread
From: Tom Rini @ 2023-08-15 14:42 UTC (permalink / raw)
  To: Maxim Uvarov, Heinrich Schuchardt
  Cc: Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, goldsimon, lwip-devel

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

On Tue, Aug 15, 2023 at 06:42:14PM +0600, Maxim Uvarov wrote:
> On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <ilias.apalodimas@linaro.org>
> wrote:
> 
> [...]
> 
> 
> > > +/*
> > > +* This function creates the DNS request to resolve a domain host name.
> > Function
> >
> > You need the name of the function as well.  Please have a look at how the
> > rest of the code is documented.
> >
> > > +* can return immediately if previous request was cached or it might
> > require
> > > +* entering the polling loop for a request to a remote server.
> > > +*
> > > +* @name  dns name to resolve
> >
> > @name: etc
> >
> > > +* @varname (optional) U-Boot variable name to store the result
> > > +* Return: ERR_OK(0) for fetching entry from the cache
> > > +*         ERR_INPROGRESS(-5) success, can go to the polling loop
> > > +*         Other value < 0, if error
> > > +*/
> > >
> >
> 
> Is there any command to check all the files for the comments style?

I suspect if you included them in docs, htmldocs/etc would note
problems, Heinrich?

-- 
Tom

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

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

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

On Mon, Aug 14, 2023 at 07:32:45PM +0600, Maxim Uvarov wrote:
> Implement function for wget command with lwIP variant. Usage and output is
> the same as the original command. This code called by compatibility code
>  between U-Boot and lwIP.
> 


Similar comments to previous patches adding commands

> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> +*
> +*
> +* @addr  start address to download result
> +* @url   url in format http://host[:port]/url
> +* Return: 0 for success
> +*         !0 if error
> +*/

Same here, sphinx needs a different syntax

> +int ulwip_wget(ulong addr, char *url);
> diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> index 0337d82cf5..4c6df94807 100644
> --- a/net/lwip/Makefile
> +++ b/net/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/net/lwip/apps/http/Makefile b/net/lwip/apps/http/Makefile
> new file mode 100644
> index 0000000000..3e92b0ef1b
> --- /dev/null
> +++ b/net/lwip/apps/http/Makefile
> @@ -0,0 +1,13 @@
> +ccflags-y += -I$(srctree)/net/lwip/port/include
> +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip
> +ccflags-y += -I$(obj)
> +
> +$(obj)/http_clinet.o: $(obj)/http_client.c
> +.PHONY: $(obj)/http_client.c
> +$(obj)/http_client.c:
> +	cp $(srctree)/net/lwip/lwip-external/src/apps/http/http_client.c $(obj)/http_client.c
> +	cp $(srctree)/net/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/net/lwip/apps/http/lwip-wget.c b/net/lwip/apps/http/lwip-wget.c
> new file mode 100644
> index 0000000000..73d82225a2
> --- /dev/null
> +++ b/net/lwip/apps/http/lwip-wget.c
> @@ -0,0 +1,131 @@
> +// 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 <vsprintf.h>
> +
> +#include "http_client.h"
> +#include <net/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 unused_err)
> +{
> +	struct pbuf *q;

Please change the p/q stuff to something that's actually readable and hints
on what those variables represent 

> +
> +	if (!p)
> +		return ERR_BUF;
> +
> +	for (q = p; q != NULL; q = q->next) {
> +		memcpy((void *)daddr, q->payload, q->len);
> +		log_debug("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr);
> +		daddr += q->len;
> +	}
> +	altcp_recved(pcb, p->tot_len);
> +	pbuf_free(p);

Why is this freed here?
If the caller allocates this, he should also be responsible for freeing it 

> +	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) {
> +		log_info("\n%d bytes successfully downloaded.\n", rx_content_len);
> +		env_set_ulong("filesize", rx_content_len);
> +		ulwip_exit(0);
> +	} else {
> +		log_err("\nhttp eroror: %d\n", httpc_result);
> +		ulwip_exit(-1);
> +	}
> +}
> +
> +/* http://hostname:port/url */
> +static int parse_url(char *url, char *host, u16 *port)

I think we discussed this already.  If the existing wget application
doesn't support configurable ports, just skip it on the initial patch and 
add it in the future 

> +{
> +	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 = (u16)dectoul(portstr, NULL);
> +	} 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 ulwip_wget(ulong addr, char *url)
> +{
> +	err_t err;
> +	u16 port;
> +	char server_name[SERVER_NAME_SIZE];
> +	httpc_state_t *connection;
> +
> +	daddr = addr;
> +
> +	err = parse_url(url, server_name, &port);
> +	if (err) {
> +		log_err("error parse_url\n");
> +		return -1;
> +	}
> +
> +	log_info("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) {
> +		log_err("httpc_init_connection failed\n");
> +		return err;
> +	}
> +
> +	env_set_hex("fileaddr", addr);
> +	return 0;
> +}
> -- 
> 2.30.2
> 

Thanks
/Ilias

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

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

On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
>  * can return immediately if previous request was cached or it might require
> @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
>  *         !0 if error
>  */
>  int ulwip_wget(ulong addr, char *url);
> +
> +/**
> + * ulwip_tftp() - load file with tftp
> + *
> + * Load file with tftp to specific address
> + *
> + * @param addr - address to store downloaded file
> + * @param filename - file name on remote tftp server to download

Please fix function comments properly 

> + *
> + *
> + * @return 0 if success, !0 if error
> + */
> +int ulwip_tftp(ulong addr, const char *filename);
> +
> +/*
> +* This function creates the ping for  address provided in parameters.
> +* After this function you need to invoke the polling
> +* loop to process network communication.
> +*
> +*
> +* @ping_addr  start address to download result
> +* Return: 0 for success
> +*         !0 if error
> +*/
> +int ulwip_ping(char *ping_addr);
> diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> index 4c6df94807..8b3e843426 100644
> --- a/net/lwip/Makefile
> +++ b/net/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/net/lwip/apps/ping/Makefile b/net/lwip/apps/ping/Makefile
> new file mode 100644
> index 0000000000..dc63feb7b5
> --- /dev/null
> +++ b/net/lwip/apps/ping/Makefile
> @@ -0,0 +1,11 @@
> +ccflags-y += -I$(srctree)/net/lwip/port/include
> +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip
> +ccflags-y += -I$(obj)
> +
> +.PHONY: $(obj)/ping.c
> +$(obj)/ping.o: $(obj)/ping.c
> +$(obj)/ping.c:
> +	cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c b/net/lwip/apps/ping/lwip_ping.c
> new file mode 100644
> index 0000000000..611fcaf591
> --- /dev/null
> +++ b/net/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 "lwip_ping.h"
> +
> +static ip_addr_t ip_target;
> +
> +static int ulwip_ping_tmo(void)
> +{
> +
> +	log_err("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target));
> +	return 1;
> +}
> +
> +int ulwip_ping(char *ping_addr)
> +{
> +	int err;
> +
> +	err = ipaddr_aton(ping_addr, &ip_target);
> +	if (!err) {
> +		log_err("wrong ping addr string \"%s\" \n", ping_addr);

Invalid ip address is enough

> +		return -1;
> +	}
> +
> +	ulwip_set_tmo(ulwip_ping_tmo);
> +
> +	ping_init(&ip_target);
> +	ping_send_now();
> +
> +	return 0;
> +}
> diff --git a/net/lwip/apps/ping/lwip_ping.h b/net/lwip/apps/ping/lwip_ping.h
> new file mode 100644
> index 0000000000..0374f07d9e
> --- /dev/null
> +++ b/net/lwip/apps/ping/lwip_ping.h
> @@ -0,0 +1,15 @@
> +/* 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>
> +
> +void ping_raw_init(void);
> +void ping_send_now(void);
> +
> +#endif /* LWIP_PING_H */
> diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
> new file mode 100644
> index 0000000000..006a18c658
> --- /dev/null
> +++ b/net/lwip/apps/ping/ping.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#include <net/ulwip.h>
> +#include "lwip/ip_addr.h"
> +
> +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
> +#define PING_RESULT(cond) { \
> +	if (cond == 1) { \
> +		printf("host %s a alive\n", ipaddr_ntoa(addr)); \
> +		printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
> +		ulwip_exit(0); \
> +	} else { \
> +		printf("ping failed; host %s in not alive\n",\
> +		       ipaddr_ntoa(addr)); \
> +		ulwip_exit(-1); \
> +	} \
> +     } while (0);

On the previous patch you are defining a function to do something similar
(httpc_result()).  We need to be consistent on this.  Can we define a
common function for all failures?  Certianly don't define a macro here and
a function elsewhere

> +
> +void ping_init(const ip_addr_t *ping_addr);
> -- 
> 2.30.2
> 

Thanks
/Ilias

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

* Re: [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot
  2023-08-14 13:32 ` [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot Maxim Uvarov
@ 2023-08-16  9:01   ` Ilias Apalodimas
  2023-08-18 12:53     ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-16  9:01 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Mon, Aug 14, 2023 at 07:32:48PM +0600, Maxim Uvarov wrote:
> Implement network lwIP interface connected to the U-boot.
> Keep original file structure widely used fro lwIP ports.
> (i.e. port/if.c port/sys-arch.c).

What the patch does is obvious.  Try to describe *why* we need this 

> 
> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> ---
>  net/eth-uclass.c                      |   8 +
>  net/lwip/port/if.c                    | 260 ++++++++++++++++++++++++++
>  net/lwip/port/include/arch/cc.h       |  39 ++++
>  net/lwip/port/include/arch/sys_arch.h |  56 ++++++
>  net/lwip/port/include/limits.h        |   0
>  net/lwip/port/sys-arch.c              |  20 ++
>  6 files changed, 383 insertions(+)
>  create mode 100644 net/lwip/port/if.c
>  create mode 100644 net/lwip/port/include/arch/cc.h
>  create mode 100644 net/lwip/port/include/arch/sys_arch.h
>  create mode 100644 net/lwip/port/include/limits.h
>  create mode 100644 net/lwip/port/sys-arch.c
> 
> diff --git a/net/eth-uclass.c b/net/eth-uclass.c
> index c393600fab..6625f6d8a5 100644
> --- a/net/eth-uclass.c
> +++ b/net/eth-uclass.c
> @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
>  struct eth_device_priv {
>  	enum eth_state_t state;
>  	bool running;
> +	ulwip ulwip;
>  };
>  
>  /**
> @@ -347,6 +348,13 @@ int eth_init(void)
>  	return ret;
>  }
>  
> +struct ulwip *eth_lwip_priv(struct udevice *current)
> +{
> +	struct eth_device_priv *priv = dev_get_uclass_priv(current);
> +
> +	return &priv->ulwip;
> +}
> +
>  void eth_halt(void)
>  {
>  	struct udevice *current;
> diff --git a/net/lwip/port/if.c b/net/lwip/port/if.c
> new file mode 100644
> index 0000000000..625a9c10bf
> --- /dev/null
> +++ b/net/lwip/port/if.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <net/eth.h>
> +#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/ethip6.h"
> +
> +#include "lwip/ip.h"
> +
> +#define IFNAME0 'e'
> +#define IFNAME1 '0'

Why is this needed and how was 'e0' chosen?
Dont we have a device name in the udevice struct?

> +
> +static struct pbuf *low_level_input(struct netif *netif);
> +
> +int ulwip_enabled(void)
> +{
> +	struct ulwip *ulwip;
> +
> +	ulwip = eth_lwip_priv(eth_get_dev());

eth_get_dev() can return NULL.  There are various locations of this call
that needs fixing

> +	return ulwip->init_done;
> +}
> +
> +
> +struct ulwip_if {
> +};

Why the forward declaration?

> +
> +#define LWIP_PORT_INIT_NETMASK(addr)  IP4_ADDR((addr), 255, 255, 255, 0)

Why are we limiting the netmask to a class C network?

> +
> +void ulwip_poll(void)
> +{
> +	struct pbuf *p;
> +	int err;
> +	struct netif *netif = netif_get_by_index(1);

First of all netif can be NULL. Apart from that always requesting index 1
feels wrong.  We should do something similar to eth_get_dev() and get the
*active* device correlation to an index

> +
> +	p = low_level_input(netif);
> +	if (!p) {
> +		log_err("error p = low_level_input = NULL\n");

This looks like a debug message.
'Network interface undefined' or something else, which is more readable. 

> +		return;
> +	}
> +
> +	/* ethernet_input always returns ERR_OK */
> +	err = ethernet_input(p, netif);
> +	if (err)
> +		log_err("ip4_input err %d\n", err);
> +
> +	return;
> +}
> +
> +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;
> +
> +	/* We allocate a pbuf chain of pbufs from the pool. */
> +	p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
> +	if (p) {

if (!p) and reverse the logic 

> +		/* 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();
> +
> +		LINK_STATS_INC(link.recv);
> +	} else {
> +		// drop packet();

Is this a commented function that's missing?

> +		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) {
> +		log_err("eth_send error %d\n", err);
> +		return ERR_ABRT;
> +	}
> +	return ERR_OK;
> +}
> +
> +err_t ulwip_if_init(struct netif *netif)
> +{
> +	struct ulwip_if *uif;
> +	struct ulwip *ulwip;
> +
> +	uif = malloc(sizeof(struct ulwip_if));
> +	if (!uif) {
> +		log_err("uif: 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);

What if ethaddr is not set?

> +#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
> +#if LWIP_IPV6
> +	netif->output_ip6 = ethip6_output;
> +#endif
> +
> +	netif->linkoutput = low_level_output;
> +	netif->mtu = 1500;
> +	netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
> +
> +	ulwip = eth_lwip_priv(eth_get_dev());
> +	ulwip->init_done = 1;
> +	if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
> +		log_info("Initialized LWIP stack\n");
> +	}
> +
> +	return ERR_OK;
> +}
> +
> +int ulwip_init(void)
> +{
> +	ip4_addr_t ipaddr, netmask, gw;
> +	struct netif *unetif;
> +	struct ulwip *ulwip;
> +	int ret;
> +
> +	ret = eth_init();
> +	if (ret) {
> +		log_err("eth_init error %d\n", ret);
> +		return ERR_IF;
> +	}
> +
> +	ulwip = eth_lwip_priv(eth_get_dev());
> +	if (ulwip->init_done)
> +		return CMD_RET_SUCCESS;
> +
> +	unetif = malloc(sizeof(struct netif));
> +	if (!unetif)
> +		return ERR_MEM;
> +	memset(unetif, 0, sizeof(struct netif));
> +
> +	ip4_addr_set_zero(&gw);
> +	ip4_addr_set_zero(&ipaddr);
> +	ip4_addr_set_zero(&netmask);
> +
> +	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));

log_info()

> +	}
> +
> +	if (!netif_add(unetif, &ipaddr, &netmask, &gw,
> +		       unetif, ulwip_if_init, ethernetif_input))
> +		printf("err: netif_add failed!\n");
> +
> +	netif_set_up(unetif);
> +	netif_set_link_up(unetif);
> +#if LWIP_IPV6
> +	netif_create_ip6_linklocal_address(unetif, 1);
> +	printf("             IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(unetif, 0)));
> +#endif /* LWIP_IPV6 */
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +/* placeholder, not used now */
> +void ulwip_destroy(void)
> +{
> +}
> diff --git a/net/lwip/port/include/arch/cc.h b/net/lwip/port/include/arch/cc.h
> new file mode 100644
> index 0000000000..55f7787ce1
> --- /dev/null
> +++ b/net/lwip/port/include/arch/cc.h
> @@ -0,0 +1,39 @@
> +/* 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>
> +//#include <stdlib.h>    /* getenv, atoi */

Please dont leave comments like that 

> +#include <vsprintf.h>
> +
> +#define LWIP_ERRNO_INCLUDE <errno.h>
> +
> +#define LWIP_ERRNO_STDINCLUDE	1
> +#define LWIP_NO_UNISTD_H 1
> +#define LWIP_TIMEVAL_PRIVATE 1

Should those be defined in the LWIP config header instead?

> +
> +extern unsigned int lwip_port_rand(void);

This is like the forth time we go through this and it's a repeating
pattern.  Why do we need this extern? Can't we just include the proper
header files?

> +#define LWIP_RAND() (lwip_port_rand())

This seems quite useless. Just use the function directly

> +
> +/* different handling for unit test, normally not needed */
> +#ifdef LWIP_NOASSERT_ON_ERROR
> +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
> +						    handler; }} while (0)
> +#endif
> +
> +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
> +
> +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
> +				    x, __LINE__, __FILE__); } while (0)
> +
> +#define atoi(str) (int)dectoul(str, NULL)
> +
> +#define LWIP_ERR_T int
> +
> +#endif /* LWIP_ARCH_CC_H */
> diff --git a/net/lwip/port/include/arch/sys_arch.h b/net/lwip/port/include/arch/sys_arch.h
> new file mode 100644
> index 0000000000..92a8560d49
> --- /dev/null
> +++ b/net/lwip/port/include/arch/sys_arch.h
> @@ -0,0 +1,56 @@
> +/* 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)

Dont redefine random functions here.  U-Boot should already have all the
sleep functions you need

> +
> +#if SYS_LIGHTWEIGHT_PROT

Is this working? Can we define 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;
> +
> +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)

All these macros seem unnecessary.  Just assign types to NULL directly etc

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

Are those really needed?  Why do we just return 0? 

> +
> +#endif /* LWIP_ARCH_SYS_ARCH_H */
> diff --git a/net/lwip/port/include/limits.h b/net/lwip/port/include/limits.h
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/net/lwip/port/sys-arch.c b/net/lwip/port/sys-arch.c
> new file mode 100644
> index 0000000000..609eeccf8c
> --- /dev/null
> +++ b/net/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();

I dont see why we cant use the U-Boot defined ones directly

> +}
> +
> -- 
> 2.30.2
> 

Thanks
/Ilias

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

* Re: [PATCHv6 07/14] net/lwip: implement ping cmd
  2023-08-16  8:42   ` Ilias Apalodimas
@ 2023-08-16  9:09     ` Maxim Uvarov
  2023-08-16 14:39       ` Simon Glass
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-16  9:09 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Wed, 16 Aug 2023 at 14:42, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
> >  * can return immediately if previous request was cached or it might
> require
> > @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
> >  *         !0 if error
> >  */
> >  int ulwip_wget(ulong addr, char *url);
> > +
> > +/**
> > + * ulwip_tftp() - load file with tftp
> > + *
> > + * Load file with tftp to specific address
> > + *
> > + * @param addr - address to store downloaded file
> > + * @param filename - file name on remote tftp server to download
>
> Please fix function comments properly
>
> > + *
> > + *
> > + * @return 0 if success, !0 if error
> > + */
> > +int ulwip_tftp(ulong addr, const char *filename);
> > +
> > +/*
> > +* This function creates the ping for  address provided in parameters.
> > +* After this function you need to invoke the polling
> > +* loop to process network communication.
> > +*
> > +*
> > +* @ping_addr  start address to download result
> > +* Return: 0 for success
> > +*         !0 if error
> > +*/
> > +int ulwip_ping(char *ping_addr);
> > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > index 4c6df94807..8b3e843426 100644
> > --- a/net/lwip/Makefile
> > +++ b/net/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/net/lwip/apps/ping/Makefile b/net/lwip/apps/ping/Makefile
> > new file mode 100644
> > index 0000000000..dc63feb7b5
> > --- /dev/null
> > +++ b/net/lwip/apps/ping/Makefile
> > @@ -0,0 +1,11 @@
> > +ccflags-y += -I$(srctree)/net/lwip/port/include
> > +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include
> -I$(srctree)/net/lwip
> > +ccflags-y += -I$(obj)
> > +
> > +.PHONY: $(obj)/ping.c
> > +$(obj)/ping.o: $(obj)/ping.c
> > +$(obj)/ping.c:
> > +     cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c
> b/net/lwip/apps/ping/lwip_ping.c
> > new file mode 100644
> > index 0000000000..611fcaf591
> > --- /dev/null
> > +++ b/net/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 "lwip_ping.h"
> > +
> > +static ip_addr_t ip_target;
> > +
> > +static int ulwip_ping_tmo(void)
> > +{
> > +
> > +     log_err("ping failed; host %s is not alive\n",
> ipaddr_ntoa(&ip_target));
> > +     return 1;
> > +}
> > +
> > +int ulwip_ping(char *ping_addr)
> > +{
> > +     int err;
> > +
> > +     err = ipaddr_aton(ping_addr, &ip_target);
> > +     if (!err) {
> > +             log_err("wrong ping addr string \"%s\" \n", ping_addr);
>
> Invalid ip address is enough
>
> > +             return -1;
> > +     }
> > +
> > +     ulwip_set_tmo(ulwip_ping_tmo);
> > +
> > +     ping_init(&ip_target);
> > +     ping_send_now();
> > +
> > +     return 0;
> > +}
> > diff --git a/net/lwip/apps/ping/lwip_ping.h
> b/net/lwip/apps/ping/lwip_ping.h
> > new file mode 100644
> > index 0000000000..0374f07d9e
> > --- /dev/null
> > +++ b/net/lwip/apps/ping/lwip_ping.h
> > @@ -0,0 +1,15 @@
> > +/* 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>
> > +
> > +void ping_raw_init(void);
> > +void ping_send_now(void);
> > +
> > +#endif /* LWIP_PING_H */
> > diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
> > new file mode 100644
> > index 0000000000..006a18c658
> > --- /dev/null
> > +++ b/net/lwip/apps/ping/ping.h
> > @@ -0,0 +1,19 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#include <net/ulwip.h>
> > +#include "lwip/ip_addr.h"
> > +
> > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
> > +#define PING_RESULT(cond) { \
> > +     if (cond == 1) { \
> > +             printf("host %s a alive\n", ipaddr_ntoa(addr)); \
> > +             printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
> > +             ulwip_exit(0); \
> > +     } else { \
> > +             printf("ping failed; host %s in not alive\n",\
> > +                    ipaddr_ntoa(addr)); \
> > +             ulwip_exit(-1); \
> > +     } \
> > +     } while (0);
>
> On the previous patch you are defining a function to do something similar
> (httpc_result()).  We need to be consistent on this.  Can we define a
> common function for all failures?  Certianly don't define a macro here and
> a function elsewhere
>

Ilias, there I reuse lwip example ping.c. It has PING_RESULT which can be
redefined by the application.
This is a way to not modify this original ping.c example code.
The common part of this function and httpc_result() is ulwip_exit(err) with
some additional print (print is differ).

BR,
Maxim.


>
> > +
> > +void ping_init(const ip_addr_t *ping_addr);
> > --
> > 2.30.2
> >
>
> Thanks
> /Ilias
>

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

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

On Mon, Aug 14, 2023 at 07:32:50PM +0600, Maxim Uvarov wrote:

Commit message missing again

> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> ---
>  cmd/Makefile   |   1 +
>  cmd/net-lwip.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 307 insertions(+)
>  create mode 100644 cmd/net-lwip.c
> +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc,
> +		      char *const argv[])
> +{
> +	if (!ulwip_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)

We discussed this in the previous patchset but I am not convinced this is
the best approach.  Instead of setting the callback function on the dhcp
and ping commands and calling a function pointer here,  just define
discrete function and set them during net_set_timeout_handler()
if there is common code like eth_halt() etc just create a function with
them

> +{
> +	eth_halt();
> +	ulwip_tmo();
> +	net_set_state(NETLOOP_FAIL);	/* we did not get the reply */
> +	ulwip_loop_set(0);
> +}
> +
> +int ulwip_loop(void)
> +{
> +	int ret = CMD_RET_FAILURE;
> +
> +	ulwip_loop_set(1);
> +	if (!net_loop(LWIP))
> +		ret = CMD_RET_SUCCESS;
> +	ulwip_loop_set(0);
> +	return ret;
> +}
> +
> +#if defined(CONFIG_CMD_PING)
> +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
> +		 char *const argv[])
> +{
> +	int ret;
> +
> +	if (argc < 2) {
> +		printf("argc = %d, error\n", argc);
> +		return CMD_RET_USAGE;
> +	}
> +
> +	ret = ulwip_init();
> +	if (ret) {
> +		log_err("ulwip_init err %d\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	printf("Using %s device\n", eth_get_name());
> +	printf("pinging addr: %s\n", argv[1]);
> +
> +	net_set_timeout_handler(1000UL, ulwip_timeout_handler);
> +
> +	if (ulwip_ping(argv[1])) {
> +		printf("ping init fail\n");
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	return ulwip_loop();
> +}
> +#endif /* CONFIG_CMD_PING */
> +
> +#if defined(CONFIG_CMD_WGET)
> +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
> +		 char *const argv[])
> +{
> +	char *url;
> +	int ret;
> +
> +	if (argc < 2)
> +		return CMD_RET_USAGE;
> +
> +	url = argv[1];
> +
> +	ret = ulwip_init();
> +	if (ret) {
> +		log_err("ulwip_init err %d\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	ret = ulwip_wget(image_load_addr, url);
> +	if (ret) {
> +		log_err("lwip_wget err %d\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +
> +	return ulwip_loop();
> +}
> +#endif
> +
> +#if defined(CONFIG_CMD_TFTPBOOT)
> +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;
> +	}
> +
> +	ret = ulwip_init();
> +	if (ret) {
> +		log_err("ulwip_init err %d\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	ret = ulwip_tftp(image_load_addr, filename);

filename can be NULL.  We went through this on v4 as well.  Go through all
the comments and fix them before v6. 

> +	if (ret)
> +		return ret;
> +
> +	return ulwip_loop();
> +}
> +#endif /* CONFIG_CMD_TFTPBOOT */
> +
> +#if defined(CONFIG_CMD_DHCP)
> +int do_lwip_dhcp(void)
> +{
> +	int ret;
> +	char *filename;
> +
> +	ret = ulwip_init();
> +	if (ret) {
> +		log_err("ulwip_init err %d\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	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) {
> +			log_notice("no bootfile\n");
> +			return CMD_RET_SUCCESS;
> +		}
> +
> +		ret = ulwip_init();
> +		if (ret) {
> +			log_err("ulwip_init err %d\n", ret);
> +			return CMD_RET_FAILURE;
> +		}
> +
> +		net_set_timeout_handler(20000UL, ulwip_timeout_handler);
> +		ulwip_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; /* lwip/err.h */
> +
> +	if (argc == 1)
> +		return CMD_RET_USAGE;
> +
> +	name = argv[1];
> +
> +	if (argc == 3)
> +		varname = argv[2];
> +	else
> +		varname = NULL;
> +
> +	ret = ulwip_init();
> +	if (ret) {
> +		log_err("ulwip_init err %d\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	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(init, 1, 0, do_lwip_init,
> +			 "initialize lwip stack", ""),
> +#if defined(CONFIG_CMD_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",
> +	"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"
> +	);
> -- 
> 2.30.2
> 

Thanks
/Ilias

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

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-15 14:42       ` Tom Rini
@ 2023-08-16 10:26         ` Ilias Apalodimas
  2023-08-16 11:01           ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-16 10:26 UTC (permalink / raw)
  To: Tom Rini
  Cc: Maxim Uvarov, Heinrich Schuchardt, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

On Tue, 15 Aug 2023 at 17:42, Tom Rini <trini@konsulko.com> wrote:
>
> On Tue, Aug 15, 2023 at 06:42:14PM +0600, Maxim Uvarov wrote:
> > On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > wrote:
> >
> > [...]
> >
> >
> > > > +/*
> > > > +* This function creates the DNS request to resolve a domain host name.
> > > Function
> > >
> > > You need the name of the function as well.  Please have a look at how the
> > > rest of the code is documented.
> > >
> > > > +* can return immediately if previous request was cached or it might
> > > require
> > > > +* entering the polling loop for a request to a remote server.
> > > > +*
> > > > +* @name  dns name to resolve
> > >
> > > @name: etc
> > >
> > > > +* @varname (optional) U-Boot variable name to store the result
> > > > +* Return: ERR_OK(0) for fetching entry from the cache
> > > > +*         ERR_INPROGRESS(-5) success, can go to the polling loop
> > > > +*         Other value < 0, if error
> > > > +*/
> > > >
> > >
> >
> > Is there any command to check all the files for the comments style?
>
> I suspect if you included them in docs, htmldocs/etc would note
> problems, Heinrich?
>

Yes 'make htmldocs' blows up on errors, at least for the EFI subsystem

Cheers
/Ilias
> --
> Tom

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

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-16 10:26         ` Ilias Apalodimas
@ 2023-08-16 11:01           ` Maxim Uvarov
  2023-08-16 11:54             ` Ilias Apalodimas
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-16 11:01 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Heinrich Schuchardt, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

On Wed, 16 Aug 2023 at 16:26, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> On Tue, 15 Aug 2023 at 17:42, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Tue, Aug 15, 2023 at 06:42:14PM +0600, Maxim Uvarov wrote:
> > > On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <
> ilias.apalodimas@linaro.org>
> > > wrote:
> > >
> > > [...]
> > >
> > >
> > > > > +/*
> > > > > +* This function creates the DNS request to resolve a domain host
> name.
> > > > Function
> > > >
> > > > You need the name of the function as well.  Please have a look at
> how the
> > > > rest of the code is documented.
> > > >
> > > > > +* can return immediately if previous request was cached or it
> might
> > > > require
> > > > > +* entering the polling loop for a request to a remote server.
> > > > > +*
> > > > > +* @name  dns name to resolve
> > > >
> > > > @name: etc
> > > >
> > > > > +* @varname (optional) U-Boot variable name to store the result
> > > > > +* Return: ERR_OK(0) for fetching entry from the cache
> > > > > +*         ERR_INPROGRESS(-5) success, can go to the polling loop
> > > > > +*         Other value < 0, if error
> > > > > +*/
> > > > >
> > > >
> > >
> > > Is there any command to check all the files for the comments style?
> >
> > I suspect if you included them in docs, htmldocs/etc would note
> > problems, Heinrich?
> >
>
> Yes 'make htmldocs' blows up on errors, at least for the EFI subsystem
>
> Cheers
> /Ilias
>

O! Ilias thanks for the reference. First patch for doc/develop/net_lwip.rst
needed direct references:

.. kernel-doc:: include/net/lwip.h
   :internal:

to force Sphinx  to generate docs for these files. (as I understand for .c
files it does checks and for .h files it generates docs).

Without specification syntax is not validated. It will be good to do
something to check all U-Boot .h files for the common syntax later.

BR,
Maxim.




> > --
> > Tom
>

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

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-16 11:01           ` Maxim Uvarov
@ 2023-08-16 11:54             ` Ilias Apalodimas
  2023-08-16 12:24               ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Ilias Apalodimas @ 2023-08-16 11:54 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Tom Rini, Heinrich Schuchardt, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

On Wed, 16 Aug 2023 at 14:01, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
>
>
> On Wed, 16 Aug 2023 at 16:26, Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote:
>>
>> On Tue, 15 Aug 2023 at 17:42, Tom Rini <trini@konsulko.com> wrote:
>> >
>> > On Tue, Aug 15, 2023 at 06:42:14PM +0600, Maxim Uvarov wrote:
>> > > On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <ilias.apalodimas@linaro.org>
>> > > wrote:
>> > >
>> > > [...]
>> > >
>> > >
>> > > > > +/*
>> > > > > +* This function creates the DNS request to resolve a domain host name.
>> > > > Function
>> > > >
>> > > > You need the name of the function as well.  Please have a look at how the
>> > > > rest of the code is documented.
>> > > >
>> > > > > +* can return immediately if previous request was cached or it might
>> > > > require
>> > > > > +* entering the polling loop for a request to a remote server.
>> > > > > +*
>> > > > > +* @name  dns name to resolve
>> > > >
>> > > > @name: etc
>> > > >
>> > > > > +* @varname (optional) U-Boot variable name to store the result
>> > > > > +* Return: ERR_OK(0) for fetching entry from the cache
>> > > > > +*         ERR_INPROGRESS(-5) success, can go to the polling loop
>> > > > > +*         Other value < 0, if error
>> > > > > +*/
>> > > > >
>> > > >
>> > >
>> > > Is there any command to check all the files for the comments style?
>> >
>> > I suspect if you included them in docs, htmldocs/etc would note
>> > problems, Heinrich?
>> >
>>
>> Yes 'make htmldocs' blows up on errors, at least for the EFI subsystem
>>
>> Cheers
>> /Ilias
>
>
> O! Ilias thanks for the reference. First patch for doc/develop/net_lwip.rst needed direct references:
>
> .. kernel-doc:: include/net/lwip.h
>    :internal:
>
> to force Sphinx  to generate docs for these files. (as I understand for .c files it does checks and for .h files it generates docs).
>
> Without specification syntax is not validated. It will be good to do something to check all U-Boot .h files for the common syntax later.

You need comments that look like this
  /**
   * parse_event_log_header() -  Parse and verify the event log header
fields
   *
   * @buffer:                     Pointer to the start of the eventlog
   * @size:                       Size of the eventlog
   * @pos:                        Return offset of the next event in
buffer right
   *                              after the event header i.e specID
   *
   * Return:      status code
   */

Cheers
/Ilias
>
> BR,
> Maxim.
>
>
>
>>
>> > --
>> > Tom

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

* Re: [PATCHv6 03/14] net/lwip: implement dns cmd
  2023-08-16 11:54             ` Ilias Apalodimas
@ 2023-08-16 12:24               ` Maxim Uvarov
  0 siblings, 0 replies; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-16 12:24 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Heinrich Schuchardt, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

On Wed, 16 Aug 2023 at 17:54, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> On Wed, 16 Aug 2023 at 14:01, Maxim Uvarov <maxim.uvarov@linaro.org>
> wrote:
> >
> >
> >
> > On Wed, 16 Aug 2023 at 16:26, Ilias Apalodimas <
> ilias.apalodimas@linaro.org> wrote:
> >>
> >> On Tue, 15 Aug 2023 at 17:42, Tom Rini <trini@konsulko.com> wrote:
> >> >
> >> > On Tue, Aug 15, 2023 at 06:42:14PM +0600, Maxim Uvarov wrote:
> >> > > On Mon, 14 Aug 2023 at 20:19, Ilias Apalodimas <
> ilias.apalodimas@linaro.org>
> >> > > wrote:
> >> > >
> >> > > [...]
> >> > >
> >> > >
> >> > > > > +/*
> >> > > > > +* This function creates the DNS request to resolve a domain
> host name.
> >> > > > Function
> >> > > >
> >> > > > You need the name of the function as well.  Please have a look at
> how the
> >> > > > rest of the code is documented.
> >> > > >
> >> > > > > +* can return immediately if previous request was cached or it
> might
> >> > > > require
> >> > > > > +* entering the polling loop for a request to a remote server.
> >> > > > > +*
> >> > > > > +* @name  dns name to resolve
> >> > > >
> >> > > > @name: etc
> >> > > >
> >> > > > > +* @varname (optional) U-Boot variable name to store the result
> >> > > > > +* Return: ERR_OK(0) for fetching entry from the cache
> >> > > > > +*         ERR_INPROGRESS(-5) success, can go to the polling
> loop
> >> > > > > +*         Other value < 0, if error
> >> > > > > +*/
> >> > > > >
> >> > > >
> >> > >
> >> > > Is there any command to check all the files for the comments style?
> >> >
> >> > I suspect if you included them in docs, htmldocs/etc would note
> >> > problems, Heinrich?
> >> >
> >>
> >> Yes 'make htmldocs' blows up on errors, at least for the EFI subsystem
> >>
> >> Cheers
> >> /Ilias
> >
> >
> > O! Ilias thanks for the reference. First patch for
> doc/develop/net_lwip.rst needed direct references:
> >
> > .. kernel-doc:: include/net/lwip.h
> >    :internal:
> >
> > to force Sphinx  to generate docs for these files. (as I understand for
> .c files it does checks and for .h files it generates docs).
> >
> > Without specification syntax is not validated. It will be good to do
> something to check all U-Boot .h files for the common syntax later.
>
> You need comments that look like this
>   /**
>    * parse_event_log_header() -  Parse and verify the event log header
> fields
>    *
>    * @buffer:                     Pointer to the start of the eventlog
>    * @size:                       Size of the eventlog
>    * @pos:                        Return offset of the next event in
> buffer right
>    *                              after the event header i.e specID
>    *
>    * Return:      status code
>    */
>
> Cheers
> /Ilias
>


Yes, I added html generation for these files and now I can fix style.


> >
> > BR,
> > Maxim.
> >
> >
> >
> >>
> >> > --
> >> > Tom
>

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

* Re: [PATCHv6 07/14] net/lwip: implement ping cmd
  2023-08-16  9:09     ` Maxim Uvarov
@ 2023-08-16 14:39       ` Simon Glass
  2023-08-16 20:15         ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2023-08-16 14:39 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, trini, goldsimon, lwip-devel

Hi Maxim,

On Wed, 16 Aug 2023 at 03:09, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
> On Wed, 16 Aug 2023 at 14:42, Ilias Apalodimas <ilias.apalodimas@linaro.org>
> wrote:
>
> > On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
> > >  * can return immediately if previous request was cached or it might
> > require
> > > @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
> > >  *         !0 if error
> > >  */
> > >  int ulwip_wget(ulong addr, char *url);
> > > +
> > > +/**
> > > + * ulwip_tftp() - load file with tftp
> > > + *
> > > + * Load file with tftp to specific address
> > > + *
> > > + * @param addr - address to store downloaded file
> > > + * @param filename - file name on remote tftp server to download
> >
> > Please fix function comments properly
> >
> > > + *
> > > + *
> > > + * @return 0 if success, !0 if error
> > > + */
> > > +int ulwip_tftp(ulong addr, const char *filename);
> > > +
> > > +/*
> > > +* This function creates the ping for  address provided in parameters.
> > > +* After this function you need to invoke the polling
> > > +* loop to process network communication.
> > > +*
> > > +*
> > > +* @ping_addr  start address to download result
> > > +* Return: 0 for success
> > > +*         !0 if error
> > > +*/
> > > +int ulwip_ping(char *ping_addr);
> > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > index 4c6df94807..8b3e843426 100644
> > > --- a/net/lwip/Makefile
> > > +++ b/net/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/net/lwip/apps/ping/Makefile b/net/lwip/apps/ping/Makefile
> > > new file mode 100644
> > > index 0000000000..dc63feb7b5
> > > --- /dev/null
> > > +++ b/net/lwip/apps/ping/Makefile
> > > @@ -0,0 +1,11 @@
> > > +ccflags-y += -I$(srctree)/net/lwip/port/include
> > > +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include
> > -I$(srctree)/net/lwip
> > > +ccflags-y += -I$(obj)
> > > +
> > > +.PHONY: $(obj)/ping.c
> > > +$(obj)/ping.o: $(obj)/ping.c
> > > +$(obj)/ping.c:
> > > +     cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c
> > b/net/lwip/apps/ping/lwip_ping.c
> > > new file mode 100644
> > > index 0000000000..611fcaf591
> > > --- /dev/null
> > > +++ b/net/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 "lwip_ping.h"
> > > +
> > > +static ip_addr_t ip_target;
> > > +
> > > +static int ulwip_ping_tmo(void)
> > > +{
> > > +
> > > +     log_err("ping failed; host %s is not alive\n",
> > ipaddr_ntoa(&ip_target));
> > > +     return 1;
> > > +}
> > > +
> > > +int ulwip_ping(char *ping_addr)
> > > +{
> > > +     int err;
> > > +
> > > +     err = ipaddr_aton(ping_addr, &ip_target);
> > > +     if (!err) {
> > > +             log_err("wrong ping addr string \"%s\" \n", ping_addr);
> >
> > Invalid ip address is enough
> >
> > > +             return -1;
> > > +     }
> > > +
> > > +     ulwip_set_tmo(ulwip_ping_tmo);
> > > +
> > > +     ping_init(&ip_target);
> > > +     ping_send_now();
> > > +
> > > +     return 0;
> > > +}
> > > diff --git a/net/lwip/apps/ping/lwip_ping.h
> > b/net/lwip/apps/ping/lwip_ping.h
> > > new file mode 100644
> > > index 0000000000..0374f07d9e
> > > --- /dev/null
> > > +++ b/net/lwip/apps/ping/lwip_ping.h
> > > @@ -0,0 +1,15 @@
> > > +/* 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>
> > > +
> > > +void ping_raw_init(void);
> > > +void ping_send_now(void);
> > > +
> > > +#endif /* LWIP_PING_H */
> > > diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
> > > new file mode 100644
> > > index 0000000000..006a18c658
> > > --- /dev/null
> > > +++ b/net/lwip/apps/ping/ping.h
> > > @@ -0,0 +1,19 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +
> > > +#include <net/ulwip.h>
> > > +#include "lwip/ip_addr.h"
> > > +
> > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
> > > +#define PING_RESULT(cond) { \
> > > +     if (cond == 1) { \
> > > +             printf("host %s a alive\n", ipaddr_ntoa(addr)); \
> > > +             printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
> > > +             ulwip_exit(0); \
> > > +     } else { \
> > > +             printf("ping failed; host %s in not alive\n",\
> > > +                    ipaddr_ntoa(addr)); \
> > > +             ulwip_exit(-1); \
> > > +     } \
> > > +     } while (0);
> >
> > On the previous patch you are defining a function to do something similar
> > (httpc_result()).  We need to be consistent on this.  Can we define a
> > common function for all failures?  Certianly don't define a macro here and
> > a function elsewhere
> >
>
> Ilias, there I reuse lwip example ping.c. It has PING_RESULT which can be
> redefined by the application.
> This is a way to not modify this original ping.c example code.
> The common part of this function and httpc_result() is ulwip_exit(err) with
> some additional print (print is differ).

I'll reply on this patch, although it is a general comment.

I would like to see if we can use the cyclic feature to allow network
operations to happen in the background. This would involve splitting
each operation into:

- setup start and kick off, e.g. ping_sttart()
- checking what needs doing, e.g. ping_poll()
- finish and clean-up, e.g. ping_finish()

So something like:

ping -B 1.2.3.4

(-B is background)

That would fire off the packet but immediately return with a prompt.
When the pings are received they would show on the console, with a new
prompt displayed. The same for tftp -B...it would start the transfer
but allow other commands to be sent while it is in progress.

Part of the reason for this is that when booting there are a lot of
operations which take a long time and nothing happens until everything
is done. For example, with standard boot, mmc devices can be shown
right away, but USB and network ones take a lot longer, so having OS's
on those devices appear later on the slower devices is desirable for
the user.

Is this something that lwip can support? It is one reason why I have
advocating putting the state in a struct instead of having a lot of
separate vars.

Regards,
Simon

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

* Re: [PATCHv6 07/14] net/lwip: implement ping cmd
  2023-08-16 14:39       ` Simon Glass
@ 2023-08-16 20:15         ` Maxim Uvarov
  2023-08-18  3:10           ` Simon Glass
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-16 20:15 UTC (permalink / raw)
  To: Simon Glass
  Cc: Ilias Apalodimas, u-boot, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel, Peter Robinson

On Wed, 16 Aug 2023 at 20:39, Simon Glass <sjg@google.com> wrote:

> Hi Maxim,
>
> On Wed, 16 Aug 2023 at 03:09, Maxim Uvarov <maxim.uvarov@linaro.org>
> wrote:
> >
> > On Wed, 16 Aug 2023 at 14:42, Ilias Apalodimas <
> ilias.apalodimas@linaro.org>
> > wrote:
> >
> > > On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
> > > >  * can return immediately if previous request was cached or it might
> > > require
> > > > @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
> > > >  *         !0 if error
> > > >  */
> > > >  int ulwip_wget(ulong addr, char *url);
> > > > +
> > > > +/**
> > > > + * ulwip_tftp() - load file with tftp
> > > > + *
> > > > + * Load file with tftp to specific address
> > > > + *
> > > > + * @param addr - address to store downloaded file
> > > > + * @param filename - file name on remote tftp server to download
> > >
> > > Please fix function comments properly
> > >
> > > > + *
> > > > + *
> > > > + * @return 0 if success, !0 if error
> > > > + */
> > > > +int ulwip_tftp(ulong addr, const char *filename);
> > > > +
> > > > +/*
> > > > +* This function creates the ping for  address provided in
> parameters.
> > > > +* After this function you need to invoke the polling
> > > > +* loop to process network communication.
> > > > +*
> > > > +*
> > > > +* @ping_addr  start address to download result
> > > > +* Return: 0 for success
> > > > +*         !0 if error
> > > > +*/
> > > > +int ulwip_ping(char *ping_addr);
> > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > > index 4c6df94807..8b3e843426 100644
> > > > --- a/net/lwip/Makefile
> > > > +++ b/net/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/net/lwip/apps/ping/Makefile
> b/net/lwip/apps/ping/Makefile
> > > > new file mode 100644
> > > > index 0000000000..dc63feb7b5
> > > > --- /dev/null
> > > > +++ b/net/lwip/apps/ping/Makefile
> > > > @@ -0,0 +1,11 @@
> > > > +ccflags-y += -I$(srctree)/net/lwip/port/include
> > > > +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include
> > > -I$(srctree)/net/lwip
> > > > +ccflags-y += -I$(obj)
> > > > +
> > > > +.PHONY: $(obj)/ping.c
> > > > +$(obj)/ping.o: $(obj)/ping.c
> > > > +$(obj)/ping.c:
> > > > +     cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c
> > > b/net/lwip/apps/ping/lwip_ping.c
> > > > new file mode 100644
> > > > index 0000000000..611fcaf591
> > > > --- /dev/null
> > > > +++ b/net/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 "lwip_ping.h"
> > > > +
> > > > +static ip_addr_t ip_target;
> > > > +
> > > > +static int ulwip_ping_tmo(void)
> > > > +{
> > > > +
> > > > +     log_err("ping failed; host %s is not alive\n",
> > > ipaddr_ntoa(&ip_target));
> > > > +     return 1;
> > > > +}
> > > > +
> > > > +int ulwip_ping(char *ping_addr)
> > > > +{
> > > > +     int err;
> > > > +
> > > > +     err = ipaddr_aton(ping_addr, &ip_target);
> > > > +     if (!err) {
> > > > +             log_err("wrong ping addr string \"%s\" \n", ping_addr);
> > >
> > > Invalid ip address is enough
> > >
> > > > +             return -1;
> > > > +     }
> > > > +
> > > > +     ulwip_set_tmo(ulwip_ping_tmo);
> > > > +
> > > > +     ping_init(&ip_target);
> > > > +     ping_send_now();
> > > > +
> > > > +     return 0;
> > > > +}
> > > > diff --git a/net/lwip/apps/ping/lwip_ping.h
> > > b/net/lwip/apps/ping/lwip_ping.h
> > > > new file mode 100644
> > > > index 0000000000..0374f07d9e
> > > > --- /dev/null
> > > > +++ b/net/lwip/apps/ping/lwip_ping.h
> > > > @@ -0,0 +1,15 @@
> > > > +/* 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>
> > > > +
> > > > +void ping_raw_init(void);
> > > > +void ping_send_now(void);
> > > > +
> > > > +#endif /* LWIP_PING_H */
> > > > diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
> > > > new file mode 100644
> > > > index 0000000000..006a18c658
> > > > --- /dev/null
> > > > +++ b/net/lwip/apps/ping/ping.h
> > > > @@ -0,0 +1,19 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > > +
> > > > +#include <net/ulwip.h>
> > > > +#include "lwip/ip_addr.h"
> > > > +
> > > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
> > > > +#define PING_RESULT(cond) { \
> > > > +     if (cond == 1) { \
> > > > +             printf("host %s a alive\n", ipaddr_ntoa(addr)); \
> > > > +             printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
> > > > +             ulwip_exit(0); \
> > > > +     } else { \
> > > > +             printf("ping failed; host %s in not alive\n",\
> > > > +                    ipaddr_ntoa(addr)); \
> > > > +             ulwip_exit(-1); \
> > > > +     } \
> > > > +     } while (0);
> > >
> > > On the previous patch you are defining a function to do something
> similar
> > > (httpc_result()).  We need to be consistent on this.  Can we define a
> > > common function for all failures?  Certianly don't define a macro here
> and
> > > a function elsewhere
> > >
> >
> > Ilias, there I reuse lwip example ping.c. It has PING_RESULT which can be
> > redefined by the application.
> > This is a way to not modify this original ping.c example code.
> > The common part of this function and httpc_result() is ulwip_exit(err)
> with
> > some additional print (print is differ).
>
> I'll reply on this patch, although it is a general comment.
>
> I would like to see if we can use the cyclic feature to allow network
> operations to happen in the background. This would involve splitting
> each operation into:
>
> - setup start and kick off, e.g. ping_sttart()
> - checking what needs doing, e.g. ping_poll()
> - finish and clean-up, e.g. ping_finish()
>
> So something like:
>
> ping -B 1.2.3.4
>
> (-B is background)
>
> That would fire off the packet but immediately return with a prompt.
> When the pings are received they would show on the console, with a new
> prompt displayed. The same for tftp -B...it would start the transfer
> but allow other commands to be sent while it is in progress.
>
> Part of the reason for this is that when booting there are a lot of
> operations which take a long time and nothing happens until everything
> is done. For example, with standard boot, mmc devices can be shown
> right away, but USB and network ones take a lot longer, so having OS's
> on those devices appear later on the slower devices is desirable for
> the user.
>
> Is this something that lwip can support? It is one reason why I have
> advocating putting the state in a struct instead of having a lot of
> separate vars.
>
> Regards,
> Simon
>

This functionality can be added. I do not see any restrictions implementing
that.
Added I mean to U-Boot. lwip will definitely work with it.

There is no specific poll() for application. Application just do init() and
request
the needed packets (port, type etc, like sockets) and then common lwip
poll()
function is called.

To implement background we need to periodically call eth_rx() and
ulwip_poll() to feed lwip
stack with rx packets when we are in the cmd shell. I see in some places we
call schedule()
to reprogram wdt, if we call rx polling loop in the similar way the app
will work in the background.

We might also want to support 2 applications at the same time. Like a
telnet server
and ping. Multiply applications also work with lwip.

Even parallel download can save some time:
wget -B http://url1/zImage
wget -B http//url2/dtb
(-B = background)

But I'm thinking if we can implement background  in a more generic way in
U-Boot cmd. Things like
mount UBI fs, or download from SPI flash is slow. Or probably we can also
do some loading while
verifying the zImage checksum.

BR,
Maxim.

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-14 15:29       ` Tom Rini
@ 2023-08-17 13:46         ` Maxim Uvarov
  2023-08-17 14:04           ` Peter Robinson
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-17 13:46 UTC (permalink / raw)
  To: Tom Rini
  Cc: Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, goldsimon, lwip-devel

On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:

> On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
> ilias.apalodimas@linaro.org>
> > wrote:
> >
> > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > > > Implement function for dhcp command with lwIP variant. Usage and
> output
> > > is
> > > > the same as the original command. This code called by compatibility
> code
> > > > between U-Boot and lwIP.
> > >
> > > Same as the dns command
> > >
> > > >
> > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > > > ---
> > > >  include/net/lwip.h             | 10 +++++++
> > > >  net/lwip/Makefile              |  1 +
> > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
> ++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 62 insertions(+)
> > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> > > >
> > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > > > index c83b5c8231..2f035280eb 100644
> > > > --- a/include/net/lwip.h
> > > > +++ b/include/net/lwip.h
> > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag,
> int
> > > argc,
> > > >  *         Other value < 0, if error
> > > >  */
> > > >  int ulwip_dns(char *name, char *varname);
> > > > +
> > > > +/*
> > > > +* This function creates the DHCP request to obtain IP address. If
> DHCP
> > > server
> > >
> > > Sphinx needs something more, please check the existing functions
> > >
> > > > +* returns file name, this file will be downloaded with tftp.  After
> this
> > > > +* function you need to invoke the polling loop to process network
> > > communication.
> > > > +*
> > > > +* Return: 0 if success
> > > > +*         Other value < 0, if error
> > > > +*/
> > > > +int ulwip_dhcp(void);
> > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > > index 6d2c00605b..59323fb325 100644
> > > > --- a/net/lwip/Makefile
> > > > +
> > > > +static struct dhcp dhcp;
> > > > +
> > > > +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);
> > >
> > > What's (1)?
> > >
> > >
> > Only one lwip netif is registered. 1 - here is the index of netif. I
> don't
> > think that there is any definition for that...
> >
>
> And there's only ever going to be one interface (even if we have ipv4
> and ipv60 ? If so, define it to something please, thanks.
>
> --
> Tom
>

Yes, one interface has 2 addresses ipv4 and ipv6.

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-17 13:46         ` Maxim Uvarov
@ 2023-08-17 14:04           ` Peter Robinson
  2023-08-17 14:55             ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Peter Robinson @ 2023-08-17 14:04 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Tom Rini, Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, goldsimon, lwip-devel

On Thu, Aug 17, 2023 at 2:46 PM Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
> On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:
>
> > On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> > > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
> > ilias.apalodimas@linaro.org>
> > > wrote:
> > >
> > > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > > > > Implement function for dhcp command with lwIP variant. Usage and
> > output
> > > > is
> > > > > the same as the original command. This code called by compatibility
> > code
> > > > > between U-Boot and lwIP.
> > > >
> > > > Same as the dns command
> > > >
> > > > >
> > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > > > > ---
> > > > >  include/net/lwip.h             | 10 +++++++
> > > > >  net/lwip/Makefile              |  1 +
> > > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
> > ++++++++++++++++++++++++++++++++++
> > > > >  3 files changed, 62 insertions(+)
> > > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> > > > >
> > > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > > > > index c83b5c8231..2f035280eb 100644
> > > > > --- a/include/net/lwip.h
> > > > > +++ b/include/net/lwip.h
> > > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag,
> > int
> > > > argc,
> > > > >  *         Other value < 0, if error
> > > > >  */
> > > > >  int ulwip_dns(char *name, char *varname);
> > > > > +
> > > > > +/*
> > > > > +* This function creates the DHCP request to obtain IP address. If
> > DHCP
> > > > server
> > > >
> > > > Sphinx needs something more, please check the existing functions
> > > >
> > > > > +* returns file name, this file will be downloaded with tftp.  After
> > this
> > > > > +* function you need to invoke the polling loop to process network
> > > > communication.
> > > > > +*
> > > > > +* Return: 0 if success
> > > > > +*         Other value < 0, if error
> > > > > +*/
> > > > > +int ulwip_dhcp(void);
> > > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > > > index 6d2c00605b..59323fb325 100644
> > > > > --- a/net/lwip/Makefile
> > > > > +
> > > > > +static struct dhcp dhcp;
> > > > > +
> > > > > +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);
> > > >
> > > > What's (1)?
> > > >
> > > >
> > > Only one lwip netif is registered. 1 - here is the index of netif. I
> > don't
> > > think that there is any definition for that...
> > >
> >
> > And there's only ever going to be one interface (even if we have ipv4
> > and ipv60 ? If so, define it to something please, thanks.
> >
> > --
> > Tom
> >
>
> Yes, one interface has 2 addresses ipv4 and ipv6.

What about a device like a router which may have multiple wired
ethernet interface?

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-17 14:04           ` Peter Robinson
@ 2023-08-17 14:55             ` Maxim Uvarov
  2023-08-17 15:10               ` Tom Rini
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-17 14:55 UTC (permalink / raw)
  To: Peter Robinson
  Cc: Tom Rini, Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, goldsimon, lwip-devel

On Thu, 17 Aug 2023 at 20:04, Peter Robinson <pbrobinson@gmail.com> wrote:

> On Thu, Aug 17, 2023 at 2:46 PM Maxim Uvarov <maxim.uvarov@linaro.org>
> wrote:
> >
> > On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:
> >
> > > On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> > > > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
> > > ilias.apalodimas@linaro.org>
> > > > wrote:
> > > >
> > > > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > > > > > Implement function for dhcp command with lwIP variant. Usage and
> > > output
> > > > > is
> > > > > > the same as the original command. This code called by
> compatibility
> > > code
> > > > > > between U-Boot and lwIP.
> > > > >
> > > > > Same as the dns command
> > > > >
> > > > > >
> > > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > > > > > ---
> > > > > >  include/net/lwip.h             | 10 +++++++
> > > > > >  net/lwip/Makefile              |  1 +
> > > > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
> > > ++++++++++++++++++++++++++++++++++
> > > > > >  3 files changed, 62 insertions(+)
> > > > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> > > > > >
> > > > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > > > > > index c83b5c8231..2f035280eb 100644
> > > > > > --- a/include/net/lwip.h
> > > > > > +++ b/include/net/lwip.h
> > > > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int
> flag,
> > > int
> > > > > argc,
> > > > > >  *         Other value < 0, if error
> > > > > >  */
> > > > > >  int ulwip_dns(char *name, char *varname);
> > > > > > +
> > > > > > +/*
> > > > > > +* This function creates the DHCP request to obtain IP address.
> If
> > > DHCP
> > > > > server
> > > > >
> > > > > Sphinx needs something more, please check the existing functions
> > > > >
> > > > > > +* returns file name, this file will be downloaded with tftp.
> After
> > > this
> > > > > > +* function you need to invoke the polling loop to process
> network
> > > > > communication.
> > > > > > +*
> > > > > > +* Return: 0 if success
> > > > > > +*         Other value < 0, if error
> > > > > > +*/
> > > > > > +int ulwip_dhcp(void);
> > > > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > > > > index 6d2c00605b..59323fb325 100644
> > > > > > --- a/net/lwip/Makefile
> > > > > > +
> > > > > > +static struct dhcp dhcp;
> > > > > > +
> > > > > > +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);
> > > > >
> > > > > What's (1)?
> > > > >
> > > > >
> > > > Only one lwip netif is registered. 1 - here is the index of netif. I
> > > don't
> > > > think that there is any definition for that...
> > > >
> > >
> > > And there's only ever going to be one interface (even if we have ipv4
> > > and ipv60 ? If so, define it to something please, thanks.
> > >
> > > --
> > > Tom
> > >
> >
> > Yes, one interface has 2 addresses ipv4 and ipv6.
>
> What about a device like a router which may have multiple wired
> ethernet interface?
>

Yea, looks like we need lwip netif per U-Boots eth_devs. I did not yet
support several eth devices, but it will be good to add this to not break
existing functionality..

BR,
Maxim.

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-17 14:55             ` Maxim Uvarov
@ 2023-08-17 15:10               ` Tom Rini
  2023-08-18  9:39                 ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Tom Rini @ 2023-08-17 15:10 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Peter Robinson, Ilias Apalodimas, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

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

On Thu, Aug 17, 2023 at 08:55:17PM +0600, Maxim Uvarov wrote:
> On Thu, 17 Aug 2023 at 20:04, Peter Robinson <pbrobinson@gmail.com> wrote:
> 
> > On Thu, Aug 17, 2023 at 2:46 PM Maxim Uvarov <maxim.uvarov@linaro.org>
> > wrote:
> > >
> > > On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > > On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> > > > > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
> > > > ilias.apalodimas@linaro.org>
> > > > > wrote:
> > > > >
> > > > > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > > > > > > Implement function for dhcp command with lwIP variant. Usage and
> > > > output
> > > > > > is
> > > > > > > the same as the original command. This code called by
> > compatibility
> > > > code
> > > > > > > between U-Boot and lwIP.
> > > > > >
> > > > > > Same as the dns command
> > > > > >
> > > > > > >
> > > > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > > > > > > ---
> > > > > > >  include/net/lwip.h             | 10 +++++++
> > > > > > >  net/lwip/Makefile              |  1 +
> > > > > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
> > > > ++++++++++++++++++++++++++++++++++
> > > > > > >  3 files changed, 62 insertions(+)
> > > > > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> > > > > > >
> > > > > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > > > > > > index c83b5c8231..2f035280eb 100644
> > > > > > > --- a/include/net/lwip.h
> > > > > > > +++ b/include/net/lwip.h
> > > > > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int
> > flag,
> > > > int
> > > > > > argc,
> > > > > > >  *         Other value < 0, if error
> > > > > > >  */
> > > > > > >  int ulwip_dns(char *name, char *varname);
> > > > > > > +
> > > > > > > +/*
> > > > > > > +* This function creates the DHCP request to obtain IP address.
> > If
> > > > DHCP
> > > > > > server
> > > > > >
> > > > > > Sphinx needs something more, please check the existing functions
> > > > > >
> > > > > > > +* returns file name, this file will be downloaded with tftp.
> > After
> > > > this
> > > > > > > +* function you need to invoke the polling loop to process
> > network
> > > > > > communication.
> > > > > > > +*
> > > > > > > +* Return: 0 if success
> > > > > > > +*         Other value < 0, if error
> > > > > > > +*/
> > > > > > > +int ulwip_dhcp(void);
> > > > > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > > > > > index 6d2c00605b..59323fb325 100644
> > > > > > > --- a/net/lwip/Makefile
> > > > > > > +
> > > > > > > +static struct dhcp dhcp;
> > > > > > > +
> > > > > > > +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);
> > > > > >
> > > > > > What's (1)?
> > > > > >
> > > > > >
> > > > > Only one lwip netif is registered. 1 - here is the index of netif. I
> > > > don't
> > > > > think that there is any definition for that...
> > > > >
> > > >
> > > > And there's only ever going to be one interface (even if we have ipv4
> > > > and ipv60 ? If so, define it to something please, thanks.
> > > >
> > > > --
> > > > Tom
> > > >
> > >
> > > Yes, one interface has 2 addresses ipv4 and ipv6.
> >
> > What about a device like a router which may have multiple wired
> > ethernet interface?
> 
> Yea, looks like we need lwip netif per U-Boots eth_devs. I did not yet
> support several eth devices, but it will be good to add this to not break
> existing functionality..

The general case ends up being if we have more than one interface,
ethact is what's used.  I'm unsure off-hand if some of the fancier
networking-centric chipsets and devices have something more complex
setup in their stacks.

-- 
Tom

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

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

* Re: [PATCHv6 07/14] net/lwip: implement ping cmd
  2023-08-16 20:15         ` Maxim Uvarov
@ 2023-08-18  3:10           ` Simon Glass
  2023-08-18  9:27             ` Maxim Uvarov
  0 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2023-08-18  3:10 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Ilias Apalodimas, U-Boot Mailing List, Joe Hershberger,
	Ramon Fried, Tom Rini, Simon Goldschmidt, lwip-devel,
	Peter Robinson

Hi Maxim,

On Wed, 16 Aug 2023 at 14:15, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
>
>
> On Wed, 16 Aug 2023 at 20:39, Simon Glass <sjg@google.com> wrote:
>>
>> Hi Maxim,
>>
>> On Wed, 16 Aug 2023 at 03:09, Maxim Uvarov <maxim.uvarov@linaro.org>
wrote:
>> >
>> > On Wed, 16 Aug 2023 at 14:42, Ilias Apalodimas <
ilias.apalodimas@linaro.org>
>> > wrote:
>> >
>> > > On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
>> > > >  * can return immediately if previous request was cached or it
might
>> > > require
>> > > > @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
>> > > >  *         !0 if error
>> > > >  */
>> > > >  int ulwip_wget(ulong addr, char *url);
>> > > > +
>> > > > +/**
>> > > > + * ulwip_tftp() - load file with tftp
>> > > > + *
>> > > > + * Load file with tftp to specific address
>> > > > + *
>> > > > + * @param addr - address to store downloaded file
>> > > > + * @param filename - file name on remote tftp server to download
>> > >
>> > > Please fix function comments properly
>> > >
>> > > > + *
>> > > > + *
>> > > > + * @return 0 if success, !0 if error
>> > > > + */
>> > > > +int ulwip_tftp(ulong addr, const char *filename);
>> > > > +
>> > > > +/*
>> > > > +* This function creates the ping for  address provided in
parameters.
>> > > > +* After this function you need to invoke the polling
>> > > > +* loop to process network communication.
>> > > > +*
>> > > > +*
>> > > > +* @ping_addr  start address to download result
>> > > > +* Return: 0 for success
>> > > > +*         !0 if error
>> > > > +*/
>> > > > +int ulwip_ping(char *ping_addr);
>> > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
>> > > > index 4c6df94807..8b3e843426 100644
>> > > > --- a/net/lwip/Makefile
>> > > > +++ b/net/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/net/lwip/apps/ping/Makefile
b/net/lwip/apps/ping/Makefile
>> > > > new file mode 100644
>> > > > index 0000000000..dc63feb7b5
>> > > > --- /dev/null
>> > > > +++ b/net/lwip/apps/ping/Makefile
>> > > > @@ -0,0 +1,11 @@
>> > > > +ccflags-y += -I$(srctree)/net/lwip/port/include
>> > > > +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include
>> > > -I$(srctree)/net/lwip
>> > > > +ccflags-y += -I$(obj)
>> > > > +
>> > > > +.PHONY: $(obj)/ping.c
>> > > > +$(obj)/ping.o: $(obj)/ping.c
>> > > > +$(obj)/ping.c:
>> > > > +     cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c
>> > > b/net/lwip/apps/ping/lwip_ping.c
>> > > > new file mode 100644
>> > > > index 0000000000..611fcaf591
>> > > > --- /dev/null
>> > > > +++ b/net/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 "lwip_ping.h"
>> > > > +
>> > > > +static ip_addr_t ip_target;
>> > > > +
>> > > > +static int ulwip_ping_tmo(void)
>> > > > +{
>> > > > +
>> > > > +     log_err("ping failed; host %s is not alive\n",
>> > > ipaddr_ntoa(&ip_target));
>> > > > +     return 1;
>> > > > +}
>> > > > +
>> > > > +int ulwip_ping(char *ping_addr)
>> > > > +{
>> > > > +     int err;
>> > > > +
>> > > > +     err = ipaddr_aton(ping_addr, &ip_target);
>> > > > +     if (!err) {
>> > > > +             log_err("wrong ping addr string \"%s\" \n",
ping_addr);
>> > >
>> > > Invalid ip address is enough
>> > >
>> > > > +             return -1;
>> > > > +     }
>> > > > +
>> > > > +     ulwip_set_tmo(ulwip_ping_tmo);
>> > > > +
>> > > > +     ping_init(&ip_target);
>> > > > +     ping_send_now();
>> > > > +
>> > > > +     return 0;
>> > > > +}
>> > > > diff --git a/net/lwip/apps/ping/lwip_ping.h
>> > > b/net/lwip/apps/ping/lwip_ping.h
>> > > > new file mode 100644
>> > > > index 0000000000..0374f07d9e
>> > > > --- /dev/null
>> > > > +++ b/net/lwip/apps/ping/lwip_ping.h
>> > > > @@ -0,0 +1,15 @@
>> > > > +/* 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>
>> > > > +
>> > > > +void ping_raw_init(void);
>> > > > +void ping_send_now(void);
>> > > > +
>> > > > +#endif /* LWIP_PING_H */
>> > > > diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
>> > > > new file mode 100644
>> > > > index 0000000000..006a18c658
>> > > > --- /dev/null
>> > > > +++ b/net/lwip/apps/ping/ping.h
>> > > > @@ -0,0 +1,19 @@
>> > > > +/* SPDX-License-Identifier: GPL-2.0 */
>> > > > +
>> > > > +#include <net/ulwip.h>
>> > > > +#include "lwip/ip_addr.h"
>> > > > +
>> > > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
>> > > > +#define PING_RESULT(cond) { \
>> > > > +     if (cond == 1) { \
>> > > > +             printf("host %s a alive\n", ipaddr_ntoa(addr)); \
>> > > > +             printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
>> > > > +             ulwip_exit(0); \
>> > > > +     } else { \
>> > > > +             printf("ping failed; host %s in not alive\n",\
>> > > > +                    ipaddr_ntoa(addr)); \
>> > > > +             ulwip_exit(-1); \
>> > > > +     } \
>> > > > +     } while (0);
>> > >
>> > > On the previous patch you are defining a function to do something
similar
>> > > (httpc_result()).  We need to be consistent on this.  Can we define a
>> > > common function for all failures?  Certianly don't define a macro
here and
>> > > a function elsewhere
>> > >
>> >
>> > Ilias, there I reuse lwip example ping.c. It has PING_RESULT which can
be
>> > redefined by the application.
>> > This is a way to not modify this original ping.c example code.
>> > The common part of this function and httpc_result() is ulwip_exit(err)
with
>> > some additional print (print is differ).
>>
>> I'll reply on this patch, although it is a general comment.
>>
>> I would like to see if we can use the cyclic feature to allow network
>> operations to happen in the background. This would involve splitting
>> each operation into:
>>
>> - setup start and kick off, e.g. ping_sttart()
>> - checking what needs doing, e.g. ping_poll()
>> - finish and clean-up, e.g. ping_finish()
>>
>> So something like:
>>
>> ping -B 1.2.3.4
>>
>> (-B is background)
>>
>> That would fire off the packet but immediately return with a prompt.
>> When the pings are received they would show on the console, with a new
>> prompt displayed. The same for tftp -B...it would start the transfer
>> but allow other commands to be sent while it is in progress.
>>
>> Part of the reason for this is that when booting there are a lot of
>> operations which take a long time and nothing happens until everything
>> is done. For example, with standard boot, mmc devices can be shown
>> right away, but USB and network ones take a lot longer, so having OS's
>> on those devices appear later on the slower devices is desirable for
>> the user.
>>
>> Is this something that lwip can support? It is one reason why I have
>> advocating putting the state in a struct instead of having a lot of
>> separate vars.
>>
>> Regards,
>> Simon
>
>
> This functionality can be added. I do not see any restrictions
implementing that.
> Added I mean to U-Boot. lwip will definitely work with it.
>
> There is no specific poll() for application. Application just do init()
and request
> the needed packets (port, type etc, like sockets) and then common lwip
poll()
> function is called.
>
> To implement background we need to periodically call eth_rx() and
ulwip_poll() to feed lwip
> stack with rx packets when we are in the cmd shell. I see in some places
we call schedule()
> to reprogram wdt, if we call rx polling loop in the similar way the app
will work in the background.
>
> We might also want to support 2 applications at the same time. Like a
telnet server
> and ping. Multiply applications also work with lwip.
>
> Even parallel download can save some time:
> wget -B http://url1/zImage
> wget -B http//url2/dtb
> (-B = background)
>
> But I'm thinking if we can implement background  in a more generic way in
U-Boot cmd. Things like
> mount UBI fs, or download from SPI flash is slow. Or probably we can also
do some loading while
> verifying the zImage checksum.

Yes, perhaps we can keep a record of the command that is running, with a
little bit of state there. But does the stack support two wgets at once?

Regards,
Simon

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

* Re: [PATCHv6 07/14] net/lwip: implement ping cmd
  2023-08-18  3:10           ` Simon Glass
@ 2023-08-18  9:27             ` Maxim Uvarov
  2023-08-22 18:56               ` Simon Glass
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-18  9:27 UTC (permalink / raw)
  To: Simon Glass
  Cc: Ilias Apalodimas, U-Boot Mailing List, Joe Hershberger,
	Ramon Fried, Tom Rini, Simon Goldschmidt, lwip-devel,
	Peter Robinson

On Fri, 18 Aug 2023 at 09:10, Simon Glass <sjg@google.com> wrote:

> Hi Maxim,
>
> On Wed, 16 Aug 2023 at 14:15, Maxim Uvarov <maxim.uvarov@linaro.org>
> wrote:
> >
> >
> >
> > On Wed, 16 Aug 2023 at 20:39, Simon Glass <sjg@google.com> wrote:
> >>
> >> Hi Maxim,
> >>
> >> On Wed, 16 Aug 2023 at 03:09, Maxim Uvarov <maxim.uvarov@linaro.org>
> wrote:
> >> >
> >> > On Wed, 16 Aug 2023 at 14:42, Ilias Apalodimas <
> ilias.apalodimas@linaro.org>
> >> > wrote:
> >> >
> >> > > On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
> >> > > >  * can return immediately if previous request was cached or it
> might
> >> > > require
> >> > > > @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
> >> > > >  *         !0 if error
> >> > > >  */
> >> > > >  int ulwip_wget(ulong addr, char *url);
> >> > > > +
> >> > > > +/**
> >> > > > + * ulwip_tftp() - load file with tftp
> >> > > > + *
> >> > > > + * Load file with tftp to specific address
> >> > > > + *
> >> > > > + * @param addr - address to store downloaded file
> >> > > > + * @param filename - file name on remote tftp server to download
> >> > >
> >> > > Please fix function comments properly
> >> > >
> >> > > > + *
> >> > > > + *
> >> > > > + * @return 0 if success, !0 if error
> >> > > > + */
> >> > > > +int ulwip_tftp(ulong addr, const char *filename);
> >> > > > +
> >> > > > +/*
> >> > > > +* This function creates the ping for  address provided in
> parameters.
> >> > > > +* After this function you need to invoke the polling
> >> > > > +* loop to process network communication.
> >> > > > +*
> >> > > > +*
> >> > > > +* @ping_addr  start address to download result
> >> > > > +* Return: 0 for success
> >> > > > +*         !0 if error
> >> > > > +*/
> >> > > > +int ulwip_ping(char *ping_addr);
> >> > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> >> > > > index 4c6df94807..8b3e843426 100644
> >> > > > --- a/net/lwip/Makefile
> >> > > > +++ b/net/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/net/lwip/apps/ping/Makefile
> b/net/lwip/apps/ping/Makefile
> >> > > > new file mode 100644
> >> > > > index 0000000000..dc63feb7b5
> >> > > > --- /dev/null
> >> > > > +++ b/net/lwip/apps/ping/Makefile
> >> > > > @@ -0,0 +1,11 @@
> >> > > > +ccflags-y += -I$(srctree)/net/lwip/port/include
> >> > > > +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include
> >> > > -I$(srctree)/net/lwip
> >> > > > +ccflags-y += -I$(obj)
> >> > > > +
> >> > > > +.PHONY: $(obj)/ping.c
> >> > > > +$(obj)/ping.o: $(obj)/ping.c
> >> > > > +$(obj)/ping.c:
> >> > > > +     cp
> $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c
> >> > > b/net/lwip/apps/ping/lwip_ping.c
> >> > > > new file mode 100644
> >> > > > index 0000000000..611fcaf591
> >> > > > --- /dev/null
> >> > > > +++ b/net/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 "lwip_ping.h"
> >> > > > +
> >> > > > +static ip_addr_t ip_target;
> >> > > > +
> >> > > > +static int ulwip_ping_tmo(void)
> >> > > > +{
> >> > > > +
> >> > > > +     log_err("ping failed; host %s is not alive\n",
> >> > > ipaddr_ntoa(&ip_target));
> >> > > > +     return 1;
> >> > > > +}
> >> > > > +
> >> > > > +int ulwip_ping(char *ping_addr)
> >> > > > +{
> >> > > > +     int err;
> >> > > > +
> >> > > > +     err = ipaddr_aton(ping_addr, &ip_target);
> >> > > > +     if (!err) {
> >> > > > +             log_err("wrong ping addr string \"%s\" \n",
> ping_addr);
> >> > >
> >> > > Invalid ip address is enough
> >> > >
> >> > > > +             return -1;
> >> > > > +     }
> >> > > > +
> >> > > > +     ulwip_set_tmo(ulwip_ping_tmo);
> >> > > > +
> >> > > > +     ping_init(&ip_target);
> >> > > > +     ping_send_now();
> >> > > > +
> >> > > > +     return 0;
> >> > > > +}
> >> > > > diff --git a/net/lwip/apps/ping/lwip_ping.h
> >> > > b/net/lwip/apps/ping/lwip_ping.h
> >> > > > new file mode 100644
> >> > > > index 0000000000..0374f07d9e
> >> > > > --- /dev/null
> >> > > > +++ b/net/lwip/apps/ping/lwip_ping.h
> >> > > > @@ -0,0 +1,15 @@
> >> > > > +/* 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>
> >> > > > +
> >> > > > +void ping_raw_init(void);
> >> > > > +void ping_send_now(void);
> >> > > > +
> >> > > > +#endif /* LWIP_PING_H */
> >> > > > diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
> >> > > > new file mode 100644
> >> > > > index 0000000000..006a18c658
> >> > > > --- /dev/null
> >> > > > +++ b/net/lwip/apps/ping/ping.h
> >> > > > @@ -0,0 +1,19 @@
> >> > > > +/* SPDX-License-Identifier: GPL-2.0 */
> >> > > > +
> >> > > > +#include <net/ulwip.h>
> >> > > > +#include "lwip/ip_addr.h"
> >> > > > +
> >> > > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
> >> > > > +#define PING_RESULT(cond) { \
> >> > > > +     if (cond == 1) { \
> >> > > > +             printf("host %s a alive\n", ipaddr_ntoa(addr)); \
> >> > > > +             printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
> >> > > > +             ulwip_exit(0); \
> >> > > > +     } else { \
> >> > > > +             printf("ping failed; host %s in not alive\n",\
> >> > > > +                    ipaddr_ntoa(addr)); \
> >> > > > +             ulwip_exit(-1); \
> >> > > > +     } \
> >> > > > +     } while (0);
> >> > >
> >> > > On the previous patch you are defining a function to do something
> similar
> >> > > (httpc_result()).  We need to be consistent on this.  Can we define
> a
> >> > > common function for all failures?  Certianly don't define a macro
> here and
> >> > > a function elsewhere
> >> > >
> >> >
> >> > Ilias, there I reuse lwip example ping.c. It has PING_RESULT which
> can be
> >> > redefined by the application.
> >> > This is a way to not modify this original ping.c example code.
> >> > The common part of this function and httpc_result() is
> ulwip_exit(err) with
> >> > some additional print (print is differ).
> >>
> >> I'll reply on this patch, although it is a general comment.
> >>
> >> I would like to see if we can use the cyclic feature to allow network
> >> operations to happen in the background. This would involve splitting
> >> each operation into:
> >>
> >> - setup start and kick off, e.g. ping_sttart()
> >> - checking what needs doing, e.g. ping_poll()
> >> - finish and clean-up, e.g. ping_finish()
> >>
> >> So something like:
> >>
> >> ping -B 1.2.3.4
> >>
> >> (-B is background)
> >>
> >> That would fire off the packet but immediately return with a prompt.
> >> When the pings are received they would show on the console, with a new
> >> prompt displayed. The same for tftp -B...it would start the transfer
> >> but allow other commands to be sent while it is in progress.
> >>
> >> Part of the reason for this is that when booting there are a lot of
> >> operations which take a long time and nothing happens until everything
> >> is done. For example, with standard boot, mmc devices can be shown
> >> right away, but USB and network ones take a lot longer, so having OS's
> >> on those devices appear later on the slower devices is desirable for
> >> the user.
> >>
> >> Is this something that lwip can support? It is one reason why I have
> >> advocating putting the state in a struct instead of having a lot of
> >> separate vars.
> >>
> >> Regards,
> >> Simon
> >
> >
> > This functionality can be added. I do not see any restrictions
> implementing that.
> > Added I mean to U-Boot. lwip will definitely work with it.
> >
> > There is no specific poll() for application. Application just do init()
> and request
> > the needed packets (port, type etc, like sockets) and then common lwip
> poll()
> > function is called.
> >
> > To implement background we need to periodically call eth_rx() and
> ulwip_poll() to feed lwip
> > stack with rx packets when we are in the cmd shell. I see in some places
> we call schedule()
> > to reprogram wdt, if we call rx polling loop in the similar way the app
> will work in the background.
> >
> > We might also want to support 2 applications at the same time. Like a
> telnet server
> > and ping. Multiply applications also work with lwip.
> >
> > Even parallel download can save some time:
> > wget -B http://url1/zImage
> > wget -B http//url2/dtb
> > (-B = background)
> >
> > But I'm thinking if we can implement background  in a more generic way
> in U-Boot cmd. Things like
> > mount UBI fs, or download from SPI flash is slow. Or probably we can
> also do some loading while
> > verifying the zImage checksum.
>
> Yes, perhaps we can keep a record of the command that is running, with a
> little bit of state there. But does the stack support two wgets at once?
>
> Regards,
> Simon
>

Yes, it's a complete stack and it supports multiple networking applications.

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-17 15:10               ` Tom Rini
@ 2023-08-18  9:39                 ` Maxim Uvarov
  2023-08-18 11:14                   ` Peter Robinson
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-18  9:39 UTC (permalink / raw)
  To: Tom Rini
  Cc: Peter Robinson, Ilias Apalodimas, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

On Thu, 17 Aug 2023 at 21:10, Tom Rini <trini@konsulko.com> wrote:

> On Thu, Aug 17, 2023 at 08:55:17PM +0600, Maxim Uvarov wrote:
> > On Thu, 17 Aug 2023 at 20:04, Peter Robinson <pbrobinson@gmail.com>
> wrote:
> >
> > > On Thu, Aug 17, 2023 at 2:46 PM Maxim Uvarov <maxim.uvarov@linaro.org>
> > > wrote:
> > > >
> > > > On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > > On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> > > > > > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
> > > > > ilias.apalodimas@linaro.org>
> > > > > > wrote:
> > > > > >
> > > > > > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> > > > > > > > Implement function for dhcp command with lwIP variant. Usage
> and
> > > > > output
> > > > > > > is
> > > > > > > > the same as the original command. This code called by
> > > compatibility
> > > > > code
> > > > > > > > between U-Boot and lwIP.
> > > > > > >
> > > > > > > Same as the dns command
> > > > > > >
> > > > > > > >
> > > > > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > > > > > > > ---
> > > > > > > >  include/net/lwip.h             | 10 +++++++
> > > > > > > >  net/lwip/Makefile              |  1 +
> > > > > > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
> > > > > ++++++++++++++++++++++++++++++++++
> > > > > > > >  3 files changed, 62 insertions(+)
> > > > > > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> > > > > > > >
> > > > > > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> > > > > > > > index c83b5c8231..2f035280eb 100644
> > > > > > > > --- a/include/net/lwip.h
> > > > > > > > +++ b/include/net/lwip.h
> > > > > > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int
> > > flag,
> > > > > int
> > > > > > > argc,
> > > > > > > >  *         Other value < 0, if error
> > > > > > > >  */
> > > > > > > >  int ulwip_dns(char *name, char *varname);
> > > > > > > > +
> > > > > > > > +/*
> > > > > > > > +* This function creates the DHCP request to obtain IP
> address.
> > > If
> > > > > DHCP
> > > > > > > server
> > > > > > >
> > > > > > > Sphinx needs something more, please check the existing
> functions
> > > > > > >
> > > > > > > > +* returns file name, this file will be downloaded with tftp.
> > > After
> > > > > this
> > > > > > > > +* function you need to invoke the polling loop to process
> > > network
> > > > > > > communication.
> > > > > > > > +*
> > > > > > > > +* Return: 0 if success
> > > > > > > > +*         Other value < 0, if error
> > > > > > > > +*/
> > > > > > > > +int ulwip_dhcp(void);
> > > > > > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> > > > > > > > index 6d2c00605b..59323fb325 100644
> > > > > > > > --- a/net/lwip/Makefile
> > > > > > > > +
> > > > > > > > +static struct dhcp dhcp;
> > > > > > > > +
> > > > > > > > +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);
> > > > > > >
> > > > > > > What's (1)?
> > > > > > >
> > > > > > >
> > > > > > Only one lwip netif is registered. 1 - here is the index of
> netif. I
> > > > > don't
> > > > > > think that there is any definition for that...
> > > > > >
> > > > >
> > > > > And there's only ever going to be one interface (even if we have
> ipv4
> > > > > and ipv60 ? If so, define it to something please, thanks.
> > > > >
> > > > > --
> > > > > Tom
> > > > >
> > > >
> > > > Yes, one interface has 2 addresses ipv4 and ipv6.
> > >
> > > What about a device like a router which may have multiple wired
> > > ethernet interface?
> >
> > Yea, looks like we need lwip netif per U-Boots eth_devs. I did not yet
> > support several eth devices, but it will be good to add this to not break
> > existing functionality..
>
> The general case ends up being if we have more than one interface,
> ethact is what's used.  I'm unsure off-hand if some of the fancier
> networking-centric chipsets and devices have something more complex
> setup in their stacks.
>
> --
> Tom
>

Likely the bootloader uses the only one ethernet interface for loading. And
it might
be enough to have an IP stack on top of the active eth device only. This is
a model
that I am following in these patches.

BR,
Maxim.

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-18  9:39                 ` Maxim Uvarov
@ 2023-08-18 11:14                   ` Peter Robinson
  2023-08-18 14:24                     ` Tom Rini
  0 siblings, 1 reply; 49+ messages in thread
From: Peter Robinson @ 2023-08-18 11:14 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Tom Rini, Ilias Apalodimas, u-boot, pbrobinson, joe.hershberger,
	rfried.dev, goldsimon, lwip-devel

On Fri, Aug 18, 2023 at 10:39 AM Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
>
>
> On Thu, 17 Aug 2023 at 21:10, Tom Rini <trini@konsulko.com> wrote:
>>
>> On Thu, Aug 17, 2023 at 08:55:17PM +0600, Maxim Uvarov wrote:
>> > On Thu, 17 Aug 2023 at 20:04, Peter Robinson <pbrobinson@gmail.com> wrote:
>> >
>> > > On Thu, Aug 17, 2023 at 2:46 PM Maxim Uvarov <maxim.uvarov@linaro.org>
>> > > wrote:
>> > > >
>> > > > On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:
>> > > >
>> > > > > On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
>> > > > > > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
>> > > > > ilias.apalodimas@linaro.org>
>> > > > > > wrote:
>> > > > > >
>> > > > > > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
>> > > > > > > > Implement function for dhcp command with lwIP variant. Usage and
>> > > > > output
>> > > > > > > is
>> > > > > > > > the same as the original command. This code called by
>> > > compatibility
>> > > > > code
>> > > > > > > > between U-Boot and lwIP.
>> > > > > > >
>> > > > > > > Same as the dns command
>> > > > > > >
>> > > > > > > >
>> > > > > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
>> > > > > > > > ---
>> > > > > > > >  include/net/lwip.h             | 10 +++++++
>> > > > > > > >  net/lwip/Makefile              |  1 +
>> > > > > > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
>> > > > > ++++++++++++++++++++++++++++++++++
>> > > > > > > >  3 files changed, 62 insertions(+)
>> > > > > > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
>> > > > > > > >
>> > > > > > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
>> > > > > > > > index c83b5c8231..2f035280eb 100644
>> > > > > > > > --- a/include/net/lwip.h
>> > > > > > > > +++ b/include/net/lwip.h
>> > > > > > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int
>> > > flag,
>> > > > > int
>> > > > > > > argc,
>> > > > > > > >  *         Other value < 0, if error
>> > > > > > > >  */
>> > > > > > > >  int ulwip_dns(char *name, char *varname);
>> > > > > > > > +
>> > > > > > > > +/*
>> > > > > > > > +* This function creates the DHCP request to obtain IP address.
>> > > If
>> > > > > DHCP
>> > > > > > > server
>> > > > > > >
>> > > > > > > Sphinx needs something more, please check the existing functions
>> > > > > > >
>> > > > > > > > +* returns file name, this file will be downloaded with tftp.
>> > > After
>> > > > > this
>> > > > > > > > +* function you need to invoke the polling loop to process
>> > > network
>> > > > > > > communication.
>> > > > > > > > +*
>> > > > > > > > +* Return: 0 if success
>> > > > > > > > +*         Other value < 0, if error
>> > > > > > > > +*/
>> > > > > > > > +int ulwip_dhcp(void);
>> > > > > > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
>> > > > > > > > index 6d2c00605b..59323fb325 100644
>> > > > > > > > --- a/net/lwip/Makefile
>> > > > > > > > +
>> > > > > > > > +static struct dhcp dhcp;
>> > > > > > > > +
>> > > > > > > > +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);
>> > > > > > >
>> > > > > > > What's (1)?
>> > > > > > >
>> > > > > > >
>> > > > > > Only one lwip netif is registered. 1 - here is the index of netif. I
>> > > > > don't
>> > > > > > think that there is any definition for that...
>> > > > > >
>> > > > >
>> > > > > And there's only ever going to be one interface (even if we have ipv4
>> > > > > and ipv60 ? If so, define it to something please, thanks.
>> > > > >
>> > > > > --
>> > > > > Tom
>> > > > >
>> > > >
>> > > > Yes, one interface has 2 addresses ipv4 and ipv6.
>> > >
>> > > What about a device like a router which may have multiple wired
>> > > ethernet interface?
>> >
>> > Yea, looks like we need lwip netif per U-Boots eth_devs. I did not yet
>> > support several eth devices, but it will be good to add this to not break
>> > existing functionality..
>>
>> The general case ends up being if we have more than one interface,
>> ethact is what's used.  I'm unsure off-hand if some of the fancier
>> networking-centric chipsets and devices have something more complex
>> setup in their stacks.
>>
>> --
>> Tom
>
>
> Likely the bootloader uses the only one ethernet interface for loading. And it might
> be enough to have an IP stack on top of the active eth device only. This is a model
> that I am following in these patches.

It's possible, yes, that there may only be one active device, but you
still will need to be able to handle all of them to at least work out
which one has a link that you can bring up to get an IP. There's a
bunch of devices that will have two interfaces with the same NIC
driver, plus also there's at least a few devices that have an onboard
switch (MV88E6XXX) although grep only shows a single one upstream.

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

* Re: [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot
  2023-08-16  9:01   ` Ilias Apalodimas
@ 2023-08-18 12:53     ` Maxim Uvarov
  2023-08-18 18:21       ` Simon Goldschmidt
  0 siblings, 1 reply; 49+ messages in thread
From: Maxim Uvarov @ 2023-08-18 12:53 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini,
	goldsimon, lwip-devel

On Wed, 16 Aug 2023 at 15:01, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> On Mon, Aug 14, 2023 at 07:32:48PM +0600, Maxim Uvarov wrote:
> > Implement network lwIP interface connected to the U-boot.
> > Keep original file structure widely used fro lwIP ports.
> > (i.e. port/if.c port/sys-arch.c).
>
> What the patch does is obvious.  Try to describe *why* we need this
>
> >
> > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> > ---
> >  net/eth-uclass.c                      |   8 +
> >  net/lwip/port/if.c                    | 260 ++++++++++++++++++++++++++
> >  net/lwip/port/include/arch/cc.h       |  39 ++++
> >  net/lwip/port/include/arch/sys_arch.h |  56 ++++++
> >  net/lwip/port/include/limits.h        |   0
> >  net/lwip/port/sys-arch.c              |  20 ++
> >  6 files changed, 383 insertions(+)
> >  create mode 100644 net/lwip/port/if.c
> >  create mode 100644 net/lwip/port/include/arch/cc.h
> >  create mode 100644 net/lwip/port/include/arch/sys_arch.h
> >  create mode 100644 net/lwip/port/include/limits.h
> >  create mode 100644 net/lwip/port/sys-arch.c
> >
> > diff --git a/net/eth-uclass.c b/net/eth-uclass.c
> > index c393600fab..6625f6d8a5 100644
> > --- a/net/eth-uclass.c
> > +++ b/net/eth-uclass.c
> > @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
> >  struct eth_device_priv {
> >       enum eth_state_t state;
> >       bool running;
> > +     ulwip ulwip;
> >  };
> >
> >  /**
> > @@ -347,6 +348,13 @@ int eth_init(void)
> >       return ret;
> >  }
> >
> > +struct ulwip *eth_lwip_priv(struct udevice *current)
> > +{
> > +     struct eth_device_priv *priv = dev_get_uclass_priv(current);
> > +
> > +     return &priv->ulwip;
> > +}
> > +
> >  void eth_halt(void)
> >  {
> >       struct udevice *current;
> > diff --git a/net/lwip/port/if.c b/net/lwip/port/if.c
> > new file mode 100644
> > index 0000000000..625a9c10bf
> > --- /dev/null
> > +++ b/net/lwip/port/if.c
> > @@ -0,0 +1,260 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +/*
> > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
> > + */
> > +
> > +#include <common.h>
> > +#include <command.h>
> > +#include <net/eth.h>
> > +#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/ethip6.h"
> > +
> > +#include "lwip/ip.h"
> > +
> > +#define IFNAME0 'e'
> > +#define IFNAME1 '0'
>
> Why is this needed and how was 'e0' chosen?
> Dont we have a device name in the udevice struct?
>
>
If we assume that we have lwip netif on top of an active U-Boot eth device,
then it can be any name.

  /** descriptive abbreviation */

  char name[2];

./net/lwip/lwip-external/contrib/examples/ethernetif/ethernetif.c:#define
IFNAME0 'e'
./net/lwip/lwip-external/contrib/examples/ethernetif/ethernetif.c:#define
IFNAME1 'n'
./net/lwip/lwip-external/contrib/ports/unix/port/netif/tapif.c:#define
IFNAME0 't'
./net/lwip/lwip-external/contrib/ports/unix/port/netif/tapif.c:#define
IFNAME1 'p'
./net/lwip/lwip-external/contrib/ports/unix/port/netif/vdeif.c:#define
IFNAME0 'v'
./net/lwip/lwip-external/contrib/ports/unix/port/netif/vdeif.c:#define
IFNAME1 'd'
./net/lwip/lwip-external/contrib/ports/win32/pcapif.c:#define IFNAME0
                'e'
./net/lwip/lwip-external/contrib/ports/win32/pcapif.c:#define IFNAME1
                '0'
./net/lwip/lwip-external/src/netif/bridgeif.c:#define IFNAME0 'b'
./net/lwip/lwip-external/src/netif/bridgeif.c:#define IFNAME1 'r'
./net/lwip/port/if.c:#define IFNAME0 'u'
./net/lwip/port/if.c:#define IFNAME1 '0'



> > +
> > +static struct pbuf *low_level_input(struct netif *netif);
> > +
> > +int ulwip_enabled(void)
> > +{
> > +     struct ulwip *ulwip;
> > +
> > +     ulwip = eth_lwip_priv(eth_get_dev());
>
> eth_get_dev() can return NULL.  There are various locations of this call
> that needs fixing
>


ok.


>
> > +     return ulwip->init_done;
> > +}
> > +
> > +
> > +struct ulwip_if {
> > +};
>
> Why the forward declaration?
>
> > +
> > +#define LWIP_PORT_INIT_NETMASK(addr)  IP4_ADDR((addr), 255, 255, 255, 0)
>
> Why are we limiting the netmask to a class C network?
>
>
that can be completely removed.


> > +
> > +void ulwip_poll(void)
> > +{
> > +     struct pbuf *p;
> > +     int err;
> > +     struct netif *netif = netif_get_by_index(1);
>
> First of all netif can be NULL. Apart from that always requesting index 1
> feels wrong.  We should do something similar to eth_get_dev() and get the
> *active* device correlation to an index
>
>
I expect that it will be 1 lwip netif for all eth defs. And only active eth
dev works with lwip.
This can be reconsidered but might be not a part of the initial patch set.


> > +
> > +     p = low_level_input(netif);
> > +     if (!p) {
> > +             log_err("error p = low_level_input = NULL\n");
>
> This looks like a debug message.
> 'Network interface undefined' or something else, which is more readable.
>
> > +             return;
> > +     }
> > +
> > +     /* ethernet_input always returns ERR_OK */
> > +     err = ethernet_input(p, netif);
> > +     if (err)
> > +             log_err("ip4_input err %d\n", err);
> > +
> > +     return;
> > +}
> > +
> > +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;
> > +
> > +     /* We allocate a pbuf chain of pbufs from the pool. */
> > +     p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
> > +     if (p) {
>
> if (!p) and reverse the logic
>
> > +             /* 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();
> > +
> > +             LINK_STATS_INC(link.recv);
> > +     } else {
> > +             // drop packet();
>
> Is this a commented function that's missing?
>
>
it's a comment.  That means lwip does now own this packet and actual drop
will be by U-Boot eth dev.
I will remove this comment to not confuse anybody.


> > +             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) {
> > +             log_err("eth_send error %d\n", err);
> > +             return ERR_ABRT;
> > +     }
> > +     return ERR_OK;
> > +}
> > +
> > +err_t ulwip_if_init(struct netif *netif)
> > +{
> > +     struct ulwip_if *uif;
> > +     struct ulwip *ulwip;
> > +
> > +     uif = malloc(sizeof(struct ulwip_if));
> > +     if (!uif) {
> > +             log_err("uif: 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);
>
> What if ethaddr is not set?
>
>
U-Boot set's it automatically. I think it will generate random one. But
even if somehow it will not set
string_to_enetaddr()  function just will do nothing.



> > +#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
> > +#if LWIP_IPV6
> > +     netif->output_ip6 = ethip6_output;
> > +#endif
> > +
> > +     netif->linkoutput = low_level_output;
> > +     netif->mtu = 1500;
> > +     netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
> NETIF_FLAG_LINK_UP;
> > +
> > +     ulwip = eth_lwip_priv(eth_get_dev());
> > +     ulwip->init_done = 1;
> > +     if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
> > +             log_info("Initialized LWIP stack\n");
> > +     }
> > +
> > +     return ERR_OK;
> > +}
> > +
> > +int ulwip_init(void)
> > +{
> > +     ip4_addr_t ipaddr, netmask, gw;
> > +     struct netif *unetif;
> > +     struct ulwip *ulwip;
> > +     int ret;
> > +
> > +     ret = eth_init();
> > +     if (ret) {
> > +             log_err("eth_init error %d\n", ret);
> > +             return ERR_IF;
> > +     }
> > +
> > +     ulwip = eth_lwip_priv(eth_get_dev());
> > +     if (ulwip->init_done)
> > +             return CMD_RET_SUCCESS;
> > +
> > +     unetif = malloc(sizeof(struct netif));
> > +     if (!unetif)
> > +             return ERR_MEM;
> > +     memset(unetif, 0, sizeof(struct netif));
> > +
> > +     ip4_addr_set_zero(&gw);
> > +     ip4_addr_set_zero(&ipaddr);
> > +     ip4_addr_set_zero(&netmask);
> > +
> > +     ipaddr_aton(env_get("ipaddr"), &ipaddr);
> > +     ipaddr_aton(env_get("ipaddr"), &netmask);
>

Here I missed "netmask" for &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));
>
> log_info()
>
> > +     }
> > +
> > +     if (!netif_add(unetif, &ipaddr, &netmask, &gw,
> > +                    unetif, ulwip_if_init, ethernetif_input))
> > +             printf("err: netif_add failed!\n");
> > +
> > +     netif_set_up(unetif);
> > +     netif_set_link_up(unetif);
> > +#if LWIP_IPV6
> > +     netif_create_ip6_linklocal_address(unetif, 1);
> > +     printf("             IPv6: %s\n",
> ip6addr_ntoa(netif_ip6_addr(unetif, 0)));
> > +#endif /* LWIP_IPV6 */
> > +
> > +     return CMD_RET_SUCCESS;
> > +}
> > +
> > +/* placeholder, not used now */
> > +void ulwip_destroy(void)
> > +{
> > +}
> > diff --git a/net/lwip/port/include/arch/cc.h
> b/net/lwip/port/include/arch/cc.h
> > new file mode 100644
> > index 0000000000..55f7787ce1
> > --- /dev/null
> > +++ b/net/lwip/port/include/arch/cc.h
> > @@ -0,0 +1,39 @@
> > +/* 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>
> > +//#include <stdlib.h>    /* getenv, atoi */
>
> Please dont leave comments like that
>
> > +#include <vsprintf.h>
> > +
> > +#define LWIP_ERRNO_INCLUDE <errno.h>
> > +
> > +#define LWIP_ERRNO_STDINCLUDE        1
> > +#define LWIP_NO_UNISTD_H 1
> > +#define LWIP_TIMEVAL_PRIVATE 1
>
> Should those be defined in the LWIP config header instead?
>
> I would keep it here, like
./net/lwip/lwip-external/contrib/ports/unix/port/include/arch/cc.h does.
Because LWIP config is more related to protocol features and settings and
this header is about
porr for a specific platform.



> > +
> > +extern unsigned int lwip_port_rand(void);
>
> This is like the forth time we go through this and it's a repeating
> pattern.  Why do we need this extern? Can't we just include the proper
> header files?
>
> > +#define LWIP_RAND() (lwip_port_rand())
>
> This seems quite useless. Just use the function directly
>
>
somehow I missed  this, this should be direct call:
#include <rand.h>
#define LWIP_RAND() ((u32_t)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)
> > +
> > +#define atoi(str) (int)dectoul(str, NULL)
> > +
> > +#define LWIP_ERR_T int
> > +
> > +#endif /* LWIP_ARCH_CC_H */
> > diff --git a/net/lwip/port/include/arch/sys_arch.h
> b/net/lwip/port/include/arch/sys_arch.h
> > new file mode 100644
> > index 0000000000..92a8560d49
> > --- /dev/null
> > +++ b/net/lwip/port/include/arch/sys_arch.h
> > @@ -0,0 +1,56 @@
> > +/* 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)
>
> Dont redefine random functions here.  U-Boot should already have all the
> sleep functions you need
>
>
dropeed.


> > +
> > +#if SYS_LIGHTWEIGHT_PROT
>
> Is this working? Can we define SYS_LIGHTWEIGHT_PROT?
>
> dropeed.


> > +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;
> > +
> > +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)
>
> All these macros seem unnecessary.  Just assign types to NULL directly etc
>
>
ok.


> > +
> > +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;
> > +};
>
> Are those really needed?  Why do we just return 0?
>
> Not needed,  I think I planned to implement socket API later where it's
needed. All these functions and macro can be defined to NULL with #define
NO_SYS  1 in the lwip configuration.
This has to be an empty file.


> > +
> > +#endif /* LWIP_ARCH_SYS_ARCH_H */
> > diff --git a/net/lwip/port/include/limits.h
> b/net/lwip/port/include/limits.h
> > new file mode 100644
> > index 0000000000..e69de29bb2
> > diff --git a/net/lwip/port/sys-arch.c b/net/lwip/port/sys-arch.c
> > new file mode 100644
> > index 0000000000..609eeccf8c
> > --- /dev/null
> > +++ b/net/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();
>
> I dont see why we cant use the U-Boot defined ones directly
>
>
changed.


> > +}
> > +
> > --
> > 2.30.2
> >
>
> Thanks
> /Ilias
>

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

* Re: [PATCHv6 04/14] net/lwip: implement dhcp cmd
  2023-08-18 11:14                   ` Peter Robinson
@ 2023-08-18 14:24                     ` Tom Rini
  0 siblings, 0 replies; 49+ messages in thread
From: Tom Rini @ 2023-08-18 14:24 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Peter Robinson, Ilias Apalodimas, u-boot, pbrobinson,
	joe.hershberger, rfried.dev, goldsimon, lwip-devel

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

On Fri, Aug 18, 2023 at 12:14:11PM +0100, Peter Robinson wrote:
> On Fri, Aug 18, 2023 at 10:39 AM Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
> >
> >
> >
> > On Thu, 17 Aug 2023 at 21:10, Tom Rini <trini@konsulko.com> wrote:
> >>
> >> On Thu, Aug 17, 2023 at 08:55:17PM +0600, Maxim Uvarov wrote:
> >> > On Thu, 17 Aug 2023 at 20:04, Peter Robinson <pbrobinson@gmail.com> wrote:
> >> >
> >> > > On Thu, Aug 17, 2023 at 2:46 PM Maxim Uvarov <maxim.uvarov@linaro.org>
> >> > > wrote:
> >> > > >
> >> > > > On Mon, 14 Aug 2023 at 21:29, Tom Rini <trini@konsulko.com> wrote:
> >> > > >
> >> > > > > On Mon, Aug 14, 2023 at 09:18:19PM +0600, Maxim Uvarov wrote:
> >> > > > > > On Mon, 14 Aug 2023 at 20:21, Ilias Apalodimas <
> >> > > > > ilias.apalodimas@linaro.org>
> >> > > > > > wrote:
> >> > > > > >
> >> > > > > > > On Mon, Aug 14, 2023 at 07:32:43PM +0600, Maxim Uvarov wrote:
> >> > > > > > > > Implement function for dhcp command with lwIP variant. Usage and
> >> > > > > output
> >> > > > > > > is
> >> > > > > > > > the same as the original command. This code called by
> >> > > compatibility
> >> > > > > code
> >> > > > > > > > between U-Boot and lwIP.
> >> > > > > > >
> >> > > > > > > Same as the dns command
> >> > > > > > >
> >> > > > > > > >
> >> > > > > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
> >> > > > > > > > ---
> >> > > > > > > >  include/net/lwip.h             | 10 +++++++
> >> > > > > > > >  net/lwip/Makefile              |  1 +
> >> > > > > > > >  net/lwip/apps/dhcp/lwip-dhcp.c | 51
> >> > > > > ++++++++++++++++++++++++++++++++++
> >> > > > > > > >  3 files changed, 62 insertions(+)
> >> > > > > > > >  create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
> >> > > > > > > >
> >> > > > > > > > diff --git a/include/net/lwip.h b/include/net/lwip.h
> >> > > > > > > > index c83b5c8231..2f035280eb 100644
> >> > > > > > > > --- a/include/net/lwip.h
> >> > > > > > > > +++ b/include/net/lwip.h
> >> > > > > > > > @@ -15,3 +15,13 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int
> >> > > flag,
> >> > > > > int
> >> > > > > > > argc,
> >> > > > > > > >  *         Other value < 0, if error
> >> > > > > > > >  */
> >> > > > > > > >  int ulwip_dns(char *name, char *varname);
> >> > > > > > > > +
> >> > > > > > > > +/*
> >> > > > > > > > +* This function creates the DHCP request to obtain IP address.
> >> > > If
> >> > > > > DHCP
> >> > > > > > > server
> >> > > > > > >
> >> > > > > > > Sphinx needs something more, please check the existing functions
> >> > > > > > >
> >> > > > > > > > +* returns file name, this file will be downloaded with tftp.
> >> > > After
> >> > > > > this
> >> > > > > > > > +* function you need to invoke the polling loop to process
> >> > > network
> >> > > > > > > communication.
> >> > > > > > > > +*
> >> > > > > > > > +* Return: 0 if success
> >> > > > > > > > +*         Other value < 0, if error
> >> > > > > > > > +*/
> >> > > > > > > > +int ulwip_dhcp(void);
> >> > > > > > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
> >> > > > > > > > index 6d2c00605b..59323fb325 100644
> >> > > > > > > > --- a/net/lwip/Makefile
> >> > > > > > > > +
> >> > > > > > > > +static struct dhcp dhcp;
> >> > > > > > > > +
> >> > > > > > > > +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);
> >> > > > > > >
> >> > > > > > > What's (1)?
> >> > > > > > >
> >> > > > > > >
> >> > > > > > Only one lwip netif is registered. 1 - here is the index of netif. I
> >> > > > > don't
> >> > > > > > think that there is any definition for that...
> >> > > > > >
> >> > > > >
> >> > > > > And there's only ever going to be one interface (even if we have ipv4
> >> > > > > and ipv60 ? If so, define it to something please, thanks.
> >> > > > >
> >> > > > > --
> >> > > > > Tom
> >> > > > >
> >> > > >
> >> > > > Yes, one interface has 2 addresses ipv4 and ipv6.
> >> > >
> >> > > What about a device like a router which may have multiple wired
> >> > > ethernet interface?
> >> >
> >> > Yea, looks like we need lwip netif per U-Boots eth_devs. I did not yet
> >> > support several eth devices, but it will be good to add this to not break
> >> > existing functionality..
> >>
> >> The general case ends up being if we have more than one interface,
> >> ethact is what's used.  I'm unsure off-hand if some of the fancier
> >> networking-centric chipsets and devices have something more complex
> >> setup in their stacks.
> >>
> >> --
> >> Tom
> >
> >
> > Likely the bootloader uses the only one ethernet interface for loading. And it might
> > be enough to have an IP stack on top of the active eth device only. This is a model
> > that I am following in these patches.
> 
> It's possible, yes, that there may only be one active device, but you
> still will need to be able to handle all of them to at least work out
> which one has a link that you can bring up to get an IP. There's a
> bunch of devices that will have two interfaces with the same NIC
> driver, plus also there's at least a few devices that have an onboard
> switch (MV88E6XXX) although grep only shows a single one upstream.

Right.  You can even simulate this on some other devices via the gadget
ethernet driver.  In other words, please make sure we don't forget to
use "ethact" (see net/eth-uclass.c and net/eth_common.c).

-- 
Tom

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

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

* Re: [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot
  2023-08-18 12:53     ` Maxim Uvarov
@ 2023-08-18 18:21       ` Simon Goldschmidt
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Goldschmidt @ 2023-08-18 18:21 UTC (permalink / raw)
  To: Maxim Uvarov, Ilias Apalodimas
  Cc: u-boot, pbrobinson, joe.hershberger, rfried.dev, trini

Hi all,

could you please remove the lwip-devel list from CC? I am interested in these mails, but the more you dive into U-Boot specific things here, the less people on our lwip list will be interested in this topic.

Thanks,
Simon


Am 18. August 2023 14:53:43 MESZ schrieb Maxim Uvarov <maxim.uvarov@linaro.org>:
>On Wed, 16 Aug 2023 at 15:01, Ilias Apalodimas <ilias.apalodimas@linaro.org>
>wrote:
>
>> On Mon, Aug 14, 2023 at 07:32:48PM +0600, Maxim Uvarov wrote:
>> > Implement network lwIP interface connected to the U-boot.
>> > Keep original file structure widely used fro lwIP ports.
>> > (i.e. port/if.c port/sys-arch.c).
>>
>> What the patch does is obvious.  Try to describe *why* we need this
>>
>> >
>> > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
>> > ---
>> >  net/eth-uclass.c                      |   8 +
>> >  net/lwip/port/if.c                    | 260 ++++++++++++++++++++++++++
>> >  net/lwip/port/include/arch/cc.h       |  39 ++++
>> >  net/lwip/port/include/arch/sys_arch.h |  56 ++++++
>> >  net/lwip/port/include/limits.h        |   0
>> >  net/lwip/port/sys-arch.c              |  20 ++
>> >  6 files changed, 383 insertions(+)
>> >  create mode 100644 net/lwip/port/if.c
>> >  create mode 100644 net/lwip/port/include/arch/cc.h
>> >  create mode 100644 net/lwip/port/include/arch/sys_arch.h
>> >  create mode 100644 net/lwip/port/include/limits.h
>> >  create mode 100644 net/lwip/port/sys-arch.c
>> >
>> > diff --git a/net/eth-uclass.c b/net/eth-uclass.c
>> > index c393600fab..6625f6d8a5 100644
>> > --- a/net/eth-uclass.c
>> > +++ b/net/eth-uclass.c
>> > @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
>> >  struct eth_device_priv {
>> >       enum eth_state_t state;
>> >       bool running;
>> > +     ulwip ulwip;
>> >  };
>> >
>> >  /**
>> > @@ -347,6 +348,13 @@ int eth_init(void)
>> >       return ret;
>> >  }
>> >
>> > +struct ulwip *eth_lwip_priv(struct udevice *current)
>> > +{
>> > +     struct eth_device_priv *priv = dev_get_uclass_priv(current);
>> > +
>> > +     return &priv->ulwip;
>> > +}
>> > +
>> >  void eth_halt(void)
>> >  {
>> >       struct udevice *current;
>> > diff --git a/net/lwip/port/if.c b/net/lwip/port/if.c
>> > new file mode 100644
>> > index 0000000000..625a9c10bf
>> > --- /dev/null
>> > +++ b/net/lwip/port/if.c
>> > @@ -0,0 +1,260 @@
>> > +// SPDX-License-Identifier: GPL-2.0
>> > +
>> > +/*
>> > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
>> > + */
>> > +
>> > +#include <common.h>
>> > +#include <command.h>
>> > +#include <net/eth.h>
>> > +#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/ethip6.h"
>> > +
>> > +#include "lwip/ip.h"
>> > +
>> > +#define IFNAME0 'e'
>> > +#define IFNAME1 '0'
>>
>> Why is this needed and how was 'e0' chosen?
>> Dont we have a device name in the udevice struct?
>>
>>
>If we assume that we have lwip netif on top of an active U-Boot eth device,
>then it can be any name.
>
>  /** descriptive abbreviation */
>
>  char name[2];
>
>./net/lwip/lwip-external/contrib/examples/ethernetif/ethernetif.c:#define
>IFNAME0 'e'
>./net/lwip/lwip-external/contrib/examples/ethernetif/ethernetif.c:#define
>IFNAME1 'n'
>./net/lwip/lwip-external/contrib/ports/unix/port/netif/tapif.c:#define
>IFNAME0 't'
>./net/lwip/lwip-external/contrib/ports/unix/port/netif/tapif.c:#define
>IFNAME1 'p'
>./net/lwip/lwip-external/contrib/ports/unix/port/netif/vdeif.c:#define
>IFNAME0 'v'
>./net/lwip/lwip-external/contrib/ports/unix/port/netif/vdeif.c:#define
>IFNAME1 'd'
>./net/lwip/lwip-external/contrib/ports/win32/pcapif.c:#define IFNAME0
>                'e'
>./net/lwip/lwip-external/contrib/ports/win32/pcapif.c:#define IFNAME1
>                '0'
>./net/lwip/lwip-external/src/netif/bridgeif.c:#define IFNAME0 'b'
>./net/lwip/lwip-external/src/netif/bridgeif.c:#define IFNAME1 'r'
>./net/lwip/port/if.c:#define IFNAME0 'u'
>./net/lwip/port/if.c:#define IFNAME1 '0'
>
>
>
>> > +
>> > +static struct pbuf *low_level_input(struct netif *netif);
>> > +
>> > +int ulwip_enabled(void)
>> > +{
>> > +     struct ulwip *ulwip;
>> > +
>> > +     ulwip = eth_lwip_priv(eth_get_dev());
>>
>> eth_get_dev() can return NULL.  There are various locations of this call
>> that needs fixing
>>
>
>
>ok.
>
>
>>
>> > +     return ulwip->init_done;
>> > +}
>> > +
>> > +
>> > +struct ulwip_if {
>> > +};
>>
>> Why the forward declaration?
>>
>> > +
>> > +#define LWIP_PORT_INIT_NETMASK(addr)  IP4_ADDR((addr), 255, 255, 255, 0)
>>
>> Why are we limiting the netmask to a class C network?
>>
>>
>that can be completely removed.
>
>
>> > +
>> > +void ulwip_poll(void)
>> > +{
>> > +     struct pbuf *p;
>> > +     int err;
>> > +     struct netif *netif = netif_get_by_index(1);
>>
>> First of all netif can be NULL. Apart from that always requesting index 1
>> feels wrong.  We should do something similar to eth_get_dev() and get the
>> *active* device correlation to an index
>>
>>
>I expect that it will be 1 lwip netif for all eth defs. And only active eth
>dev works with lwip.
>This can be reconsidered but might be not a part of the initial patch set.
>
>
>> > +
>> > +     p = low_level_input(netif);
>> > +     if (!p) {
>> > +             log_err("error p = low_level_input = NULL\n");
>>
>> This looks like a debug message.
>> 'Network interface undefined' or something else, which is more readable.
>>
>> > +             return;
>> > +     }
>> > +
>> > +     /* ethernet_input always returns ERR_OK */
>> > +     err = ethernet_input(p, netif);
>> > +     if (err)
>> > +             log_err("ip4_input err %d\n", err);
>> > +
>> > +     return;
>> > +}
>> > +
>> > +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;
>> > +
>> > +     /* We allocate a pbuf chain of pbufs from the pool. */
>> > +     p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
>> > +     if (p) {
>>
>> if (!p) and reverse the logic
>>
>> > +             /* 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();
>> > +
>> > +             LINK_STATS_INC(link.recv);
>> > +     } else {
>> > +             // drop packet();
>>
>> Is this a commented function that's missing?
>>
>>
>it's a comment.  That means lwip does now own this packet and actual drop
>will be by U-Boot eth dev.
>I will remove this comment to not confuse anybody.
>
>
>> > +             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) {
>> > +             log_err("eth_send error %d\n", err);
>> > +             return ERR_ABRT;
>> > +     }
>> > +     return ERR_OK;
>> > +}
>> > +
>> > +err_t ulwip_if_init(struct netif *netif)
>> > +{
>> > +     struct ulwip_if *uif;
>> > +     struct ulwip *ulwip;
>> > +
>> > +     uif = malloc(sizeof(struct ulwip_if));
>> > +     if (!uif) {
>> > +             log_err("uif: 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);
>>
>> What if ethaddr is not set?
>>
>>
>U-Boot set's it automatically. I think it will generate random one. But
>even if somehow it will not set
>string_to_enetaddr()  function just will do nothing.
>
>
>
>> > +#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
>> > +#if LWIP_IPV6
>> > +     netif->output_ip6 = ethip6_output;
>> > +#endif
>> > +
>> > +     netif->linkoutput = low_level_output;
>> > +     netif->mtu = 1500;
>> > +     netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
>> NETIF_FLAG_LINK_UP;
>> > +
>> > +     ulwip = eth_lwip_priv(eth_get_dev());
>> > +     ulwip->init_done = 1;
>> > +     if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
>> > +             log_info("Initialized LWIP stack\n");
>> > +     }
>> > +
>> > +     return ERR_OK;
>> > +}
>> > +
>> > +int ulwip_init(void)
>> > +{
>> > +     ip4_addr_t ipaddr, netmask, gw;
>> > +     struct netif *unetif;
>> > +     struct ulwip *ulwip;
>> > +     int ret;
>> > +
>> > +     ret = eth_init();
>> > +     if (ret) {
>> > +             log_err("eth_init error %d\n", ret);
>> > +             return ERR_IF;
>> > +     }
>> > +
>> > +     ulwip = eth_lwip_priv(eth_get_dev());
>> > +     if (ulwip->init_done)
>> > +             return CMD_RET_SUCCESS;
>> > +
>> > +     unetif = malloc(sizeof(struct netif));
>> > +     if (!unetif)
>> > +             return ERR_MEM;
>> > +     memset(unetif, 0, sizeof(struct netif));
>> > +
>> > +     ip4_addr_set_zero(&gw);
>> > +     ip4_addr_set_zero(&ipaddr);
>> > +     ip4_addr_set_zero(&netmask);
>> > +
>> > +     ipaddr_aton(env_get("ipaddr"), &ipaddr);
>> > +     ipaddr_aton(env_get("ipaddr"), &netmask);
>>
>
>Here I missed "netmask" for &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));
>>
>> log_info()
>>
>> > +     }
>> > +
>> > +     if (!netif_add(unetif, &ipaddr, &netmask, &gw,
>> > +                    unetif, ulwip_if_init, ethernetif_input))
>> > +             printf("err: netif_add failed!\n");
>> > +
>> > +     netif_set_up(unetif);
>> > +     netif_set_link_up(unetif);
>> > +#if LWIP_IPV6
>> > +     netif_create_ip6_linklocal_address(unetif, 1);
>> > +     printf("             IPv6: %s\n",
>> ip6addr_ntoa(netif_ip6_addr(unetif, 0)));
>> > +#endif /* LWIP_IPV6 */
>> > +
>> > +     return CMD_RET_SUCCESS;
>> > +}
>> > +
>> > +/* placeholder, not used now */
>> > +void ulwip_destroy(void)
>> > +{
>> > +}
>> > diff --git a/net/lwip/port/include/arch/cc.h
>> b/net/lwip/port/include/arch/cc.h
>> > new file mode 100644
>> > index 0000000000..55f7787ce1
>> > --- /dev/null
>> > +++ b/net/lwip/port/include/arch/cc.h
>> > @@ -0,0 +1,39 @@
>> > +/* 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>
>> > +//#include <stdlib.h>    /* getenv, atoi */
>>
>> Please dont leave comments like that
>>
>> > +#include <vsprintf.h>
>> > +
>> > +#define LWIP_ERRNO_INCLUDE <errno.h>
>> > +
>> > +#define LWIP_ERRNO_STDINCLUDE        1
>> > +#define LWIP_NO_UNISTD_H 1
>> > +#define LWIP_TIMEVAL_PRIVATE 1
>>
>> Should those be defined in the LWIP config header instead?
>>
>> I would keep it here, like
>./net/lwip/lwip-external/contrib/ports/unix/port/include/arch/cc.h does.
>Because LWIP config is more related to protocol features and settings and
>this header is about
>porr for a specific platform.
>
>
>
>> > +
>> > +extern unsigned int lwip_port_rand(void);
>>
>> This is like the forth time we go through this and it's a repeating
>> pattern.  Why do we need this extern? Can't we just include the proper
>> header files?
>>
>> > +#define LWIP_RAND() (lwip_port_rand())
>>
>> This seems quite useless. Just use the function directly
>>
>>
>somehow I missed  this, this should be direct call:
>#include <rand.h>
>#define LWIP_RAND() ((u32_t)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)
>> > +
>> > +#define atoi(str) (int)dectoul(str, NULL)
>> > +
>> > +#define LWIP_ERR_T int
>> > +
>> > +#endif /* LWIP_ARCH_CC_H */
>> > diff --git a/net/lwip/port/include/arch/sys_arch.h
>> b/net/lwip/port/include/arch/sys_arch.h
>> > new file mode 100644
>> > index 0000000000..92a8560d49
>> > --- /dev/null
>> > +++ b/net/lwip/port/include/arch/sys_arch.h
>> > @@ -0,0 +1,56 @@
>> > +/* 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)
>>
>> Dont redefine random functions here.  U-Boot should already have all the
>> sleep functions you need
>>
>>
>dropeed.
>
>
>> > +
>> > +#if SYS_LIGHTWEIGHT_PROT
>>
>> Is this working? Can we define SYS_LIGHTWEIGHT_PROT?
>>
>> dropeed.
>
>
>> > +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;
>> > +
>> > +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)
>>
>> All these macros seem unnecessary.  Just assign types to NULL directly etc
>>
>>
>ok.
>
>
>> > +
>> > +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;
>> > +};
>>
>> Are those really needed?  Why do we just return 0?
>>
>> Not needed,  I think I planned to implement socket API later where it's
>needed. All these functions and macro can be defined to NULL with #define
>NO_SYS  1 in the lwip configuration.
>This has to be an empty file.
>
>
>> > +
>> > +#endif /* LWIP_ARCH_SYS_ARCH_H */
>> > diff --git a/net/lwip/port/include/limits.h
>> b/net/lwip/port/include/limits.h
>> > new file mode 100644
>> > index 0000000000..e69de29bb2
>> > diff --git a/net/lwip/port/sys-arch.c b/net/lwip/port/sys-arch.c
>> > new file mode 100644
>> > index 0000000000..609eeccf8c
>> > --- /dev/null
>> > +++ b/net/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();
>>
>> I dont see why we cant use the U-Boot defined ones directly
>>
>>
>changed.
>
>
>> > +}
>> > +
>> > --
>> > 2.30.2
>> >
>>
>> Thanks
>> /Ilias
>>

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

* Re: [PATCHv6 07/14] net/lwip: implement ping cmd
  2023-08-18  9:27             ` Maxim Uvarov
@ 2023-08-22 18:56               ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2023-08-22 18:56 UTC (permalink / raw)
  To: Maxim Uvarov
  Cc: Ilias Apalodimas, U-Boot Mailing List, Joe Hershberger,
	Ramon Fried, Tom Rini, Simon Goldschmidt, lwip-devel,
	Peter Robinson

Hi Maxim,

On Fri, 18 Aug 2023 at 03:27, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
>
>
> On Fri, 18 Aug 2023 at 09:10, Simon Glass <sjg@google.com> wrote:
>>
>> Hi Maxim,
>>
>> On Wed, 16 Aug 2023 at 14:15, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>> >
>> >
>> >
>> > On Wed, 16 Aug 2023 at 20:39, Simon Glass <sjg@google.com> wrote:
>> >>
>> >> Hi Maxim,
>> >>
>> >> On Wed, 16 Aug 2023 at 03:09, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>> >> >
>> >> > On Wed, 16 Aug 2023 at 14:42, Ilias Apalodimas <ilias.apalodimas@linaro.org>
>> >> > wrote:
>> >> >
>> >> > > On Mon, Aug 14, 2023 at 07:32:46PM +0600, Maxim Uvarov wrote:
>> >> > > >  * can return immediately if previous request was cached or it might
>> >> > > require
>> >> > > > @@ -38,3 +39,28 @@ int ulwip_dhcp(void);
>> >> > > >  *         !0 if error
>> >> > > >  */
>> >> > > >  int ulwip_wget(ulong addr, char *url);
>> >> > > > +
>> >> > > > +/**
>> >> > > > + * ulwip_tftp() - load file with tftp
>> >> > > > + *
>> >> > > > + * Load file with tftp to specific address
>> >> > > > + *
>> >> > > > + * @param addr - address to store downloaded file
>> >> > > > + * @param filename - file name on remote tftp server to download
>> >> > >
>> >> > > Please fix function comments properly
>> >> > >
>> >> > > > + *
>> >> > > > + *
>> >> > > > + * @return 0 if success, !0 if error
>> >> > > > + */
>> >> > > > +int ulwip_tftp(ulong addr, const char *filename);
>> >> > > > +
>> >> > > > +/*
>> >> > > > +* This function creates the ping for  address provided in parameters.
>> >> > > > +* After this function you need to invoke the polling
>> >> > > > +* loop to process network communication.
>> >> > > > +*
>> >> > > > +*
>> >> > > > +* @ping_addr  start address to download result
>> >> > > > +* Return: 0 for success
>> >> > > > +*         !0 if error
>> >> > > > +*/
>> >> > > > +int ulwip_ping(char *ping_addr);
>> >> > > > diff --git a/net/lwip/Makefile b/net/lwip/Makefile
>> >> > > > index 4c6df94807..8b3e843426 100644
>> >> > > > --- a/net/lwip/Makefile
>> >> > > > +++ b/net/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/net/lwip/apps/ping/Makefile b/net/lwip/apps/ping/Makefile
>> >> > > > new file mode 100644
>> >> > > > index 0000000000..dc63feb7b5
>> >> > > > --- /dev/null
>> >> > > > +++ b/net/lwip/apps/ping/Makefile
>> >> > > > @@ -0,0 +1,11 @@
>> >> > > > +ccflags-y += -I$(srctree)/net/lwip/port/include
>> >> > > > +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include
>> >> > > -I$(srctree)/net/lwip
>> >> > > > +ccflags-y += -I$(obj)
>> >> > > > +
>> >> > > > +.PHONY: $(obj)/ping.c
>> >> > > > +$(obj)/ping.o: $(obj)/ping.c
>> >> > > > +$(obj)/ping.c:
>> >> > > > +     cp $(srctree)/net/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/net/lwip/apps/ping/lwip_ping.c
>> >> > > b/net/lwip/apps/ping/lwip_ping.c
>> >> > > > new file mode 100644
>> >> > > > index 0000000000..611fcaf591
>> >> > > > --- /dev/null
>> >> > > > +++ b/net/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 "lwip_ping.h"
>> >> > > > +
>> >> > > > +static ip_addr_t ip_target;
>> >> > > > +
>> >> > > > +static int ulwip_ping_tmo(void)
>> >> > > > +{
>> >> > > > +
>> >> > > > +     log_err("ping failed; host %s is not alive\n",
>> >> > > ipaddr_ntoa(&ip_target));
>> >> > > > +     return 1;
>> >> > > > +}
>> >> > > > +
>> >> > > > +int ulwip_ping(char *ping_addr)
>> >> > > > +{
>> >> > > > +     int err;
>> >> > > > +
>> >> > > > +     err = ipaddr_aton(ping_addr, &ip_target);
>> >> > > > +     if (!err) {
>> >> > > > +             log_err("wrong ping addr string \"%s\" \n", ping_addr);
>> >> > >
>> >> > > Invalid ip address is enough
>> >> > >
>> >> > > > +             return -1;
>> >> > > > +     }
>> >> > > > +
>> >> > > > +     ulwip_set_tmo(ulwip_ping_tmo);
>> >> > > > +
>> >> > > > +     ping_init(&ip_target);
>> >> > > > +     ping_send_now();
>> >> > > > +
>> >> > > > +     return 0;
>> >> > > > +}
>> >> > > > diff --git a/net/lwip/apps/ping/lwip_ping.h
>> >> > > b/net/lwip/apps/ping/lwip_ping.h
>> >> > > > new file mode 100644
>> >> > > > index 0000000000..0374f07d9e
>> >> > > > --- /dev/null
>> >> > > > +++ b/net/lwip/apps/ping/lwip_ping.h
>> >> > > > @@ -0,0 +1,15 @@
>> >> > > > +/* 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>
>> >> > > > +
>> >> > > > +void ping_raw_init(void);
>> >> > > > +void ping_send_now(void);
>> >> > > > +
>> >> > > > +#endif /* LWIP_PING_H */
>> >> > > > diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h
>> >> > > > new file mode 100644
>> >> > > > index 0000000000..006a18c658
>> >> > > > --- /dev/null
>> >> > > > +++ b/net/lwip/apps/ping/ping.h
>> >> > > > @@ -0,0 +1,19 @@
>> >> > > > +/* SPDX-License-Identifier: GPL-2.0 */
>> >> > > > +
>> >> > > > +#include <net/ulwip.h>
>> >> > > > +#include "lwip/ip_addr.h"
>> >> > > > +
>> >> > > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
>> >> > > > +#define PING_RESULT(cond) { \
>> >> > > > +     if (cond == 1) { \
>> >> > > > +             printf("host %s a alive\n", ipaddr_ntoa(addr)); \
>> >> > > > +             printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
>> >> > > > +             ulwip_exit(0); \
>> >> > > > +     } else { \
>> >> > > > +             printf("ping failed; host %s in not alive\n",\
>> >> > > > +                    ipaddr_ntoa(addr)); \
>> >> > > > +             ulwip_exit(-1); \
>> >> > > > +     } \
>> >> > > > +     } while (0);
>> >> > >
>> >> > > On the previous patch you are defining a function to do something similar
>> >> > > (httpc_result()).  We need to be consistent on this.  Can we define a
>> >> > > common function for all failures?  Certianly don't define a macro here and
>> >> > > a function elsewhere
>> >> > >
>> >> >
>> >> > Ilias, there I reuse lwip example ping.c. It has PING_RESULT which can be
>> >> > redefined by the application.
>> >> > This is a way to not modify this original ping.c example code.
>> >> > The common part of this function and httpc_result() is ulwip_exit(err) with
>> >> > some additional print (print is differ).
>> >>
>> >> I'll reply on this patch, although it is a general comment.
>> >>
>> >> I would like to see if we can use the cyclic feature to allow network
>> >> operations to happen in the background. This would involve splitting
>> >> each operation into:
>> >>
>> >> - setup start and kick off, e.g. ping_sttart()
>> >> - checking what needs doing, e.g. ping_poll()
>> >> - finish and clean-up, e.g. ping_finish()
>> >>
>> >> So something like:
>> >>
>> >> ping -B 1.2.3.4
>> >>
>> >> (-B is background)
>> >>
>> >> That would fire off the packet but immediately return with a prompt.
>> >> When the pings are received they would show on the console, with a new
>> >> prompt displayed. The same for tftp -B...it would start the transfer
>> >> but allow other commands to be sent while it is in progress.
>> >>
>> >> Part of the reason for this is that when booting there are a lot of
>> >> operations which take a long time and nothing happens until everything
>> >> is done. For example, with standard boot, mmc devices can be shown
>> >> right away, but USB and network ones take a lot longer, so having OS's
>> >> on those devices appear later on the slower devices is desirable for
>> >> the user.
>> >>
>> >> Is this something that lwip can support? It is one reason why I have
>> >> advocating putting the state in a struct instead of having a lot of
>> >> separate vars.
>> >>
>> >> Regards,
>> >> Simon
>> >
>> >
>> > This functionality can be added. I do not see any restrictions implementing that.
>> > Added I mean to U-Boot. lwip will definitely work with it.
>> >
>> > There is no specific poll() for application. Application just do init() and request
>> > the needed packets (port, type etc, like sockets) and then common lwip poll()
>> > function is called.
>> >
>> > To implement background we need to periodically call eth_rx() and ulwip_poll() to feed lwip
>> > stack with rx packets when we are in the cmd shell. I see in some places we call schedule()
>> > to reprogram wdt, if we call rx polling loop in the similar way the app will work in the background.
>> >
>> > We might also want to support 2 applications at the same time. Like a telnet server
>> > and ping. Multiply applications also work with lwip.
>> >
>> > Even parallel download can save some time:
>> > wget -B http://url1/zImage
>> > wget -B http//url2/dtb
>> > (-B = background)
>> >
>> > But I'm thinking if we can implement background  in a more generic way in U-Boot cmd. Things like
>> > mount UBI fs, or download from SPI flash is slow. Or probably we can also do some loading while
>> > verifying the zImage checksum.
>>
>> Yes, perhaps we can keep a record of the command that is running, with a little bit of state there. But does the stack support two wgets at once?
>>
>> Regards,
>> Simon
>
>
> Yes, it's a complete stack and it supports multiple networking applications.

Really what I meant was whether it can support several operations at
once, based on how you have integrated it into U-Boot, but I suspect
the answer is yes.

Regards,
Simon

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

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

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-14 13:32 [PATCHv6 00/14] net/lwip: add lwip library for the network stack Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 01/14] net/lwip: add doc/develop/net_lwip.rst Maxim Uvarov
2023-08-14 14:10   ` Ilias Apalodimas
2023-08-14 13:32 ` [PATCHv6 02/14] net/lwip: integrate lwIP library Maxim Uvarov
2023-08-14 14:13   ` Ilias Apalodimas
2023-08-14 13:32 ` [PATCHv6 03/14] net/lwip: implement dns cmd Maxim Uvarov
2023-08-14 14:19   ` Ilias Apalodimas
2023-08-14 15:15     ` Maxim Uvarov
2023-08-15 12:42     ` Maxim Uvarov
2023-08-15 14:42       ` Tom Rini
2023-08-16 10:26         ` Ilias Apalodimas
2023-08-16 11:01           ` Maxim Uvarov
2023-08-16 11:54             ` Ilias Apalodimas
2023-08-16 12:24               ` Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 04/14] net/lwip: implement dhcp cmd Maxim Uvarov
2023-08-14 14:21   ` Ilias Apalodimas
2023-08-14 15:18     ` Maxim Uvarov
2023-08-14 15:29       ` Tom Rini
2023-08-17 13:46         ` Maxim Uvarov
2023-08-17 14:04           ` Peter Robinson
2023-08-17 14:55             ` Maxim Uvarov
2023-08-17 15:10               ` Tom Rini
2023-08-18  9:39                 ` Maxim Uvarov
2023-08-18 11:14                   ` Peter Robinson
2023-08-18 14:24                     ` Tom Rini
2023-08-14 13:32 ` [PATCHv6 05/14] net/lwip: implement tftp cmd Maxim Uvarov
2023-08-14 14:25   ` Ilias Apalodimas
2023-08-14 18:54     ` Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 06/14] net/lwip: implement wget cmd Maxim Uvarov
2023-08-16  8:38   ` Ilias Apalodimas
2023-08-14 13:32 ` [PATCHv6 07/14] net/lwip: implement ping cmd Maxim Uvarov
2023-08-16  8:42   ` Ilias Apalodimas
2023-08-16  9:09     ` Maxim Uvarov
2023-08-16 14:39       ` Simon Glass
2023-08-16 20:15         ` Maxim Uvarov
2023-08-18  3:10           ` Simon Glass
2023-08-18  9:27             ` Maxim Uvarov
2023-08-22 18:56               ` Simon Glass
2023-08-14 13:32 ` [PATCHv6 08/14] net/lwip: add lwIP configuration Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 09/14] net/lwip: implement lwIP port to U-Boot Maxim Uvarov
2023-08-16  9:01   ` Ilias Apalodimas
2023-08-18 12:53     ` Maxim Uvarov
2023-08-18 18:21       ` Simon Goldschmidt
2023-08-14 13:32 ` [PATCHv6 10/14] net/lwip: update .gitignore with lwIP Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 11/14] net/lwip: connection between cmd and lwip apps Maxim Uvarov
2023-08-16  9:12   ` Ilias Apalodimas
2023-08-14 13:32 ` [PATCHv6 12/14] net/lwip: replace original net commands with lwip Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 13/14] net/lwip: split net.h to net.h, arp.h and eth.h Maxim Uvarov
2023-08-14 13:32 ` [PATCHv6 14/14] net/lwip: drop old net/wget 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.