diff mbox series

[2/3] net: lwip: add sntp command

Message ID 20250521151516.16729-3-jerome.forissier@linaro.org
State New
Headers show
Series sntp for NET_LWIP | expand

Commit Message

Jerome Forissier May 21, 2025, 3:14 p.m. UTC
Implement the sntp command when NET_LWIP=y.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---

 cmd/Kconfig                |  13 ++--
 cmd/net-lwip.c             |   5 ++
 include/net-common.h       |  11 ++++
 lib/lwip/Makefile          |   1 +
 lib/lwip/u-boot/arch/cc.h  |   4 ++
 lib/lwip/u-boot/lwipopts.h |   4 ++
 net/lwip/Makefile          |   1 +
 net/lwip/sntp.c            | 128 +++++++++++++++++++++++++++++++++++++
 8 files changed, 161 insertions(+), 6 deletions(-)
 create mode 100644 net/lwip/sntp.c
diff mbox series

Patch

diff --git a/cmd/Kconfig b/cmd/Kconfig
index f21d27cb27f..58f629e1c34 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2061,12 +2061,6 @@  config CMD_CDP
 	  and to retrieve configuration data including the VLAN id using the
 	  proprietary Cisco Discovery Protocol (CDP).
 
-config CMD_SNTP
-	bool "sntp"
-	select PROT_UDP
-	help
-	  Synchronize RTC via network
-
 config CMD_LINK_LOCAL
 	bool "linklocal"
 	depends on (LIB_RAND || LIB_HW_RAND)
@@ -2144,6 +2138,13 @@  config CMD_PING
 	help
 	  Send ICMP ECHO_REQUEST to network host
 
+config CMD_SNTP
+	bool "sntp"
+	select PROT_UDP if NET
+	select PROT_UDP_LWIP if NET_LWIP
+	help
+	  Synchronize RTC via network
+
 config CMD_TFTPBOOT
 	bool "tftp"
 	select PROT_UDP_LWIP if NET_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index cecf8d02555..2ffee64f97e 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -21,6 +21,11 @@  U_BOOT_CMD(tftpboot, 3, 0, do_tftpb,
 	   "[loadAddress] [[hostIPaddr:]bootfilename]");
 #endif
 
+#if defined(CONFIG_CMD_SNTP)
+U_BOOT_CMD(sntp, 2, 1, do_sntp, "synchronize RTC via network",
+	   "[NTP server IP]");
+#endif
+
 #if defined(CONFIG_CMD_DNS)
 U_BOOT_CMD(dns, 3, 1, do_dns, "lookup the IP of a hostname",
 	   "hostname [envvar]");
diff --git a/include/net-common.h b/include/net-common.h
index a021bf503ff..b06cafb497e 100644
--- a/include/net-common.h
+++ b/include/net-common.h
@@ -505,6 +505,17 @@  int dhcp_run(ulong addr, const char *fname, bool autoload);
  */
 int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 
+/**
+ * do_sntp - Run the sntp command
+ *
+ * @cmdtp: Unused
+ * @flag: Command flags (CMD_FLAG_...)
+ * @argc: Number of arguments
+ * @argv: List of arguments
+ * Return: result (see enum command_ret_t)
+ */
+int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+
 /**
  * do_tftpb - Run the tftpboot command
  *
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
index e9e8caee93a..c3f0e916f66 100644
--- a/lib/lwip/Makefile
+++ b/lib/lwip/Makefile
@@ -13,6 +13,7 @@  obj-y += \
 	lwip/src/api/sockets.o \
 	lwip/src/api/tcpip.o \
 	lwip/src/apps/http/http_client.o \
+	lwip/src/apps/sntp/sntp.o \
 	lwip/src/apps/tftp/tftp.o \
 	lwip/src/core/altcp_alloc.o \
 	lwip/src/core/altcp.o \
diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
index 6104c296f6f..f91127ac565 100644
--- a/lib/lwip/u-boot/arch/cc.h
+++ b/lib/lwip/u-boot/arch/cc.h
@@ -43,4 +43,8 @@ 
 #define BYTE_ORDER BIG_ENDIAN
 #endif
 
+#define SNTP_STARTUP_DELAY 0
+void sntp_set_system_time(uint32_t sec);
+#define SNTP_SET_SYSTEM_TIME(sec) sntp_set_system_time(sec)
+
 #endif /* LWIP_ARCH_CC_H */
diff --git a/lib/lwip/u-boot/lwipopts.h b/lib/lwip/u-boot/lwipopts.h
index edac74ff7a2..14ba7bd7ae2 100644
--- a/lib/lwip/u-boot/lwipopts.h
+++ b/lib/lwip/u-boot/lwipopts.h
@@ -162,4 +162,8 @@ 
 #define LWIP_ALTCP_TLS_MBEDTLS          1
 #endif
 
+#if defined(CONFIG_CMD_SNTP)
+#define LWIP_DHCP_GET_NTP_SRV 1
+#endif
+
 #endif /* LWIP_UBOOT_LWIPOPTS_H */
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index 5df222589b8..5bb98dc4d98 100644
--- a/net/lwip/Makefile
+++ b/net/lwip/Makefile
@@ -4,6 +4,7 @@  obj-$(CONFIG_$(PHASE_)DM_ETH) += net-lwip.o
 obj-$(CONFIG_CMD_DHCP) += dhcp.o
 obj-$(CONFIG_CMD_DNS) += dns.o
 obj-$(CONFIG_CMD_PING) += ping.o
+obj-$(CONFIG_CMD_SNTP) += sntp.o
 obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
 obj-$(CONFIG_WGET) += wget.o
 
diff --git a/net/lwip/sntp.c b/net/lwip/sntp.c
new file mode 100644
index 00000000000..3b2bc3c679d
--- /dev/null
+++ b/net/lwip/sntp.c
@@ -0,0 +1,128 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2025 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <dm/device.h>
+#include <lwip/apps/sntp.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+
+#define SNTP_TIMEOUT 10000
+
+static enum done_state {
+	NOT_DONE = 0,
+	SUCCESS,
+	ABORTED,
+	TIMED_OUT
+} sntp_state;
+
+static void no_response(void *arg)
+{
+	sntp_state = TIMED_OUT;
+}
+
+/* Called by lwIP via the SNTP_SET_SYSTEM_TIME() macro */
+void sntp_set_system_time(uint32_t seconds)
+{
+	char *toff;
+	int net_ntp_time_offset = 0;
+
+	toff = env_get("timeoffset");
+	if (toff)
+		net_ntp_time_offset = simple_strtol(toff, NULL, 10);
+
+	net_sntp_set_rtc(seconds + net_ntp_time_offset);
+	sntp_state = SUCCESS;
+}
+
+static bool ntp_server_known(void)
+{
+	int i;
+
+	for (i = 0; i < SNTP_MAX_SERVERS; i++) {
+		const ip_addr_t *ip = sntp_getserver(i);
+
+		if (ip && ip->addr)
+			return true;
+	}
+
+	return false;
+}
+
+static int sntp_loop(struct udevice *udev, ip_addr_t *srvip)
+{
+	struct netif *netif;
+
+	netif = net_lwip_new_netif(udev);
+	if (!netif)
+		return -1;
+
+	sntp_state = NOT_DONE;
+
+	sntp_setoperatingmode(SNTP_OPMODE_POLL);
+	sntp_servermode_dhcp(CONFIG_IS_ENABLED(CMD_DHCP));
+	if (srvip) {
+		sntp_setserver(0, srvip);
+	} else {
+		if (!ntp_server_known()) {
+			log_err("error: ntpserverip not set\n");
+			return -1;
+		}
+	}
+	sntp_init();
+
+	sys_timeout(SNTP_TIMEOUT, no_response, NULL);
+	while (sntp_state == NOT_DONE) {
+		net_lwip_rx(udev, netif);
+		sys_check_timeouts();
+		if (ctrlc()) {
+			printf("\nAbort\n");
+			sntp_state = ABORTED;
+			break;
+		}
+	}
+	sys_untimeout(no_response, NULL);
+
+	sntp_stop();
+	net_lwip_remove_netif(netif);
+
+	if (sntp_state == SUCCESS)
+		return 0;
+
+	return -1;
+}
+
+int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	ip_addr_t *srvip = NULL;
+	char *server_ip = NULL;
+	ip_addr_t ipaddr;
+
+	switch (argc) {
+	case 1:
+		server_ip = env_get("ntpserverip");
+		break;
+	case 2:
+		server_ip = argv[1];
+		break;
+	default:
+		return CMD_RET_USAGE;
+	}
+
+	if (server_ip) {
+		if (!ipaddr_aton(server_ip, &ipaddr)) {
+			log_err("error: ipaddr_aton\n");
+			return CMD_RET_FAILURE;
+		}
+		srvip = &ipaddr;
+	}
+
+	if (net_lwip_eth_start() < 0)
+		return CMD_RET_FAILURE;
+
+	if (sntp_loop(eth_get_dev(), srvip) < 0)
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}