* [PATCH v4 01/14] flash: prefix error codes with FL_
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-18 16:22 ` Tom Rini
2024-06-19 7:29 ` Ilias Apalodimas
2024-06-17 15:32 ` [PATCH v4 02/14] net: introduce alternative implementation as net-lwip/ Jerome Forissier
` (15 subsequent siblings)
16 siblings, 2 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Angelo Dureghello, Tom Rini, TsiChung Liew, Stefan Roese,
Peng Fan, Jason Liu, William Zhang
Prefix the flash status codes (ERR_*) with FL_ in order to avoid clashes
with third-party libraries. Case in point: including the lwIP library
header file <lwip/err.h> which defines err_enum_t as an enum with values
being ERR_*.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
board/cobra5272/flash.c | 26 +++++++++---------
board/freescale/m5253demo/flash.c | 6 ++---
common/flash.c | 44 +++++++++++++++----------------
drivers/mtd/cfi_flash.c | 36 ++++++++++++-------------
include/flash.h | 20 +++++++-------
5 files changed, 66 insertions(+), 66 deletions(-)
diff --git a/board/cobra5272/flash.c b/board/cobra5272/flash.c
index 8416af163ad..6464975f184 100644
--- a/board/cobra5272/flash.c
+++ b/board/cobra5272/flash.c
@@ -134,22 +134,22 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
{
ulong result;
int iflag, cflag, prot, sect;
- int rc = ERR_OK;
+ int rc = FL_ERR_OK;
int chip1;
ulong start;
/* first look for protection bits */
if (info->flash_id == FLASH_UNKNOWN)
- return ERR_UNKNOWN_FLASH_TYPE;
+ return FL_ERR_UNKNOWN_FLASH_TYPE;
if ((s_first < 0) || (s_first > s_last)) {
- return ERR_INVAL;
+ return FL_ERR_INVAL;
}
if ((info->flash_id & FLASH_VENDMASK) !=
(AMD_MANUFACT & FLASH_VENDMASK)) {
- return ERR_UNKNOWN_FLASH_VENDOR;
+ return FL_ERR_UNKNOWN_FLASH_VENDOR;
}
prot = 0;
@@ -159,7 +159,7 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
}
}
if (prot)
- return ERR_PROTECTED;
+ return FL_ERR_PROTECTED;
/*
* Disable interrupts which might cause a timeout
@@ -216,11 +216,11 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
if (chip1 == ERR) {
- rc = ERR_PROG_ERROR;
+ rc = FL_ERR_PROG_ERROR;
goto outahere;
}
if (chip1 == TMO) {
- rc = ERR_TIMEOUT;
+ rc = FL_ERR_TIMEOUT;
goto outahere;
}
@@ -251,7 +251,7 @@ static int write_word(flash_info_t *info, ulong dest, ulong data)
{
volatile u16 *addr = (volatile u16 *) dest;
ulong result;
- int rc = ERR_OK;
+ int rc = FL_ERR_OK;
int cflag, iflag;
int chip1;
ulong start;
@@ -261,7 +261,7 @@ static int write_word(flash_info_t *info, ulong dest, ulong data)
*/
result = *addr;
if ((result & data) != data)
- return ERR_NOT_ERASED;
+ return FL_ERR_NOT_ERASED;
/*
@@ -302,7 +302,7 @@ static int write_word(flash_info_t *info, ulong dest, ulong data)
*addr = CMD_READ_ARRAY;
if (chip1 == ERR || *addr != data)
- rc = ERR_PROG_ERROR;
+ rc = FL_ERR_PROG_ERROR;
if (iflag)
enable_interrupts();
@@ -321,13 +321,13 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
if (addr & 1) {
printf ("unaligned destination not supported\n");
- return ERR_ALIGN;
+ return FL_ERR_ALIGN;
}
#if 0
if (cnt & 1) {
printf ("odd transfer sizes not supported\n");
- return ERR_ALIGN;
+ return FL_ERR_ALIGN;
}
#endif
@@ -365,5 +365,5 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
cnt -= 1;
}
- return ERR_OK;
+ return FL_ERR_OK;
}
diff --git a/board/freescale/m5253demo/flash.c b/board/freescale/m5253demo/flash.c
index eeb9cfd3125..b6b7df88761 100644
--- a/board/freescale/m5253demo/flash.c
+++ b/board/freescale/m5253demo/flash.c
@@ -71,7 +71,7 @@ int flash_get_offsets(ulong base, flash_info_t * info)
}
}
- return ERR_OK;
+ return FL_ERR_OK;
}
void flash_print_info(flash_info_t * info)
@@ -368,9 +368,9 @@ int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
}
if (cnt == 0)
- return ERR_OK;
+ return FL_ERR_OK;
- return ERR_OK;
+ return FL_ERR_OK;
}
/*-----------------------------------------------------------------------
diff --git a/common/flash.c b/common/flash.c
index 848f44e59df..99fd84e2aef 100644
--- a/common/flash.c
+++ b/common/flash.c
@@ -110,13 +110,13 @@ addr2info(ulong addr)
* Make sure all target addresses are within Flash bounds,
* and no protected sectors are hit.
* Returns:
- * ERR_OK 0 - OK
- * ERR_TIMEOUT 1 - write timeout
- * ERR_NOT_ERASED 2 - Flash not erased
- * ERR_PROTECTED 4 - target range includes protected sectors
- * ERR_INVAL 8 - target address not in Flash memory
- * ERR_ALIGN 16 - target address not aligned on boundary
- * (only some targets require alignment)
+ * FL_ERR_OK 0 - OK
+ * FL_ERR_TIMEOUT 1 - write timeout
+ * FL_ERR_NOT_ERASED 2 - Flash not erased
+ * FL_ERR_PROTECTED 4 - target range includes protected sectors
+ * FL_ERR_INVAL 8 - target address not in Flash memory
+ * FL_ERR_ALIGN 16 - target address not aligned on boundary
+ * (only some targets require alignment)
*/
int
flash_write(char *src, ulong addr, ulong cnt)
@@ -131,11 +131,11 @@ flash_write(char *src, ulong addr, ulong cnt)
__maybe_unused ulong cnt_orig = cnt;
if (cnt == 0) {
- return (ERR_OK);
+ return (FL_ERR_OK);
}
if (!info_first || !info_last) {
- return (ERR_INVAL);
+ return (FL_ERR_INVAL);
}
for (info = info_first; info <= info_last; ++info) {
@@ -146,7 +146,7 @@ flash_write(char *src, ulong addr, ulong cnt)
if ((end >= info->start[i]) && (addr < e_addr) &&
(info->protect[i] != 0) ) {
- return (ERR_PROTECTED);
+ return (FL_ERR_PROTECTED);
}
}
}
@@ -169,11 +169,11 @@ flash_write(char *src, ulong addr, ulong cnt)
#if defined(CONFIG_FLASH_VERIFY)
if (memcmp(src_orig, addr_orig, cnt_orig)) {
printf("\nVerify failed!\n");
- return ERR_PROG_ERROR;
+ return FL_ERR_PROG_ERROR;
}
#endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */
- return (ERR_OK);
+ return (FL_ERR_OK);
}
/*-----------------------------------------------------------------------
@@ -182,33 +182,33 @@ flash_write(char *src, ulong addr, ulong cnt)
void flash_perror(int err)
{
switch (err) {
- case ERR_OK:
+ case FL_ERR_OK:
break;
- case ERR_TIMEOUT:
+ case FL_ERR_TIMEOUT:
puts ("Timeout writing to Flash\n");
break;
- case ERR_NOT_ERASED:
+ case FL_ERR_NOT_ERASED:
puts ("Flash not Erased\n");
break;
- case ERR_PROTECTED:
+ case FL_ERR_PROTECTED:
puts ("Can't write to protected Flash sectors\n");
break;
- case ERR_INVAL:
+ case FL_ERR_INVAL:
puts ("Outside available Flash\n");
break;
- case ERR_ALIGN:
+ case FL_ERR_ALIGN:
puts ("Start and/or end address not on sector boundary\n");
break;
- case ERR_UNKNOWN_FLASH_VENDOR:
+ case FL_ERR_UNKNOWN_FLASH_VENDOR:
puts ("Unknown Vendor of Flash\n");
break;
- case ERR_UNKNOWN_FLASH_TYPE:
+ case FL_ERR_UNKNOWN_FLASH_TYPE:
puts ("Unknown Type of Flash\n");
break;
- case ERR_PROG_ERROR:
+ case FL_ERR_PROG_ERROR:
puts ("General Flash Programming Error\n");
break;
- case ERR_ABORTED:
+ case FL_ERR_ABORTED:
puts("Flash Programming Aborted\n");
break;
default:
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 8ade7949a68..6369c7127c6 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -592,11 +592,11 @@ static int flash_status_check(flash_info_t *info, flash_sect_t sector,
flash_read_long(info, sector, 0));
flash_write_cmd(info, sector, 0, info->cmd_reset);
udelay(1);
- return ERR_TIMEOUT;
+ return FL_ERR_TIMEOUT;
}
udelay(1); /* also triggers watchdog */
}
- return ERR_OK;
+ return FL_ERR_OK;
}
/*-----------------------------------------------------------------------
@@ -615,9 +615,9 @@ static int flash_full_status_check(flash_info_t *info, flash_sect_t sector,
case CFI_CMDSET_INTEL_PROG_REGIONS:
case CFI_CMDSET_INTEL_EXTENDED:
case CFI_CMDSET_INTEL_STANDARD:
- if (retcode == ERR_OK &&
+ if (retcode == FL_ERR_OK &&
!flash_isset(info, sector, 0, FLASH_STATUS_DONE)) {
- retcode = ERR_INVAL;
+ retcode = FL_ERR_INVAL;
printf("Flash %s error at address %lx\n", prompt,
info->start[sector]);
if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS |
@@ -626,14 +626,14 @@ static int flash_full_status_check(flash_info_t *info, flash_sect_t sector,
} else if (flash_isset(info, sector, 0,
FLASH_STATUS_ECLBS)) {
puts("Block Erase Error.\n");
- retcode = ERR_NOT_ERASED;
+ retcode = FL_ERR_NOT_ERASED;
} else if (flash_isset(info, sector, 0,
FLASH_STATUS_PSLBS)) {
puts("Locking Error\n");
}
if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
puts("Block locked.\n");
- retcode = ERR_PROTECTED;
+ retcode = FL_ERR_PROTECTED;
}
if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
puts("Vpp Low Error.\n");
@@ -701,12 +701,12 @@ static int flash_status_poll(flash_info_t *info, void *src, void *dst,
if (get_timer(start) > tout) {
printf("Flash %s timeout at address %lx data %lx\n",
prompt, (ulong)dst, (ulong)flash_read8(dst));
- return ERR_TIMEOUT;
+ return FL_ERR_TIMEOUT;
}
udelay(1); /* also triggers watchdog */
}
#endif /* CONFIG_SYS_CFI_FLASH_STATUS_POLL */
- return ERR_OK;
+ return FL_ERR_OK;
}
/*-----------------------------------------------------------------------
@@ -809,7 +809,7 @@ static int flash_write_cfiword(flash_info_t *info, ulong dest, cfiword_t cword)
break;
}
if (!flag)
- return ERR_NOT_ERASED;
+ return FL_ERR_NOT_ERASED;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
@@ -898,7 +898,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
shift = 3;
break;
default:
- retcode = ERR_INVAL;
+ retcode = FL_ERR_INVAL;
goto out_unmap;
}
@@ -929,7 +929,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
}
}
if (!flag) {
- retcode = ERR_NOT_ERASED;
+ retcode = FL_ERR_NOT_ERASED;
goto out_unmap;
}
@@ -949,7 +949,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
retcode = flash_status_check(info, sector,
info->buffer_write_tout,
"write to buffer");
- if (retcode == ERR_OK) {
+ if (retcode == FL_ERR_OK) {
/* reduce the number of loops by the width of
* the port
*/
@@ -974,7 +974,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
src += 8, dst += 8;
break;
default:
- retcode = ERR_INVAL;
+ retcode = FL_ERR_INVAL;
goto out_unmap;
}
}
@@ -1024,7 +1024,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
}
break;
default:
- retcode = ERR_INVAL;
+ retcode = FL_ERR_INVAL;
goto out_unmap;
}
@@ -1042,7 +1042,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
default:
debug("Unknown Command Set\n");
- retcode = ERR_INVAL;
+ retcode = FL_ERR_INVAL;
break;
}
@@ -1388,7 +1388,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
if (i > cnt)
i = cnt;
rc = flash_write_cfibuffer(info, wp, src, i);
- if (rc != ERR_OK)
+ if (rc != FL_ERR_OK)
return rc;
i -= i & (info->portwidth - 1);
wp += i;
@@ -1397,7 +1397,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
FLASH_SHOW_PROGRESS(scale, dots, digit, i);
/* Only check every once in a while */
if ((cnt & 0xFFFF) < buffered_size && ctrlc())
- return ERR_ABORTED;
+ return FL_ERR_ABORTED;
}
#else
while (cnt >= info->portwidth) {
@@ -1412,7 +1412,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
/* Only check every once in a while */
if ((cnt & 0xFFFF) < info->portwidth && ctrlc())
- return ERR_ABORTED;
+ return FL_ERR_ABORTED;
}
#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
diff --git a/include/flash.h b/include/flash.h
index 3710a2731b7..77bee42f76b 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -125,16 +125,16 @@ void flash_perror(int err);
/*-----------------------------------------------------------------------
* return codes from flash_write():
*/
-#define ERR_OK 0
-#define ERR_TIMEOUT 1
-#define ERR_NOT_ERASED 2
-#define ERR_PROTECTED 4
-#define ERR_INVAL 8
-#define ERR_ALIGN 16
-#define ERR_UNKNOWN_FLASH_VENDOR 32
-#define ERR_UNKNOWN_FLASH_TYPE 64
-#define ERR_PROG_ERROR 128
-#define ERR_ABORTED 256
+#define FL_ERR_OK 0
+#define FL_ERR_TIMEOUT 1
+#define FL_ERR_NOT_ERASED 2
+#define FL_ERR_PROTECTED 4
+#define FL_ERR_INVAL 8
+#define FL_ERR_ALIGN 16
+#define FL_ERR_UNKNOWN_FLASH_VENDOR 32
+#define FL_ERR_UNKNOWN_FLASH_TYPE 64
+#define FL_ERR_PROG_ERROR 128
+#define FL_ERR_ABORTED 256
/*-----------------------------------------------------------------------
* Protection Flags for flash_protect():
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 01/14] flash: prefix error codes with FL_
2024-06-17 15:32 ` [PATCH v4 01/14] flash: prefix error codes with FL_ Jerome Forissier
@ 2024-06-18 16:22 ` Tom Rini
2024-06-19 7:29 ` Ilias Apalodimas
1 sibling, 0 replies; 53+ messages in thread
From: Tom Rini @ 2024-06-18 16:22 UTC (permalink / raw)
To: Jerome Forissier
Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov,
Angelo Dureghello, TsiChung Liew, Stefan Roese, Peng Fan,
Jason Liu, William Zhang
[-- Attachment #1: Type: text/plain, Size: 437 bytes --]
On Mon, Jun 17, 2024 at 05:32:53PM +0200, Jerome Forissier wrote:
> Prefix the flash status codes (ERR_*) with FL_ in order to avoid clashes
> with third-party libraries. Case in point: including the lwIP library
> header file <lwip/err.h> which defines err_enum_t as an enum with values
> being ERR_*.
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 01/14] flash: prefix error codes with FL_
2024-06-17 15:32 ` [PATCH v4 01/14] flash: prefix error codes with FL_ Jerome Forissier
2024-06-18 16:22 ` Tom Rini
@ 2024-06-19 7:29 ` Ilias Apalodimas
1 sibling, 0 replies; 53+ messages in thread
From: Ilias Apalodimas @ 2024-06-19 7:29 UTC (permalink / raw)
To: Jerome Forissier
Cc: u-boot, Javier Tia, Maxim Uvarov, Angelo Dureghello, Tom Rini,
TsiChung Liew, Stefan Roese, Peng Fan, Jason Liu, William Zhang
On Mon, 17 Jun 2024 at 18:33, Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> Prefix the flash status codes (ERR_*) with FL_ in order to avoid clashes
> with third-party libraries. Case in point: including the lwIP library
> header file <lwip/err.h> which defines err_enum_t as an enum with values
> being ERR_*.
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> ---
> board/cobra5272/flash.c | 26 +++++++++---------
> board/freescale/m5253demo/flash.c | 6 ++---
> common/flash.c | 44 +++++++++++++++----------------
> drivers/mtd/cfi_flash.c | 36 ++++++++++++-------------
> include/flash.h | 20 +++++++-------
> 5 files changed, 66 insertions(+), 66 deletions(-)
>
> diff --git a/board/cobra5272/flash.c b/board/cobra5272/flash.c
> index 8416af163ad..6464975f184 100644
> --- a/board/cobra5272/flash.c
> +++ b/board/cobra5272/flash.c
> @@ -134,22 +134,22 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
> {
> ulong result;
> int iflag, cflag, prot, sect;
> - int rc = ERR_OK;
> + int rc = FL_ERR_OK;
> int chip1;
> ulong start;
>
> /* first look for protection bits */
>
> if (info->flash_id == FLASH_UNKNOWN)
> - return ERR_UNKNOWN_FLASH_TYPE;
> + return FL_ERR_UNKNOWN_FLASH_TYPE;
>
> if ((s_first < 0) || (s_first > s_last)) {
> - return ERR_INVAL;
> + return FL_ERR_INVAL;
> }
>
> if ((info->flash_id & FLASH_VENDMASK) !=
> (AMD_MANUFACT & FLASH_VENDMASK)) {
> - return ERR_UNKNOWN_FLASH_VENDOR;
> + return FL_ERR_UNKNOWN_FLASH_VENDOR;
> }
>
> prot = 0;
> @@ -159,7 +159,7 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
> }
> }
> if (prot)
> - return ERR_PROTECTED;
> + return FL_ERR_PROTECTED;
>
> /*
> * Disable interrupts which might cause a timeout
> @@ -216,11 +216,11 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
> MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
>
> if (chip1 == ERR) {
> - rc = ERR_PROG_ERROR;
> + rc = FL_ERR_PROG_ERROR;
> goto outahere;
> }
> if (chip1 == TMO) {
> - rc = ERR_TIMEOUT;
> + rc = FL_ERR_TIMEOUT;
> goto outahere;
> }
>
> @@ -251,7 +251,7 @@ static int write_word(flash_info_t *info, ulong dest, ulong data)
> {
> volatile u16 *addr = (volatile u16 *) dest;
> ulong result;
> - int rc = ERR_OK;
> + int rc = FL_ERR_OK;
> int cflag, iflag;
> int chip1;
> ulong start;
> @@ -261,7 +261,7 @@ static int write_word(flash_info_t *info, ulong dest, ulong data)
> */
> result = *addr;
> if ((result & data) != data)
> - return ERR_NOT_ERASED;
> + return FL_ERR_NOT_ERASED;
>
>
> /*
> @@ -302,7 +302,7 @@ static int write_word(flash_info_t *info, ulong dest, ulong data)
> *addr = CMD_READ_ARRAY;
>
> if (chip1 == ERR || *addr != data)
> - rc = ERR_PROG_ERROR;
> + rc = FL_ERR_PROG_ERROR;
>
> if (iflag)
> enable_interrupts();
> @@ -321,13 +321,13 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
>
> if (addr & 1) {
> printf ("unaligned destination not supported\n");
> - return ERR_ALIGN;
> + return FL_ERR_ALIGN;
> }
>
> #if 0
> if (cnt & 1) {
> printf ("odd transfer sizes not supported\n");
> - return ERR_ALIGN;
> + return FL_ERR_ALIGN;
> }
> #endif
>
> @@ -365,5 +365,5 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
> cnt -= 1;
> }
>
> - return ERR_OK;
> + return FL_ERR_OK;
> }
> diff --git a/board/freescale/m5253demo/flash.c b/board/freescale/m5253demo/flash.c
> index eeb9cfd3125..b6b7df88761 100644
> --- a/board/freescale/m5253demo/flash.c
> +++ b/board/freescale/m5253demo/flash.c
> @@ -71,7 +71,7 @@ int flash_get_offsets(ulong base, flash_info_t * info)
> }
> }
>
> - return ERR_OK;
> + return FL_ERR_OK;
> }
>
> void flash_print_info(flash_info_t * info)
> @@ -368,9 +368,9 @@ int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
> }
>
> if (cnt == 0)
> - return ERR_OK;
> + return FL_ERR_OK;
>
> - return ERR_OK;
> + return FL_ERR_OK;
> }
>
> /*-----------------------------------------------------------------------
> diff --git a/common/flash.c b/common/flash.c
> index 848f44e59df..99fd84e2aef 100644
> --- a/common/flash.c
> +++ b/common/flash.c
> @@ -110,13 +110,13 @@ addr2info(ulong addr)
> * Make sure all target addresses are within Flash bounds,
> * and no protected sectors are hit.
> * Returns:
> - * ERR_OK 0 - OK
> - * ERR_TIMEOUT 1 - write timeout
> - * ERR_NOT_ERASED 2 - Flash not erased
> - * ERR_PROTECTED 4 - target range includes protected sectors
> - * ERR_INVAL 8 - target address not in Flash memory
> - * ERR_ALIGN 16 - target address not aligned on boundary
> - * (only some targets require alignment)
> + * FL_ERR_OK 0 - OK
> + * FL_ERR_TIMEOUT 1 - write timeout
> + * FL_ERR_NOT_ERASED 2 - Flash not erased
> + * FL_ERR_PROTECTED 4 - target range includes protected sectors
> + * FL_ERR_INVAL 8 - target address not in Flash memory
> + * FL_ERR_ALIGN 16 - target address not aligned on boundary
> + * (only some targets require alignment)
> */
> int
> flash_write(char *src, ulong addr, ulong cnt)
> @@ -131,11 +131,11 @@ flash_write(char *src, ulong addr, ulong cnt)
> __maybe_unused ulong cnt_orig = cnt;
>
> if (cnt == 0) {
> - return (ERR_OK);
> + return (FL_ERR_OK);
> }
>
> if (!info_first || !info_last) {
> - return (ERR_INVAL);
> + return (FL_ERR_INVAL);
> }
>
> for (info = info_first; info <= info_last; ++info) {
> @@ -146,7 +146,7 @@ flash_write(char *src, ulong addr, ulong cnt)
>
> if ((end >= info->start[i]) && (addr < e_addr) &&
> (info->protect[i] != 0) ) {
> - return (ERR_PROTECTED);
> + return (FL_ERR_PROTECTED);
> }
> }
> }
> @@ -169,11 +169,11 @@ flash_write(char *src, ulong addr, ulong cnt)
> #if defined(CONFIG_FLASH_VERIFY)
> if (memcmp(src_orig, addr_orig, cnt_orig)) {
> printf("\nVerify failed!\n");
> - return ERR_PROG_ERROR;
> + return FL_ERR_PROG_ERROR;
> }
> #endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */
>
> - return (ERR_OK);
> + return (FL_ERR_OK);
> }
>
> /*-----------------------------------------------------------------------
> @@ -182,33 +182,33 @@ flash_write(char *src, ulong addr, ulong cnt)
> void flash_perror(int err)
> {
> switch (err) {
> - case ERR_OK:
> + case FL_ERR_OK:
> break;
> - case ERR_TIMEOUT:
> + case FL_ERR_TIMEOUT:
> puts ("Timeout writing to Flash\n");
> break;
> - case ERR_NOT_ERASED:
> + case FL_ERR_NOT_ERASED:
> puts ("Flash not Erased\n");
> break;
> - case ERR_PROTECTED:
> + case FL_ERR_PROTECTED:
> puts ("Can't write to protected Flash sectors\n");
> break;
> - case ERR_INVAL:
> + case FL_ERR_INVAL:
> puts ("Outside available Flash\n");
> break;
> - case ERR_ALIGN:
> + case FL_ERR_ALIGN:
> puts ("Start and/or end address not on sector boundary\n");
> break;
> - case ERR_UNKNOWN_FLASH_VENDOR:
> + case FL_ERR_UNKNOWN_FLASH_VENDOR:
> puts ("Unknown Vendor of Flash\n");
> break;
> - case ERR_UNKNOWN_FLASH_TYPE:
> + case FL_ERR_UNKNOWN_FLASH_TYPE:
> puts ("Unknown Type of Flash\n");
> break;
> - case ERR_PROG_ERROR:
> + case FL_ERR_PROG_ERROR:
> puts ("General Flash Programming Error\n");
> break;
> - case ERR_ABORTED:
> + case FL_ERR_ABORTED:
> puts("Flash Programming Aborted\n");
> break;
> default:
> diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
> index 8ade7949a68..6369c7127c6 100644
> --- a/drivers/mtd/cfi_flash.c
> +++ b/drivers/mtd/cfi_flash.c
> @@ -592,11 +592,11 @@ static int flash_status_check(flash_info_t *info, flash_sect_t sector,
> flash_read_long(info, sector, 0));
> flash_write_cmd(info, sector, 0, info->cmd_reset);
> udelay(1);
> - return ERR_TIMEOUT;
> + return FL_ERR_TIMEOUT;
> }
> udelay(1); /* also triggers watchdog */
> }
> - return ERR_OK;
> + return FL_ERR_OK;
> }
>
> /*-----------------------------------------------------------------------
> @@ -615,9 +615,9 @@ static int flash_full_status_check(flash_info_t *info, flash_sect_t sector,
> case CFI_CMDSET_INTEL_PROG_REGIONS:
> case CFI_CMDSET_INTEL_EXTENDED:
> case CFI_CMDSET_INTEL_STANDARD:
> - if (retcode == ERR_OK &&
> + if (retcode == FL_ERR_OK &&
> !flash_isset(info, sector, 0, FLASH_STATUS_DONE)) {
> - retcode = ERR_INVAL;
> + retcode = FL_ERR_INVAL;
> printf("Flash %s error at address %lx\n", prompt,
> info->start[sector]);
> if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS |
> @@ -626,14 +626,14 @@ static int flash_full_status_check(flash_info_t *info, flash_sect_t sector,
> } else if (flash_isset(info, sector, 0,
> FLASH_STATUS_ECLBS)) {
> puts("Block Erase Error.\n");
> - retcode = ERR_NOT_ERASED;
> + retcode = FL_ERR_NOT_ERASED;
> } else if (flash_isset(info, sector, 0,
> FLASH_STATUS_PSLBS)) {
> puts("Locking Error\n");
> }
> if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
> puts("Block locked.\n");
> - retcode = ERR_PROTECTED;
> + retcode = FL_ERR_PROTECTED;
> }
> if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
> puts("Vpp Low Error.\n");
> @@ -701,12 +701,12 @@ static int flash_status_poll(flash_info_t *info, void *src, void *dst,
> if (get_timer(start) > tout) {
> printf("Flash %s timeout at address %lx data %lx\n",
> prompt, (ulong)dst, (ulong)flash_read8(dst));
> - return ERR_TIMEOUT;
> + return FL_ERR_TIMEOUT;
> }
> udelay(1); /* also triggers watchdog */
> }
> #endif /* CONFIG_SYS_CFI_FLASH_STATUS_POLL */
> - return ERR_OK;
> + return FL_ERR_OK;
> }
>
> /*-----------------------------------------------------------------------
> @@ -809,7 +809,7 @@ static int flash_write_cfiword(flash_info_t *info, ulong dest, cfiword_t cword)
> break;
> }
> if (!flag)
> - return ERR_NOT_ERASED;
> + return FL_ERR_NOT_ERASED;
>
> /* Disable interrupts which might cause a timeout here */
> flag = disable_interrupts();
> @@ -898,7 +898,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
> shift = 3;
> break;
> default:
> - retcode = ERR_INVAL;
> + retcode = FL_ERR_INVAL;
> goto out_unmap;
> }
>
> @@ -929,7 +929,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
> }
> }
> if (!flag) {
> - retcode = ERR_NOT_ERASED;
> + retcode = FL_ERR_NOT_ERASED;
> goto out_unmap;
> }
>
> @@ -949,7 +949,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
> retcode = flash_status_check(info, sector,
> info->buffer_write_tout,
> "write to buffer");
> - if (retcode == ERR_OK) {
> + if (retcode == FL_ERR_OK) {
> /* reduce the number of loops by the width of
> * the port
> */
> @@ -974,7 +974,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
> src += 8, dst += 8;
> break;
> default:
> - retcode = ERR_INVAL;
> + retcode = FL_ERR_INVAL;
> goto out_unmap;
> }
> }
> @@ -1024,7 +1024,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
> }
> break;
> default:
> - retcode = ERR_INVAL;
> + retcode = FL_ERR_INVAL;
> goto out_unmap;
> }
>
> @@ -1042,7 +1042,7 @@ static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar *cp,
>
> default:
> debug("Unknown Command Set\n");
> - retcode = ERR_INVAL;
> + retcode = FL_ERR_INVAL;
> break;
> }
>
> @@ -1388,7 +1388,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
> if (i > cnt)
> i = cnt;
> rc = flash_write_cfibuffer(info, wp, src, i);
> - if (rc != ERR_OK)
> + if (rc != FL_ERR_OK)
> return rc;
> i -= i & (info->portwidth - 1);
> wp += i;
> @@ -1397,7 +1397,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
> FLASH_SHOW_PROGRESS(scale, dots, digit, i);
> /* Only check every once in a while */
> if ((cnt & 0xFFFF) < buffered_size && ctrlc())
> - return ERR_ABORTED;
> + return FL_ERR_ABORTED;
> }
> #else
> while (cnt >= info->portwidth) {
> @@ -1412,7 +1412,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
> FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
> /* Only check every once in a while */
> if ((cnt & 0xFFFF) < info->portwidth && ctrlc())
> - return ERR_ABORTED;
> + return FL_ERR_ABORTED;
> }
> #endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
>
> diff --git a/include/flash.h b/include/flash.h
> index 3710a2731b7..77bee42f76b 100644
> --- a/include/flash.h
> +++ b/include/flash.h
> @@ -125,16 +125,16 @@ void flash_perror(int err);
> /*-----------------------------------------------------------------------
> * return codes from flash_write():
> */
> -#define ERR_OK 0
> -#define ERR_TIMEOUT 1
> -#define ERR_NOT_ERASED 2
> -#define ERR_PROTECTED 4
> -#define ERR_INVAL 8
> -#define ERR_ALIGN 16
> -#define ERR_UNKNOWN_FLASH_VENDOR 32
> -#define ERR_UNKNOWN_FLASH_TYPE 64
> -#define ERR_PROG_ERROR 128
> -#define ERR_ABORTED 256
> +#define FL_ERR_OK 0
> +#define FL_ERR_TIMEOUT 1
> +#define FL_ERR_NOT_ERASED 2
> +#define FL_ERR_PROTECTED 4
> +#define FL_ERR_INVAL 8
> +#define FL_ERR_ALIGN 16
> +#define FL_ERR_UNKNOWN_FLASH_VENDOR 32
> +#define FL_ERR_UNKNOWN_FLASH_TYPE 64
> +#define FL_ERR_PROG_ERROR 128
> +#define FL_ERR_ABORTED 256
>
> /*-----------------------------------------------------------------------
> * Protection Flags for flash_protect():
> --
> 2.40.1
>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH v4 02/14] net: introduce alternative implementation as net-lwip/
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
2024-06-17 15:32 ` [PATCH v4 01/14] flash: prefix error codes with FL_ Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-18 17:59 ` Tom Rini
2024-06-17 15:32 ` [PATCH v4 03/14] net: split include/net.h into net{, -common, -legacy, -lwip}.h Jerome Forissier
` (14 subsequent siblings)
16 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Lukasz Majewski, Mattijs Korpershoek, Joe Hershberger,
Ramon Fried, Marek Vasut, Simon Glass, Jonas Karlman, Paul Barker,
Sean Anderson, Jesse Taube, Greg Malysa, Shengyu Qu, Andrew Davis,
Sumit Garg, Bryan Brattlof, Leon M. Busch-George, Ying Sun,
Heinrich Schuchardt, Joshua Watt, Rasmus Villemoes, Bin Meng,
Andre Przywara, Leo Yu-Chi Liang, Mayuresh Chitale,
Oleksandr Suvorov, Samuel Holland, Jaehoon Chung,
Ashok Reddy Soma, Ion Agorria, Quentin Schulz, Alexey Romanov,
Yang Xiwen, Neil Armstrong, Boon Khai Ng, Yanhong Wang,
Nicolas Frattaroli, Miquel Raynal, Baruch Siach
Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
adding a new net-lwip/ directory and the NET_LWIP symbol. Network
support is either NO_NET, NET (legacy stack) or NET_LWIP. Subsequent
commits will introduce the lwIP code, re-work the NETDEVICE integration
and port some of the NET commands and features to lwIP.
SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
that are part of NET (such as arp_init(), arp_timeout_check(),
arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
added later.
Similarly, DFU_TFTP and FASTBOOT are not compatible with NET_LWIP
because of dependencies on net_loop(), tftp_timeout_ms,
tftp_timeout_count_max and other NET things. Let's add a dependency on
!NET_LWIP for now.
As for SANDBOX, NET_LWIP cannot be used either because of strong
assumptions on the network stack. Make NET_LWIP depend on !SANDBOX so
that the NET_LWIP alternative is not visible in make menuconfig when
sandbox_defconfig is used.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
Kconfig | 41 ++++++++++++++++++++++++++++++++++++++
Makefile | 2 +-
common/Kconfig | 2 +-
common/spl/Kconfig | 1 +
drivers/dfu/Kconfig | 1 +
drivers/fastboot/Kconfig | 1 +
drivers/net/Kconfig | 1 +
drivers/net/phy/Kconfig | 2 +-
drivers/usb/gadget/Kconfig | 2 +-
net-lwip/Kconfig | 37 ++++++++++++++++++++++++++++++++++
net/Kconfig | 14 -------------
11 files changed, 86 insertions(+), 18 deletions(-)
create mode 100644 net-lwip/Kconfig
diff --git a/Kconfig b/Kconfig
index 82df59f176e..cfe2a6d3eac 100644
--- a/Kconfig
+++ b/Kconfig
@@ -745,7 +745,48 @@ source "dts/Kconfig"
source "env/Kconfig"
+choice
+ prompt "Networking stack"
+ default NET
+
+config NO_NET
+ bool "No networking support"
+
+config NET
+ bool "Legacy U-Boot networking stack"
+ imply NETDEVICES
+
+config NET_LWIP
+ bool "Use lwIP for networking stack"
+ imply NETDEVICES
+ depends on !SANDBOX
+ help
+ Include networking support based on the lwIP (lightweight IP)
+ TCP/IP stack (https://nongnu.org/lwip). This is a replacement for
+ the default U-Boot network stack and applications located in net/
+ and enabled via CONFIG_NET as well as other pieces of code that
+ depend on CONFIG_NET (such as cmd/net.c enabled via CONFIG_CMD_NET).
+ Therefore the two symbols CONFIG_NET and CONFIG_NET_LWIP are mutually
+ exclusive.
+
+endchoice
+
+if NET
source "net/Kconfig"
+endif
+
+if NET_LWIP
+source "net-lwip/Kconfig"
+endif
+
+config SYS_RX_ETH_BUFFER
+ int "Number of receive packet buffers"
+ default 4
+ help
+ Defines the number of Ethernet receive buffers. On some Ethernet
+ controllers it is recommended to set this value to 8 or even higher,
+ since all buffers can be full shortly after enabling the interface on
+ high Ethernet traffic.
source "drivers/Kconfig"
diff --git a/Makefile b/Makefile
index f8206b2e30a..ceb99a2698e 100644
--- a/Makefile
+++ b/Makefile
@@ -859,7 +859,7 @@ libs-$(CONFIG_OF_EMBED) += dts/
libs-y += env/
libs-y += lib/
libs-y += fs/
-libs-y += net/
+libs-$(CONFIG_NET) += net/
libs-y += disk/
libs-y += drivers/
libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
diff --git a/common/Kconfig b/common/Kconfig
index 5e3070e9253..807b726384d 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -424,7 +424,7 @@ config LOGF_FUNC_PAD
config LOG_SYSLOG
bool "Log output to syslog server"
- depends on NET
+ depends on NET || NET_LWIP
help
Enables a log driver which broadcasts log records via UDP port 514
to syslog servers.
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc1..f67f0a859db 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1055,6 +1055,7 @@ config SPL_DM_SPI_FLASH
config SPL_NET
bool "Support networking"
+ depends on !NET_LWIP
help
Enable support for network devices (such as Ethernet) in SPL.
This permits SPL to load U-Boot over a network link rather than
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0360d9da142..6405a23574e 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -20,6 +20,7 @@ config DFU_WRITE_ALT
config DFU_TFTP
bool "DFU via TFTP"
depends on NETDEVICES
+ depends on !NET_LWIP
select UPDATE_COMMON
select DFU_OVER_TFTP
help
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 70207573de2..1eb460f5a02 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -1,5 +1,6 @@
menu "Fastboot support"
depends on CMDLINE
+ depends on !NET_LWIP
config FASTBOOT
bool
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b2d7b499766..efc55e45ca8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -48,6 +48,7 @@ config DM_DSA
bool "Enable Driver Model for DSA switches"
depends on DM_MDIO
depends on PHY_FIXED
+ depends on !NET_LWIP
help
Enable driver model for DSA switches
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d96938eaba..738752d29c2 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -11,7 +11,7 @@ config MV88E6352_SWITCH
menuconfig PHYLIB
bool "Ethernet PHY (physical media interface) support"
- depends on NET
+ depends on NET || NET_LWIP
help
Enable Ethernet PHY (physical media interface) support.
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 4621a6fd5e6..03fe3bca197 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -224,7 +224,7 @@ endif # USB_GADGET_DOWNLOAD
config USB_ETHER
bool "USB Ethernet Gadget"
- depends on NET
+ depends on NET || NET_LWIP
default y if ARCH_SUNXI && USB_MUSB_GADGET
help
Creates an Ethernet network device through a USB peripheral
diff --git a/net-lwip/Kconfig b/net-lwip/Kconfig
new file mode 100644
index 00000000000..a0938964b51
--- /dev/null
+++ b/net-lwip/Kconfig
@@ -0,0 +1,37 @@
+#
+# Network configuration (with lwIP stack)
+#
+
+config LWIP_DEBUG
+ bool "Enable debug traces in the lwIP library"
+
+config LWIP_ASSERT
+ bool "Enable assertions in the lwIP library"
+
+config PROT_DHCP_LWIP
+ bool "DHCP support in lwIP"
+ depends on PROT_UDP_LWIP
+ help
+ Enable support for the DHCP protocol in lwIP.
+
+config PROT_DNS_LWIP
+ bool
+ depends on PROT_UDP_LWIP
+
+config PROT_RAW_LWIP
+ bool
+
+config PROT_TCP_LWIP
+ bool
+
+config PROT_UDP_LWIP
+ bool
+
+config BOOTDEV_ETH
+ bool "Enable bootdev for ethernet"
+ depends on BOOTSTD
+ default y
+ help
+ Provide a bootdev for ethernet so that is it possible to boot
+ an operating system over the network, using the PXE (Preboot
+ Execution Environment) protocol.
diff --git a/net/Kconfig b/net/Kconfig
index 5dff6336293..4929428d2a5 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -2,11 +2,6 @@
# Network configuration
#
-menuconfig NET
- bool "Networking support"
- default y
- imply NETDEVICES
-
if NET
config ARP_TIMEOUT
@@ -254,12 +249,3 @@ config IPV6
address and find it, it will force using IPv6 in the network stack.
endif # if NET
-
-config SYS_RX_ETH_BUFFER
- int "Number of receive packet buffers"
- default 4
- help
- Defines the number of Ethernet receive buffers. On some Ethernet
- controllers it is recommended to set this value to 8 or even higher,
- since all buffers can be full shortly after enabling the interface on
- high Ethernet traffic.
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 02/14] net: introduce alternative implementation as net-lwip/
2024-06-17 15:32 ` [PATCH v4 02/14] net: introduce alternative implementation as net-lwip/ Jerome Forissier
@ 2024-06-18 17:59 ` Tom Rini
2024-06-19 9:06 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Tom Rini @ 2024-06-18 17:59 UTC (permalink / raw)
To: Jerome Forissier
Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov,
Lukasz Majewski, Mattijs Korpershoek, Joe Hershberger,
Ramon Fried, Marek Vasut, Simon Glass, Jonas Karlman, Paul Barker,
Sean Anderson, Jesse Taube, Greg Malysa, Shengyu Qu, Andrew Davis,
Sumit Garg, Bryan Brattlof, Leon M. Busch-George, Ying Sun,
Heinrich Schuchardt, Joshua Watt, Rasmus Villemoes, Bin Meng,
Andre Przywara, Leo Yu-Chi Liang, Mayuresh Chitale,
Oleksandr Suvorov, Samuel Holland, Jaehoon Chung,
Ashok Reddy Soma, Ion Agorria, Quentin Schulz, Alexey Romanov,
Yang Xiwen, Neil Armstrong, Boon Khai Ng, Yanhong Wang,
Nicolas Frattaroli, Miquel Raynal, Baruch Siach
[-- Attachment #1: Type: text/plain, Size: 2452 bytes --]
On Mon, Jun 17, 2024 at 05:32:54PM +0200, Jerome Forissier wrote:
> Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
> adding a new net-lwip/ directory and the NET_LWIP symbol. Network
> support is either NO_NET, NET (legacy stack) or NET_LWIP. Subsequent
> commits will introduce the lwIP code, re-work the NETDEVICE integration
> and port some of the NET commands and features to lwIP.
>
> SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
> that are part of NET (such as arp_init(), arp_timeout_check(),
> arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
> added later.
>
> Similarly, DFU_TFTP and FASTBOOT are not compatible with NET_LWIP
> because of dependencies on net_loop(), tftp_timeout_ms,
> tftp_timeout_count_max and other NET things. Let's add a dependency on
> !NET_LWIP for now.
>
> As for SANDBOX, NET_LWIP cannot be used either because of strong
> assumptions on the network stack. Make NET_LWIP depend on !SANDBOX so
> that the NET_LWIP alternative is not visible in make menuconfig when
> sandbox_defconfig is used.
[snip]
> diff --git a/Kconfig b/Kconfig
> index 82df59f176e..cfe2a6d3eac 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -745,7 +745,48 @@ source "dts/Kconfig"
>
> source "env/Kconfig"
>
> +choice
> + prompt "Networking stack"
> + default NET
> +
> +config NO_NET
> + bool "No networking support"
> +
> +config NET
> + bool "Legacy U-Boot networking stack"
> + imply NETDEVICES
> +
> +config NET_LWIP
> + bool "Use lwIP for networking stack"
> + imply NETDEVICES
> + depends on !SANDBOX
> + help
> + Include networking support based on the lwIP (lightweight IP)
> + TCP/IP stack (https://nongnu.org/lwip). This is a replacement for
> + the default U-Boot network stack and applications located in net/
> + and enabled via CONFIG_NET as well as other pieces of code that
> + depend on CONFIG_NET (such as cmd/net.c enabled via CONFIG_CMD_NET).
> + Therefore the two symbols CONFIG_NET and CONFIG_NET_LWIP are mutually
> + exclusive.
> +
> +endchoice
For ease of reviewability the next patch in the series should change all
of the configs with '# CONFIG_NET is not set' to 'CONFIG_NO_NET=y' so
that they functionally don't change. It's 105 files and so while it will
be folded in when lwIP is ready for merge, keeping it separate for now
will make review easier.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 02/14] net: introduce alternative implementation as net-lwip/
2024-06-18 17:59 ` Tom Rini
@ 2024-06-19 9:06 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-19 9:06 UTC (permalink / raw)
To: Tom Rini
Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov,
Lukasz Majewski, Mattijs Korpershoek, Joe Hershberger,
Ramon Fried, Marek Vasut, Simon Glass, Jonas Karlman, Paul Barker,
Sean Anderson, Jesse Taube, Greg Malysa, Shengyu Qu, Andrew Davis,
Sumit Garg, Bryan Brattlof, Leon M. Busch-George, Ying Sun,
Heinrich Schuchardt, Joshua Watt, Rasmus Villemoes, Bin Meng,
Andre Przywara, Leo Yu-Chi Liang, Mayuresh Chitale,
Oleksandr Suvorov, Samuel Holland, Jaehoon Chung,
Ashok Reddy Soma, Ion Agorria, Quentin Schulz, Alexey Romanov,
Yang Xiwen, Neil Armstrong, Boon Khai Ng, Yanhong Wang,
Nicolas Frattaroli, Miquel Raynal, Baruch Siach
On 6/18/24 19:59, Tom Rini wrote:
> On Mon, Jun 17, 2024 at 05:32:54PM +0200, Jerome Forissier wrote:
>
>> Prepare the introduction of the lwIP (lightweight IP) TCP/IP stack by
>> adding a new net-lwip/ directory and the NET_LWIP symbol. Network
>> support is either NO_NET, NET (legacy stack) or NET_LWIP. Subsequent
>> commits will introduce the lwIP code, re-work the NETDEVICE integration
>> and port some of the NET commands and features to lwIP.
>>
>> SPL_NET cannot be enabled when NET_LWIP=y. SPL_NET pulls some symbols
>> that are part of NET (such as arp_init(), arp_timeout_check(),
>> arp_receive(), net_arp_wait_packet_ip()). lwIP support in SPL may be
>> added later.
>>
>> Similarly, DFU_TFTP and FASTBOOT are not compatible with NET_LWIP
>> because of dependencies on net_loop(), tftp_timeout_ms,
>> tftp_timeout_count_max and other NET things. Let's add a dependency on
>> !NET_LWIP for now.
>>
>> As for SANDBOX, NET_LWIP cannot be used either because of strong
>> assumptions on the network stack. Make NET_LWIP depend on !SANDBOX so
>> that the NET_LWIP alternative is not visible in make menuconfig when
>> sandbox_defconfig is used.
> [snip]
>> diff --git a/Kconfig b/Kconfig
>> index 82df59f176e..cfe2a6d3eac 100644
>> --- a/Kconfig
>> +++ b/Kconfig
>> @@ -745,7 +745,48 @@ source "dts/Kconfig"
>>
>> source "env/Kconfig"
>>
>> +choice
>> + prompt "Networking stack"
>> + default NET
>> +
>> +config NO_NET
>> + bool "No networking support"
>> +
>> +config NET
>> + bool "Legacy U-Boot networking stack"
>> + imply NETDEVICES
>> +
>> +config NET_LWIP
>> + bool "Use lwIP for networking stack"
>> + imply NETDEVICES
>> + depends on !SANDBOX
>> + help
>> + Include networking support based on the lwIP (lightweight IP)
>> + TCP/IP stack (https://nongnu.org/lwip). This is a replacement for
>> + the default U-Boot network stack and applications located in net/
>> + and enabled via CONFIG_NET as well as other pieces of code that
>> + depend on CONFIG_NET (such as cmd/net.c enabled via CONFIG_CMD_NET).
>> + Therefore the two symbols CONFIG_NET and CONFIG_NET_LWIP are mutually
>> + exclusive.
>> +
>> +endchoice
>
> For ease of reviewability the next patch in the series should change all
> of the configs with '# CONFIG_NET is not set' to 'CONFIG_NO_NET=y' so
> that they functionally don't change. It's 105 files and so while it will
> be folded in when lwIP is ready for merge, keeping it separate for now
> will make review easier.
OK, done in v6.
Thanks,
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH v4 03/14] net: split include/net.h into net{, -common, -legacy, -lwip}.h
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
2024-06-17 15:32 ` [PATCH v4 01/14] flash: prefix error codes with FL_ Jerome Forissier
2024-06-17 15:32 ` [PATCH v4 02/14] net: introduce alternative implementation as net-lwip/ Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-17 15:32 ` [PATCH v4 04/14] net-lwip: build lwIP Jerome Forissier
` (13 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Joe Hershberger, Ramon Fried, Simon Glass, Sumit Garg,
Heinrich Schuchardt, Andrew Davis, Marek Vasut, Bryan Brattlof,
Jesse Taube, Leon M. Busch-George, Masahisa Kojima, Sean Anderson
Make net.h a wrapper which includes net-common.h and either
net-legacy.h or net-lwip.h based on NET_LWIP.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
Makefile | 4 +-
include/net-common.h | 408 +++++++++++++++++++
include/net-legacy.h | 649 +++++++++++++++++++++++++++++
include/net-lwip.h | 14 +
include/net.h | 944 +------------------------------------------
5 files changed, 1078 insertions(+), 941 deletions(-)
create mode 100644 include/net-common.h
create mode 100644 include/net-legacy.h
create mode 100644 include/net-lwip.h
diff --git a/Makefile b/Makefile
index ceb99a2698e..0fe1623c550 100644
--- a/Makefile
+++ b/Makefile
@@ -836,7 +836,9 @@ UBOOTINCLUDE := \
-I$(srctree)/arch/arm/thumb1/include)) \
-I$(srctree)/arch/$(ARCH)/include \
-include $(srctree)/include/linux/kconfig.h \
- -I$(srctree)/dts/upstream/include
+ -I$(srctree)/dts/upstream/include \
+ $(if $(CONFIG_NET_LWIP), -I$(srctree)/lib/lwip/lwip/src/include \
+ -I$(srctree)/lib/lwip/u-boot)
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
diff --git a/include/net-common.h b/include/net-common.h
new file mode 100644
index 00000000000..77bdf17c6cd
--- /dev/null
+++ b/include/net-common.h
@@ -0,0 +1,408 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __NET_COMMON_H__
+#define __NET_COMMON_H__
+
+#include <asm/cache.h>
+#include <command.h>
+#include <env.h>
+#include <hexdump.h>
+#include <linux/if_ether.h>
+#include <linux/types.h>
+#include <time.h>
+
+#define DEBUG_NET_PKT_TRACE 0 /* Trace all packet data */
+
+/*
+ * 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
+
+/* IPv4 addresses are always 32 bits in size */
+struct in_addr {
+ __be32 s_addr;
+};
+
+#define PROT_IP 0x0800 /* IP protocol */
+#define PROT_ARP 0x0806 /* IP ARP protocol */
+#define PROT_WOL 0x0842 /* ether-wake WoL protocol */
+#define PROT_RARP 0x8035 /* IP ARP protocol */
+#define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */
+#define PROT_IPV6 0x86dd /* IPv6 over bluebook */
+#define PROT_PPP_SES 0x8864 /* PPPoE session messages */
+#define PROT_NCSI 0x88f8 /* NC-SI control packets */
+
+#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
+#define IPPROTO_TCP 6 /* Transmission Control Protocol */
+#define IPPROTO_UDP 17 /* User Datagram Protocol */
+
+#define IP_OFFS 0x1fff /* ip offset *= 8 */
+#define IP_FLAGS 0xe000 /* first 3 bits */
+#define IP_FLAGS_RES 0x8000 /* reserved */
+#define IP_FLAGS_DFRAG 0x4000 /* don't fragments */
+#define IP_FLAGS_MFRAG 0x2000 /* more fragments */
+
+#define IP_HDR_SIZE (sizeof(struct ip_hdr))
+
+#define IP_MIN_FRAG_DATAGRAM_SIZE (IP_HDR_SIZE + 8)
+
+
+/*
+ * Internet Protocol (IP) + UDP header.
+ */
+struct ip_udp_hdr {
+ u8 ip_hl_v; /* header length and version */
+ u8 ip_tos; /* type of service */
+ u16 ip_len; /* total length */
+ u16 ip_id; /* identification */
+ u16 ip_off; /* fragment offset field */
+ u8 ip_ttl; /* time to live */
+ u8 ip_p; /* protocol */
+ u16 ip_sum; /* checksum */
+ struct in_addr ip_src; /* Source IP address */
+ struct in_addr ip_dst; /* Destination IP address */
+ u16 udp_src; /* UDP source port */
+ u16 udp_dst; /* UDP destination port */
+ u16 udp_len; /* Length of UDP packet */
+ u16 udp_xsum; /* Checksum */
+} __attribute__((packed));
+
+#define IP_UDP_HDR_SIZE (sizeof(struct ip_udp_hdr))
+#define UDP_HDR_SIZE (IP_UDP_HDR_SIZE - IP_HDR_SIZE)
+
+/* 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)
+
+# define ARP_ETHER 1 /* Ethernet hardware address */
+
+/*
+ * Maximum packet size; used to allocate packet storage. Use
+ * the maxium Ethernet frame size as specified by the Ethernet
+ * standard including the 802.1Q tag (VLAN tagging).
+ * maximum packet size = 1522
+ * maximum packet size and multiple of 32 bytes = 1536
+ */
+#define PKTSIZE 1522
+#ifndef CONFIG_DM_DSA
+#define PKTSIZE_ALIGN 1536
+#else
+/* Maximum DSA tagging overhead (headroom and/or tailroom) */
+#define DSA_MAX_OVR 256
+#define PKTSIZE_ALIGN (1536 + DSA_MAX_OVR)
+#endif
+
+extern int net_restart_wrap; /* Tried all network devices */
+extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */
+
+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);
+
+/*
+ * 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);
+
+/**
+ * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
+ *
+ * This sets up an environment variable with the given MAC address (@enetaddr).
+ * The environment variable to be set is defined by <@base_name><@index>addr.
+ * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
+ * eth1addr, etc.
+ *
+ * @base_name: Base name for variable, typically "eth"
+ * @index: Index of interface being updated (>=0)
+ * @enetaddr: Pointer to MAC address to put into the variable
+ * Return: 0 if OK, other value on error
+ */
+int eth_env_set_enetaddr_by_index(const char *base_name, int index,
+ uchar *enetaddr);
+
+int eth_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 */
+
+static inline void net_send_packet(uchar *pkt, int len)
+{
+ if (DEBUG_NET_PKT_TRACE)
+ print_hex_dump_bytes("tx: ", DUMP_PREFIX_OFFSET, pkt, len);
+ /* Currently no way to return errors from eth_send() */
+ (void) eth_send(pkt, len);
+}
+
+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 */
+unsigned char *eth_get_ethaddr(void); /* get the current device MAC */
+int eth_get_dev_index(void);
+int eth_rx(void); /* Check for received packets */
+void eth_halt(void); /* stop SCC */
+const char *eth_get_name(void);
+int eth_get_dev_index(void);
+int eth_init_state_only(void); /* Set active 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 */
+
+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;
+};
+
+struct ethernet_hdr {
+ u8 et_dest[ARP_HLEN]; /* Destination node */
+ u8 et_src[ARP_HLEN]; /* Source node */
+ u16 et_protlen; /* Protocol or length */
+} __attribute__((packed));
+
+/* Ethernet header size */
+#define ETHER_HDR_SIZE (sizeof(struct ethernet_hdr))
+
+/**
+ * is_zero_ethaddr - Determine if give Ethernet address is all zeros.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is all zeroes.
+ */
+static inline int is_zero_ethaddr(const u8 *addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+/**
+ * is_multicast_ethaddr - Determine if the Ethernet address is a multicast.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a multicast address.
+ * By definition the broadcast address is also a multicast address.
+ */
+static inline int is_multicast_ethaddr(const u8 *addr)
+{
+ return 0x01 & addr[0];
+}
+
+/*
+ * is_broadcast_ethaddr - Determine if the Ethernet address is broadcast
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is the broadcast address.
+ */
+static inline int is_broadcast_ethaddr(const u8 *addr)
+{
+ return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) ==
+ 0xff;
+}
+
+/*
+ * is_valid_ethaddr - Determine if the given Ethernet address is valid
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
+ * a multicast address, and is not FF:FF:FF:FF:FF:FF.
+ *
+ * Return true if the address is valid.
+ */
+static inline int is_valid_ethaddr(const u8 *addr)
+{
+ /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
+ * explicitly check for it here. */
+ return !is_multicast_ethaddr(addr) && !is_zero_ethaddr(addr);
+}
+
+/**
+ * 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);
+
+/**
+ * string_to_ip() - Convert a string to ip address
+ *
+ * Implemented in lib/net_utils.c (built unconditionally)
+ *
+ * @s: Input string to parse
+ * @return: in_addr struct containing the parsed IP address
+ */
+struct in_addr string_to_ip(const char *s);
+
+/* Processes a received packet */
+void net_process_received_packet(uchar *in_packet, int len);
+
+/**
+ * update_tftp - Update firmware over TFTP (via DFU)
+ *
+ * This function updates board's firmware via TFTP
+ *
+ * @param addr - memory address where data is stored
+ * @param interface - the DFU medium name - e.g. "mmc"
+ * @param devstring - the DFU medium number - e.g. "1"
+ *
+ * Return: - 0 on success, other value on failure
+ */
+int update_tftp(ulong addr, char *interface, char *devstring);
+
+/**
+ * env_get_ip() - Convert an environment value to to an ip address
+ *
+ * @var: Environment variable to convert. The value of this variable must be
+ * in the format format a.b.c.d, where each value is a decimal number from
+ * 0 to 255
+ * Return: IP address, or 0 if invalid
+ */
+static inline struct in_addr env_get_ip(char *var)
+{
+ return string_to_ip(env_get(var));
+}
+
+int net_init(void);
+
+/**
+ * dhcp_run() - Run DHCP on the current ethernet device
+ *
+ * This sets the autoload variable, then puts it back to similar to its original
+ * state (y, n or unset).
+ *
+ * @addr: Address to load the file into (0 if @autoload is false)
+ * @fname: Filename of file to load (NULL if @autoload is false or to use the
+ * default filename)
+ * @autoload: true to load the file, false to just get the network IP
+ * @return 0 if OK, -EINVAL if the environment failed, -ENOENT if ant file was
+ * not found
+ */
+int dhcp_run(ulong addr, const char *fname, bool autoload);
+
+/**
+ * do_tftpb - Run the tftpboot command
+ *
+ * @cmdtp: Command information for tftpboot
+ * @flag: Command flags (CMD_FLAG_...)
+ * @argc: Number of arguments
+ * @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[]);
+
+/**
+ * wget_with_dns() - runs dns host IP address resulution before wget
+ *
+ * @dst_addr: destination address to download the file
+ * @uri: uri string of target file of wget
+ * Return: downloaded file size, negative if failed
+ */
+int wget_with_dns(ulong dst_addr, char *uri);
+/**
+ * wget_validate_uri() - varidate the uri
+ *
+ * @uri: uri string of target file of wget
+ * Return: true if uri is valid, false if uri is invalid
+ */
+bool wget_validate_uri(char *uri);
+//int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+
+#endif /* __NET_COMMON_H__ */
diff --git a/include/net-legacy.h b/include/net-legacy.h
new file mode 100644
index 00000000000..0c0c873005a
--- /dev/null
+++ b/include/net-legacy.h
@@ -0,0 +1,649 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * LiMon Monitor (LiMon) - Network.
+ *
+ * Copyright 1994 - 2000 Neil Russell.
+ * (See License)
+ *
+ * History
+ * 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added
+ */
+
+#ifndef __NET_LEGACY_H__
+#define __NET_LEGACY_H__
+
+#include <linux/types.h>
+#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
+#include <log.h>
+#include <time.h>
+#include <linux/if_ether.h>
+#include <rand.h>
+
+struct bd_info;
+struct cmd_tbl;
+struct udevice;
+
+#define DEBUG_LL_STATE 0 /* Link local state machine changes */
+#define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */
+#define DEBUG_NET_PKT 0 /* Packets on info on the network at large */
+#define DEBUG_INT_STATE 0 /* Internal network state changes */
+
+/* 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)
+
+/**
+ * An incoming packet handler.
+ * @param pkt pointer to the application packet
+ * @param dport destination UDP port
+ * @param sip source IP address
+ * @param sport source UDP port
+ * @param len packet length
+ */
+typedef void rxhand_f(uchar *pkt, unsigned dport,
+ struct in_addr sip, unsigned sport,
+ unsigned len);
+
+/**
+ * An incoming ICMP packet handler.
+ * @param type ICMP type
+ * @param code ICMP code
+ * @param dport destination UDP port
+ * @param sip source IP address
+ * @param sport source UDP port
+ * @param pkt pointer to the ICMP packet data
+ * @param len packet length
+ */
+typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport,
+ struct in_addr sip, unsigned sport, uchar *pkt, unsigned len);
+
+/*
+ * A timeout handler. Called after time interval has expired.
+ */
+typedef void thand_f(void);
+
+/*
+ * 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);
+/* Used only when NetConsole is enabled */
+int eth_is_active(struct udevice *dev); /* Test device for active state */
+void eth_halt_state_only(void); /* Set passive state */
+
+
+/**
+ * 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
+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);
+
+/**********************************************************************/
+/*
+ * Protocol headers.
+ */
+
+#define ETH_FCS_LEN 4 /* Octets in the FCS */
+
+struct e802_hdr {
+ u8 et_dest[ARP_HLEN]; /* Destination node */
+ u8 et_src[ARP_HLEN]; /* Source node */
+ u16 et_protlen; /* Protocol or length */
+ u8 et_dsap; /* 802 DSAP */
+ u8 et_ssap; /* 802 SSAP */
+ u8 et_ctl; /* 802 control */
+ u8 et_snap1; /* SNAP */
+ u8 et_snap2;
+ u8 et_snap3;
+ u16 et_prot; /* 802 protocol */
+} __attribute__((packed));
+
+/* 802 + SNAP + ethernet header size */
+#define E802_HDR_SIZE (sizeof(struct e802_hdr))
+
+/*
+ * Virtual LAN Ethernet header
+ */
+struct vlan_ethernet_hdr {
+ u8 vet_dest[ARP_HLEN]; /* Destination node */
+ u8 vet_src[ARP_HLEN]; /* Source node */
+ u16 vet_vlan_type; /* PROT_VLAN */
+ u16 vet_tag; /* TAG of VLAN */
+ u16 vet_type; /* protocol type */
+} __attribute__((packed));
+
+/* VLAN Ethernet header size */
+#define VLAN_ETHER_HDR_SIZE (sizeof(struct vlan_ethernet_hdr))
+
+/*
+ * Internet Protocol (IP) header.
+ */
+struct ip_hdr {
+ u8 ip_hl_v; /* header length and version */
+ u8 ip_tos; /* type of service */
+ u16 ip_len; /* total length */
+ u16 ip_id; /* identification */
+ u16 ip_off; /* fragment offset field */
+ u8 ip_ttl; /* time to live */
+ u8 ip_p; /* protocol */
+ u16 ip_sum; /* checksum */
+ struct in_addr ip_src; /* Source IP address */
+ struct in_addr ip_dst; /* Destination IP address */
+} __attribute__((packed));
+
+#define IP_OFFS 0x1fff /* ip offset *= 8 */
+#define IP_FLAGS 0xe000 /* first 3 bits */
+#define IP_FLAGS_RES 0x8000 /* reserved */
+#define IP_FLAGS_DFRAG 0x4000 /* don't fragments */
+#define IP_FLAGS_MFRAG 0x2000 /* more fragments */
+
+#define IP_HDR_SIZE (sizeof(struct ip_hdr))
+
+#define IP_MIN_FRAG_DATAGRAM_SIZE (IP_HDR_SIZE + 8)
+
+/*
+ * Address Resolution Protocol (ARP) header.
+ */
+struct arp_hdr {
+ u16 ar_hrd; /* Format of hardware address */
+# define ARP_ETHER 1 /* Ethernet hardware address */
+ u16 ar_pro; /* Format of protocol address */
+ u8 ar_hln; /* Length of hardware address */
+ u8 ar_pln; /* Length of protocol address */
+# define ARP_PLEN 4
+ u16 ar_op; /* Operation */
+# define ARPOP_REQUEST 1 /* Request to resolve address */
+# define ARPOP_REPLY 2 /* Response to previous request */
+
+# define RARPOP_REQUEST 3 /* Request to resolve address */
+# define RARPOP_REPLY 4 /* Response to previous request */
+
+ /*
+ * The remaining fields are variable in size, according to
+ * the sizes above, and are defined as appropriate for
+ * specific hardware/protocol combinations.
+ */
+ u8 ar_data[0];
+#define ar_sha ar_data[0]
+#define ar_spa ar_data[ARP_HLEN]
+#define ar_tha ar_data[ARP_HLEN + ARP_PLEN]
+#define ar_tpa ar_data[ARP_HLEN + ARP_PLEN + ARP_HLEN]
+#if 0
+ u8 ar_sha[]; /* Sender hardware address */
+ u8 ar_spa[]; /* Sender protocol address */
+ u8 ar_tha[]; /* Target hardware address */
+ u8 ar_tpa[]; /* Target protocol address */
+#endif /* 0 */
+} __attribute__((packed));
+
+#define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */
+
+/*
+ * ICMP stuff (just enough to handle (host) redirect messages)
+ */
+#define ICMP_ECHO_REPLY 0 /* Echo reply */
+#define ICMP_NOT_REACH 3 /* Detination unreachable */
+#define ICMP_REDIRECT 5 /* Redirect (change route) */
+#define ICMP_ECHO_REQUEST 8 /* Echo request */
+
+/* Codes for REDIRECT. */
+#define ICMP_REDIR_NET 0 /* Redirect Net */
+#define ICMP_REDIR_HOST 1 /* Redirect Host */
+
+/* Codes for NOT_REACH */
+#define ICMP_NOT_REACH_PORT 3 /* Port unreachable */
+
+struct icmp_hdr {
+ u8 type;
+ u8 code;
+ u16 checksum;
+ union {
+ struct {
+ u16 id;
+ u16 sequence;
+ } echo;
+ u32 gateway;
+ struct {
+ u16 unused;
+ u16 mtu;
+ } frag;
+ u8 data[0];
+ } un;
+} __attribute__((packed));
+
+#define ICMP_HDR_SIZE (sizeof(struct icmp_hdr))
+#define IP_ICMP_HDR_SIZE (IP_HDR_SIZE + ICMP_HDR_SIZE)
+
+/*
+ * Maximum packet size; used to allocate packet storage. Use
+ * the maxium Ethernet frame size as specified by the Ethernet
+ * standard including the 802.1Q tag (VLAN tagging).
+ * maximum packet size = 1522
+ * maximum packet size and multiple of 32 bytes = 1536
+ */
+#define PKTSIZE 1522
+#ifndef CONFIG_DM_DSA
+#define PKTSIZE_ALIGN 1536
+#else
+/* Maximum DSA tagging overhead (headroom and/or tailroom) */
+#define DSA_MAX_OVR 256
+#define PKTSIZE_ALIGN (1536 + DSA_MAX_OVR)
+#endif
+
+/*
+ * Maximum receive ring size; that is, the number of packets
+ * we can buffer before overflow happens. Basically, this just
+ * needs to be enough to prevent a packet being discarded while
+ * we are processing the previous one.
+ */
+#define RINGSZ 4
+#define RINGSZ_LOG2 2
+
+/**********************************************************************/
+/*
+ * Globals.
+ *
+ * Note:
+ *
+ * All variables of type struct in_addr are stored in NETWORK byte order
+ * (big endian).
+ */
+
+/* net.c */
+/** BOOTP EXTENTIONS **/
+extern struct in_addr net_gateway; /* Our gateway IP address */
+extern struct in_addr net_netmask; /* Our subnet mask (0 = unknown) */
+/* Our Domain Name Server (0 = unknown) */
+extern struct in_addr net_dns_server;
+#if defined(CONFIG_BOOTP_DNS2)
+/* Our 2nd Domain Name Server (0 = unknown) */
+extern struct in_addr net_dns_server2;
+#endif
+extern char net_nis_domain[32]; /* Our IS domain */
+extern char net_hostname[32]; /* Our hostname */
+#ifdef CONFIG_NET
+extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */
+#endif
+/* 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 */
+extern ushort net_our_vlan; /* Our VLAN */
+extern ushort net_native_vlan; /* Our Native VLAN */
+
+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
+};
+
+extern char net_boot_file_name[1024];/* Boot File name */
+/* Indicates whether the file name was specified on the command line */
+extern bool net_boot_file_name_explicit;
+/* The actual transferred size of the bootfile (in bytes) */
+extern u32 net_boot_file_size;
+/* Boot file size in blocks as reported by the DHCP server */
+extern u32 net_boot_file_expected_size_in_blocks;
+
+#if defined(CONFIG_CMD_DNS)
+extern char *net_dns_resolve; /* The host to resolve */
+extern char *net_dns_env_var; /* the env var to put the ip into */
+#endif
+
+#if defined(CONFIG_CMD_PING)
+extern struct in_addr net_ping_ip; /* the ip address to ping */
+#endif
+
+#if defined(CONFIG_CMD_CDP)
+/* when CDP completes these hold the return values */
+extern ushort cdp_native_vlan; /* CDP returned native VLAN */
+extern ushort cdp_appliance_vlan; /* CDP returned appliance VLAN */
+
+/*
+ * Check for a CDP packet by examining the received MAC address field
+ */
+static inline int is_cdp_packet(const uchar *ethaddr)
+{
+ extern const u8 net_cdp_ethaddr[ARP_HLEN];
+
+ return memcmp(ethaddr, net_cdp_ethaddr, ARP_HLEN) == 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_SNTP)
+extern struct in_addr net_ntp_server; /* the ip address to NTP */
+extern int net_ntp_time_offset; /* offset time from UTC */
+#endif
+
+int net_loop(enum proto_t);
+
+/* Load failed. Start again. */
+int net_start_again(void);
+
+/* Get size of the ethernet header when we send */
+int net_eth_hdr_size(void);
+
+/* Set ethernet header; returns the size of the header */
+int net_set_ether(uchar *xet, const uchar *dest_ethaddr, uint prot);
+int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
+
+/* Set IP header */
+void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source,
+ u16 pkt_len, u8 proto);
+void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport,
+ int sport, int len);
+
+/**
+ * compute_ip_checksum() - Compute IP checksum
+ *
+ * @addr: Address to check (must be 16-bit aligned)
+ * @nbytes: Number of bytes to check (normally a multiple of 2)
+ * Return: 16-bit IP checksum
+ */
+unsigned compute_ip_checksum(const void *addr, unsigned nbytes);
+
+/**
+ * add_ip_checksums() - add two IP checksums
+ *
+ * @offset: Offset of first sum (if odd we do a byte-swap)
+ * @sum: First checksum
+ * @new_sum: New checksum to add
+ * Return: updated 16-bit IP checksum
+ */
+unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
+
+/**
+ * ip_checksum_ok() - check if a checksum is correct
+ *
+ * This works by making sure the checksum sums to 0
+ *
+ * @addr: Address to check (must be 16-bit aligned)
+ * @nbytes: Number of bytes to check (normally a multiple of 2)
+ * Return: true if the checksum matches, false if not
+ */
+int ip_checksum_ok(const void *addr, unsigned nbytes);
+
+/* Callbacks */
+rxhand_f *net_get_udp_handler(void); /* Get UDP RX packet handler */
+void net_set_udp_handler(rxhand_f *); /* Set UDP RX packet handler */
+rxhand_f *net_get_arp_handler(void); /* Get ARP RX packet handler */
+void net_set_arp_handler(rxhand_f *); /* Set ARP RX packet handler */
+bool arp_is_waiting(void); /* Waiting for ARP reply? */
+void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
+void net_set_timeout_handler(ulong, thand_f *);/* Set timeout handler */
+
+/* Network loop state */
+enum net_loop_state {
+ NETLOOP_CONTINUE,
+ NETLOOP_RESTART,
+ NETLOOP_SUCCESS,
+ NETLOOP_FAIL
+};
+extern enum net_loop_state net_state;
+
+static inline void net_set_state(enum net_loop_state state)
+{
+ debug_cond(DEBUG_INT_STATE, "--- NetState set to %d\n", state);
+ net_state = state;
+}
+
+/*
+ * net_get_async_tx_pkt_buf - Get a packet buffer that is not in use for
+ * sending an asynchronous reply
+ *
+ * returns - ptr to packet buffer
+ */
+uchar * net_get_async_tx_pkt_buf(void);
+
+/**
+ * net_send_ip_packet() - Transmit "net_tx_packet" as UDP or TCP packet,
+ * send ARP request if needed (ether will be populated)
+ * @ether: Raw packet buffer
+ * @dest: IP address to send the datagram to
+ * @dport: Destination UDP port
+ * @sport: Source UDP port
+ * @payload_len: Length of data after the UDP header
+ * @action: TCP action to be performed
+ * @tcp_seq_num: TCP sequence number of this transmission
+ * @tcp_ack_num: TCP stream acknolegement number
+ *
+ * Return: 0 on success, other value on failure
+ */
+int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
+ int payload_len, int proto, u8 action, u32 tcp_seq_num,
+ u32 tcp_ack_num);
+/**
+ * net_send_tcp_packet() - Transmit TCP packet.
+ * @payload_len: length of payload
+ * @dport: Destination TCP port
+ * @sport: Source TCP port
+ * @action: TCP action to be performed
+ * @tcp_seq_num: TCP sequence number of this transmission
+ * @tcp_ack_num: TCP stream acknolegement number
+ *
+ * Return: 0 on success, other value on failure
+ */
+int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action,
+ u32 tcp_seq_num, u32 tcp_ack_num);
+int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport,
+ int sport, int payload_len);
+
+#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
+void nc_start(void);
+int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
+ unsigned src_port, unsigned len);
+#endif
+
+static __always_inline int eth_is_on_demand_init(void)
+{
+#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
+ extern enum proto_t net_loop_last_protocol;
+
+ return net_loop_last_protocol != NETCONS;
+#else
+ return 1;
+#endif
+}
+
+static inline void eth_set_last_protocol(int protocol)
+{
+#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
+ extern enum proto_t net_loop_last_protocol;
+
+ net_loop_last_protocol = protocol;
+#endif
+}
+
+/*
+ * Check if autoload is enabled. If so, use either NFS or TFTP to download
+ * the boot file.
+ */
+void net_auto_load(void);
+
+/*
+ * The following functions are a bit ugly, but necessary to deal with
+ * alignment restrictions on ARM.
+ *
+ * We're using inline functions, which had the smallest memory
+ * footprint in our tests.
+ */
+/* return IP *in network byteorder* */
+static inline struct in_addr net_read_ip(void *from)
+{
+ struct in_addr ip;
+
+ memcpy((void *)&ip, (void *)from, sizeof(ip));
+ return ip;
+}
+
+/* return ulong *in network byteorder* */
+static inline u32 net_read_u32(void *from)
+{
+ u32 l;
+
+ memcpy((void *)&l, (void *)from, sizeof(l));
+ return l;
+}
+
+/* write IP *in network byteorder* */
+static inline void net_write_ip(void *to, struct in_addr ip)
+{
+ memcpy(to, (void *)&ip, sizeof(ip));
+}
+
+/* copy IP */
+static inline void net_copy_ip(void *to, void *from)
+{
+ memcpy((void *)to, from, sizeof(struct in_addr));
+}
+
+/* copy ulong */
+static inline void net_copy_u32(void *to, void *from)
+{
+ memcpy((void *)to, (void *)from, sizeof(u32));
+}
+
+/**
+ * net_random_ethaddr - Generate software assigned random Ethernet address
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Generate a random Ethernet address (MAC) that is not multicast
+ * and has the local assigned bit set.
+ */
+static inline void net_random_ethaddr(uchar *addr)
+{
+ int i;
+ unsigned int seed = get_ticks();
+
+ for (i = 0; i < 6; i++)
+ addr[i] = rand_r(&seed);
+
+ addr[0] &= 0xfe; /* clear multicast bit */
+ addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
+}
+
+/* Convert an IP address to a string */
+void ip_to_string(struct in_addr x, char *s);
+
+/**
+ * string_to_ip() - Convert a string to ip address
+ *
+ * Implemented in lib/net_utils.c (built unconditionally)
+ *
+ * @s: Input string to parse
+ * @return: in_addr struct containing the parsed IP address
+ */
+struct in_addr string_to_ip(const char *s);
+
+/* Convert a VLAN id to a string */
+void vlan_to_string(ushort x, char *s);
+
+/* Convert a string to a vlan id */
+ushort string_to_vlan(const char *s);
+
+/* read a VLAN id from an environment variable */
+ushort env_get_vlan(char *);
+
+/* copy a filename (allow for "..." notation, limit length) */
+void copy_filename(char *dst, const char *src, int size);
+
+/* check if serverip is specified in filename from the command line */
+int is_serverip_in_cmd(void);
+
+/**
+ * net_parse_bootfile - Parse the bootfile env var / cmd line param
+ *
+ * @param ipaddr - a pointer to the ipaddr to populate if included in bootfile
+ * @param filename - a pointer to the string to save the filename part
+ * @param max_len - The longest - 1 that the filename part can be
+ *
+ * return 1 if parsed, 0 if bootfile is empty
+ */
+int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len);
+
+/**
+ * reset_phy() - Reset the Ethernet PHY
+ *
+ * This should be implemented by boards if CONFIG_RESET_PHY_R is enabled
+ */
+void reset_phy(void);
+
+#if CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP)
+/**
+ * eth_set_enable_bootdevs() - Enable or disable binding of Ethernet bootdevs
+ *
+ * These get in the way of bootstd testing, so are normally disabled by tests.
+ * This provide control of this setting. It only affects binding of Ethernet
+ * devices, so if that has already happened, this flag does nothing.
+ *
+ * @enable: true to enable binding of bootdevs when binding new Ethernet
+ * devices, false to disable it
+ */
+void eth_set_enable_bootdevs(bool enable);
+#else
+static inline void eth_set_enable_bootdevs(bool enable) {}
+#endif
+
+#endif /* __NET_LEGACY_H__ */
diff --git a/include/net-lwip.h b/include/net-lwip.h
new file mode 100644
index 00000000000..f5c743b8d11
--- /dev/null
+++ b/include/net-lwip.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __NET_LWIP_H__
+#define __NET_LWIP_H__
+
+#include <lwip/ip4.h>
+#include <lwip/netif.h>
+
+struct netif *net_lwip_new_netif(void);
+struct netif *net_lwip_new_netif_noip(void);
+void net_lwip_remove_netif(struct netif *netif);
+struct netif *net_lwip_get_netif(void);
+
+#endif /* __NET_LWIP_H__ */
diff --git a/include/net.h b/include/net.h
index ac511eab103..afa46f239ee 100644
--- a/include/net.h
+++ b/include/net.h
@@ -1,950 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * LiMon Monitor (LiMon) - Network.
- *
- * Copyright 1994 - 2000 Neil Russell.
- * (See License)
- *
- * History
- * 9/16/00 bor adapted to TQM823L/STK8xxL board, RARP/TFTP boot added
- */
#ifndef __NET_H__
#define __NET_H__
-#include <linux/types.h>
-#include <asm/cache.h>
-#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
-#include <env.h>
-#include <hexdump.h>
-#include <log.h>
-#include <time.h>
-#include <linux/if_ether.h>
-#include <rand.h>
+#include <net-common.h>
-struct bd_info;
-struct cmd_tbl;
-struct udevice;
-
-#define DEBUG_LL_STATE 0 /* Link local state machine changes */
-#define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */
-#define DEBUG_NET_PKT 0 /* Packets on info on the network at large */
-#define DEBUG_INT_STATE 0 /* Internal network state changes */
-#define DEBUG_NET_PKT_TRACE 0 /* Trace all packet data */
-
-/*
- * 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;
-};
-
-/**
- * do_tftpb - Run the tftpboot command
- *
- * @cmdtp: Command information for tftpboot
- * @flag: Command flags (CMD_FLAG_...)
- * @argc: Number of arguments
- * @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[]);
-
-/**
- * dhcp_run() - Run DHCP on the current ethernet device
- *
- * This sets the autoload variable, then puts it back to similar to its original
- * state (y, n or unset).
- *
- * @addr: Address to load the file into (0 if @autoload is false)
- * @fname: Filename of file to load (NULL if @autoload is false or to use the
- * default filename)
- * @autoload: true to load the file, false to just get the network IP
- * @return 0 if OK, -EINVAL if the environment failed, -ENOENT if ant file was
- * not found
- */
-int dhcp_run(ulong addr, const char *fname, bool autoload);
-
-/**
- * An incoming packet handler.
- * @param pkt pointer to the application packet
- * @param dport destination UDP port
- * @param sip source IP address
- * @param sport source UDP port
- * @param len packet length
- */
-typedef void rxhand_f(uchar *pkt, unsigned dport,
- struct in_addr sip, unsigned sport,
- unsigned len);
-
-/**
- * An incoming ICMP packet handler.
- * @param type ICMP type
- * @param code ICMP code
- * @param dport destination UDP port
- * @param sip source IP address
- * @param sport source UDP port
- * @param pkt pointer to the ICMP packet data
- * @param len packet length
- */
-typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport,
- struct in_addr sip, unsigned sport, uchar *pkt, unsigned len);
-
-/*
- * A timeout handler. Called after time interval has expired.
- */
-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);
-
-/**********************************************************************/
-/*
- * Protocol headers.
- */
-
-/*
- * Ethernet header
- */
-
-struct ethernet_hdr {
- u8 et_dest[ARP_HLEN]; /* Destination node */
- u8 et_src[ARP_HLEN]; /* Source node */
- u16 et_protlen; /* Protocol or length */
-} __attribute__((packed));
-
-/* Ethernet header size */
-#define ETHER_HDR_SIZE (sizeof(struct ethernet_hdr))
-
-#define ETH_FCS_LEN 4 /* Octets in the FCS */
-
-struct e802_hdr {
- u8 et_dest[ARP_HLEN]; /* Destination node */
- u8 et_src[ARP_HLEN]; /* Source node */
- u16 et_protlen; /* Protocol or length */
- u8 et_dsap; /* 802 DSAP */
- u8 et_ssap; /* 802 SSAP */
- u8 et_ctl; /* 802 control */
- u8 et_snap1; /* SNAP */
- u8 et_snap2;
- u8 et_snap3;
- u16 et_prot; /* 802 protocol */
-} __attribute__((packed));
-
-/* 802 + SNAP + ethernet header size */
-#define E802_HDR_SIZE (sizeof(struct e802_hdr))
-
-/*
- * Virtual LAN Ethernet header
- */
-struct vlan_ethernet_hdr {
- u8 vet_dest[ARP_HLEN]; /* Destination node */
- u8 vet_src[ARP_HLEN]; /* Source node */
- u16 vet_vlan_type; /* PROT_VLAN */
- u16 vet_tag; /* TAG of VLAN */
- u16 vet_type; /* protocol type */
-} __attribute__((packed));
-
-/* VLAN Ethernet header size */
-#define VLAN_ETHER_HDR_SIZE (sizeof(struct vlan_ethernet_hdr))
-
-#define PROT_IP 0x0800 /* IP protocol */
-#define PROT_ARP 0x0806 /* IP ARP protocol */
-#define PROT_WOL 0x0842 /* ether-wake WoL protocol */
-#define PROT_RARP 0x8035 /* IP ARP protocol */
-#define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */
-#define PROT_IPV6 0x86dd /* IPv6 over bluebook */
-#define PROT_PPP_SES 0x8864 /* PPPoE session messages */
-#define PROT_NCSI 0x88f8 /* NC-SI control packets */
-
-#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
-#define IPPROTO_TCP 6 /* Transmission Control Protocol */
-#define IPPROTO_UDP 17 /* User Datagram Protocol */
-
-/*
- * Internet Protocol (IP) header.
- */
-struct ip_hdr {
- u8 ip_hl_v; /* header length and version */
- u8 ip_tos; /* type of service */
- u16 ip_len; /* total length */
- u16 ip_id; /* identification */
- u16 ip_off; /* fragment offset field */
- u8 ip_ttl; /* time to live */
- u8 ip_p; /* protocol */
- u16 ip_sum; /* checksum */
- struct in_addr ip_src; /* Source IP address */
- struct in_addr ip_dst; /* Destination IP address */
-} __attribute__((packed));
-
-#define IP_OFFS 0x1fff /* ip offset *= 8 */
-#define IP_FLAGS 0xe000 /* first 3 bits */
-#define IP_FLAGS_RES 0x8000 /* reserved */
-#define IP_FLAGS_DFRAG 0x4000 /* don't fragments */
-#define IP_FLAGS_MFRAG 0x2000 /* more fragments */
-
-#define IP_HDR_SIZE (sizeof(struct ip_hdr))
-
-#define IP_MIN_FRAG_DATAGRAM_SIZE (IP_HDR_SIZE + 8)
-
-/*
- * Internet Protocol (IP) + UDP header.
- */
-struct ip_udp_hdr {
- u8 ip_hl_v; /* header length and version */
- u8 ip_tos; /* type of service */
- u16 ip_len; /* total length */
- u16 ip_id; /* identification */
- u16 ip_off; /* fragment offset field */
- u8 ip_ttl; /* time to live */
- u8 ip_p; /* protocol */
- u16 ip_sum; /* checksum */
- struct in_addr ip_src; /* Source IP address */
- struct in_addr ip_dst; /* Destination IP address */
- u16 udp_src; /* UDP source port */
- u16 udp_dst; /* UDP destination port */
- u16 udp_len; /* Length of UDP packet */
- u16 udp_xsum; /* Checksum */
-} __attribute__((packed));
-
-#define IP_UDP_HDR_SIZE (sizeof(struct ip_udp_hdr))
-#define UDP_HDR_SIZE (IP_UDP_HDR_SIZE - IP_HDR_SIZE)
-
-/*
- * Address Resolution Protocol (ARP) header.
- */
-struct arp_hdr {
- u16 ar_hrd; /* Format of hardware address */
-# define ARP_ETHER 1 /* Ethernet hardware address */
- u16 ar_pro; /* Format of protocol address */
- u8 ar_hln; /* Length of hardware address */
- u8 ar_pln; /* Length of protocol address */
-# define ARP_PLEN 4
- u16 ar_op; /* Operation */
-# define ARPOP_REQUEST 1 /* Request to resolve address */
-# define ARPOP_REPLY 2 /* Response to previous request */
-
-# define RARPOP_REQUEST 3 /* Request to resolve address */
-# define RARPOP_REPLY 4 /* Response to previous request */
-
- /*
- * The remaining fields are variable in size, according to
- * the sizes above, and are defined as appropriate for
- * specific hardware/protocol combinations.
- */
- u8 ar_data[0];
-#define ar_sha ar_data[0]
-#define ar_spa ar_data[ARP_HLEN]
-#define ar_tha ar_data[ARP_HLEN + ARP_PLEN]
-#define ar_tpa ar_data[ARP_HLEN + ARP_PLEN + ARP_HLEN]
-#if 0
- u8 ar_sha[]; /* Sender hardware address */
- u8 ar_spa[]; /* Sender protocol address */
- u8 ar_tha[]; /* Target hardware address */
- u8 ar_tpa[]; /* Target protocol address */
-#endif /* 0 */
-} __attribute__((packed));
-
-#define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */
-
-/*
- * ICMP stuff (just enough to handle (host) redirect messages)
- */
-#define ICMP_ECHO_REPLY 0 /* Echo reply */
-#define ICMP_NOT_REACH 3 /* Detination unreachable */
-#define ICMP_REDIRECT 5 /* Redirect (change route) */
-#define ICMP_ECHO_REQUEST 8 /* Echo request */
-
-/* Codes for REDIRECT. */
-#define ICMP_REDIR_NET 0 /* Redirect Net */
-#define ICMP_REDIR_HOST 1 /* Redirect Host */
-
-/* Codes for NOT_REACH */
-#define ICMP_NOT_REACH_PORT 3 /* Port unreachable */
-
-struct icmp_hdr {
- u8 type;
- u8 code;
- u16 checksum;
- union {
- struct {
- u16 id;
- u16 sequence;
- } echo;
- u32 gateway;
- struct {
- u16 unused;
- u16 mtu;
- } frag;
- u8 data[0];
- } un;
-} __attribute__((packed));
-
-#define ICMP_HDR_SIZE (sizeof(struct icmp_hdr))
-#define IP_ICMP_HDR_SIZE (IP_HDR_SIZE + ICMP_HDR_SIZE)
-
-/*
- * Maximum packet size; used to allocate packet storage. Use
- * the maxium Ethernet frame size as specified by the Ethernet
- * standard including the 802.1Q tag (VLAN tagging).
- * maximum packet size = 1522
- * maximum packet size and multiple of 32 bytes = 1536
- */
-#define PKTSIZE 1522
-#ifndef CONFIG_DM_DSA
-#define PKTSIZE_ALIGN 1536
-#else
-/* Maximum DSA tagging overhead (headroom and/or tailroom) */
-#define DSA_MAX_OVR 256
-#define PKTSIZE_ALIGN (1536 + DSA_MAX_OVR)
-#endif
-
-/*
- * Maximum receive ring size; that is, the number of packets
- * we can buffer before overflow happens. Basically, this just
- * needs to be enough to prevent a packet being discarded while
- * we are processing the previous one.
- */
-#define RINGSZ 4
-#define RINGSZ_LOG2 2
-
-/**********************************************************************/
-/*
- * Globals.
- *
- * Note:
- *
- * All variables of type struct in_addr are stored in NETWORK byte order
- * (big endian).
- */
-
-/* net.c */
-/** BOOTP EXTENTIONS **/
-extern struct in_addr net_gateway; /* Our gateway IP address */
-extern struct in_addr net_netmask; /* Our subnet mask (0 = unknown) */
-/* Our Domain Name Server (0 = unknown) */
-extern struct in_addr net_dns_server;
-#if defined(CONFIG_BOOTP_DNS2)
-/* Our 2nd Domain Name Server (0 = unknown) */
-extern struct in_addr net_dns_server2;
-#endif
-extern char net_nis_domain[32]; /* Our IS domain */
-extern char net_hostname[32]; /* Our hostname */
-#ifdef CONFIG_NET
-extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */
-#endif
-/* 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 */
-extern ushort net_our_vlan; /* Our VLAN */
-extern ushort net_native_vlan; /* Our Native VLAN */
-
-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
-};
-
-extern char net_boot_file_name[1024];/* Boot File name */
-/* Indicates whether the file name was specified on the command line */
-extern bool net_boot_file_name_explicit;
-/* The actual transferred size of the bootfile (in bytes) */
-extern u32 net_boot_file_size;
-/* Boot file size in blocks as reported by the DHCP server */
-extern u32 net_boot_file_expected_size_in_blocks;
-
-#if defined(CONFIG_CMD_DNS)
-extern char *net_dns_resolve; /* The host to resolve */
-extern char *net_dns_env_var; /* the env var to put the ip into */
-#endif
-
-#if defined(CONFIG_CMD_PING)
-extern struct in_addr net_ping_ip; /* the ip address to ping */
-#endif
-
-#if defined(CONFIG_CMD_CDP)
-/* when CDP completes these hold the return values */
-extern ushort cdp_native_vlan; /* CDP returned native VLAN */
-extern ushort cdp_appliance_vlan; /* CDP returned appliance VLAN */
-
-/*
- * Check for a CDP packet by examining the received MAC address field
- */
-static inline int is_cdp_packet(const uchar *ethaddr)
-{
- extern const u8 net_cdp_ethaddr[ARP_HLEN];
-
- return memcmp(ethaddr, net_cdp_ethaddr, ARP_HLEN) == 0;
-}
-#endif
-
-#if defined(CONFIG_CMD_SNTP)
-extern struct in_addr net_ntp_server; /* the ip address to NTP */
-extern int net_ntp_time_offset; /* offset time from UTC */
-#endif
-
-/* Initialize the network adapter */
-int net_init(void);
-int net_loop(enum proto_t);
-
-/* Load failed. Start again. */
-int net_start_again(void);
-
-/* Get size of the ethernet header when we send */
-int net_eth_hdr_size(void);
-
-/* Set ethernet header; returns the size of the header */
-int net_set_ether(uchar *xet, const uchar *dest_ethaddr, uint prot);
-int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot);
-
-/* Set IP header */
-void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source,
- u16 pkt_len, u8 proto);
-void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport,
- int sport, int len);
-
-/**
- * compute_ip_checksum() - Compute IP checksum
- *
- * @addr: Address to check (must be 16-bit aligned)
- * @nbytes: Number of bytes to check (normally a multiple of 2)
- * Return: 16-bit IP checksum
- */
-unsigned compute_ip_checksum(const void *addr, unsigned nbytes);
-
-/**
- * add_ip_checksums() - add two IP checksums
- *
- * @offset: Offset of first sum (if odd we do a byte-swap)
- * @sum: First checksum
- * @new_sum: New checksum to add
- * Return: updated 16-bit IP checksum
- */
-unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
-
-/**
- * ip_checksum_ok() - check if a checksum is correct
- *
- * This works by making sure the checksum sums to 0
- *
- * @addr: Address to check (must be 16-bit aligned)
- * @nbytes: Number of bytes to check (normally a multiple of 2)
- * Return: true if the checksum matches, false if not
- */
-int ip_checksum_ok(const void *addr, unsigned nbytes);
-
-/* Callbacks */
-rxhand_f *net_get_udp_handler(void); /* Get UDP RX packet handler */
-void net_set_udp_handler(rxhand_f *); /* Set UDP RX packet handler */
-rxhand_f *net_get_arp_handler(void); /* Get ARP RX packet handler */
-void net_set_arp_handler(rxhand_f *); /* Set ARP RX packet handler */
-bool arp_is_waiting(void); /* Waiting for ARP reply? */
-void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
-void net_set_timeout_handler(ulong, thand_f *);/* Set timeout handler */
-
-/* Network loop state */
-enum net_loop_state {
- NETLOOP_CONTINUE,
- NETLOOP_RESTART,
- NETLOOP_SUCCESS,
- NETLOOP_FAIL
-};
-extern enum net_loop_state net_state;
-
-static inline void net_set_state(enum net_loop_state state)
-{
- debug_cond(DEBUG_INT_STATE, "--- NetState set to %d\n", state);
- net_state = state;
-}
-
-/*
- * net_get_async_tx_pkt_buf - Get a packet buffer that is not in use for
- * sending an asynchronous reply
- *
- * returns - ptr to packet buffer
- */
-uchar * net_get_async_tx_pkt_buf(void);
-
-/* Transmit a packet */
-static inline void net_send_packet(uchar *pkt, int len)
-{
- if (DEBUG_NET_PKT_TRACE)
- print_hex_dump_bytes("tx: ", DUMP_PREFIX_OFFSET, pkt, len);
- /* Currently no way to return errors from eth_send() */
- (void) eth_send(pkt, len);
-}
-
-/**
- * net_send_ip_packet() - Transmit "net_tx_packet" as UDP or TCP packet,
- * send ARP request if needed (ether will be populated)
- * @ether: Raw packet buffer
- * @dest: IP address to send the datagram to
- * @dport: Destination UDP port
- * @sport: Source UDP port
- * @payload_len: Length of data after the UDP header
- * @action: TCP action to be performed
- * @tcp_seq_num: TCP sequence number of this transmission
- * @tcp_ack_num: TCP stream acknolegement number
- *
- * Return: 0 on success, other value on failure
- */
-int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
- int payload_len, int proto, u8 action, u32 tcp_seq_num,
- u32 tcp_ack_num);
-/**
- * net_send_tcp_packet() - Transmit TCP packet.
- * @payload_len: length of payload
- * @dport: Destination TCP port
- * @sport: Source TCP port
- * @action: TCP action to be performed
- * @tcp_seq_num: TCP sequence number of this transmission
- * @tcp_ack_num: TCP stream acknolegement number
- *
- * Return: 0 on success, other value on failure
- */
-int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action,
- u32 tcp_seq_num, u32 tcp_ack_num);
-int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport,
- int sport, int payload_len);
-
-/* Processes a received packet */
-void net_process_received_packet(uchar *in_packet, int len);
-
-#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
-void nc_start(void);
-int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
- unsigned src_port, unsigned len);
-#endif
-
-static __always_inline int eth_is_on_demand_init(void)
-{
-#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
- extern enum proto_t net_loop_last_protocol;
-
- return net_loop_last_protocol != NETCONS;
-#else
- return 1;
-#endif
-}
-
-static inline void eth_set_last_protocol(int protocol)
-{
-#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD)
- extern enum proto_t net_loop_last_protocol;
-
- net_loop_last_protocol = protocol;
-#endif
-}
-
-/*
- * Check if autoload is enabled. If so, use either NFS or TFTP to download
- * the boot file.
- */
-void net_auto_load(void);
-
-/*
- * The following functions are a bit ugly, but necessary to deal with
- * alignment restrictions on ARM.
- *
- * We're using inline functions, which had the smallest memory
- * footprint in our tests.
- */
-/* return IP *in network byteorder* */
-static inline struct in_addr net_read_ip(void *from)
-{
- struct in_addr ip;
-
- memcpy((void *)&ip, (void *)from, sizeof(ip));
- return ip;
-}
-
-/* return ulong *in network byteorder* */
-static inline u32 net_read_u32(void *from)
-{
- u32 l;
-
- memcpy((void *)&l, (void *)from, sizeof(l));
- return l;
-}
-
-/* write IP *in network byteorder* */
-static inline void net_write_ip(void *to, struct in_addr ip)
-{
- memcpy(to, (void *)&ip, sizeof(ip));
-}
-
-/* copy IP */
-static inline void net_copy_ip(void *to, void *from)
-{
- memcpy((void *)to, from, sizeof(struct in_addr));
-}
-
-/* copy ulong */
-static inline void net_copy_u32(void *to, void *from)
-{
- memcpy((void *)to, (void *)from, sizeof(u32));
-}
-
-/**
- * is_zero_ethaddr - Determine if give Ethernet address is all zeros.
- * @addr: Pointer to a six-byte array containing the Ethernet address
- *
- * Return true if the address is all zeroes.
- */
-static inline int is_zero_ethaddr(const u8 *addr)
-{
- return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
-}
-
-/**
- * is_multicast_ethaddr - Determine if the Ethernet address is a multicast.
- * @addr: Pointer to a six-byte array containing the Ethernet address
- *
- * Return true if the address is a multicast address.
- * By definition the broadcast address is also a multicast address.
- */
-static inline int is_multicast_ethaddr(const u8 *addr)
-{
- return 0x01 & addr[0];
-}
-
-/*
- * is_broadcast_ethaddr - Determine if the Ethernet address is broadcast
- * @addr: Pointer to a six-byte array containing the Ethernet address
- *
- * Return true if the address is the broadcast address.
- */
-static inline int is_broadcast_ethaddr(const u8 *addr)
-{
- return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) ==
- 0xff;
-}
-
-/*
- * is_valid_ethaddr - Determine if the given Ethernet address is valid
- * @addr: Pointer to a six-byte array containing the Ethernet address
- *
- * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
- * a multicast address, and is not FF:FF:FF:FF:FF:FF.
- *
- * Return true if the address is valid.
- */
-static inline int is_valid_ethaddr(const u8 *addr)
-{
- /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
- * explicitly check for it here. */
- return !is_multicast_ethaddr(addr) && !is_zero_ethaddr(addr);
-}
-
-/**
- * net_random_ethaddr - Generate software assigned random Ethernet address
- * @addr: Pointer to a six-byte array containing the Ethernet address
- *
- * Generate a random Ethernet address (MAC) that is not multicast
- * and has the local assigned bit set.
- */
-static inline void net_random_ethaddr(uchar *addr)
-{
- int i;
- unsigned int seed = get_ticks();
-
- for (i = 0; i < 6; i++)
- addr[i] = rand_r(&seed);
-
- addr[0] &= 0xfe; /* clear multicast bit */
- 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);
-
-/**
- * string_to_ip() - Convert a string to ip address
- *
- * Implemented in lib/net_utils.c (built unconditionally)
- *
- * @s: Input string to parse
- * @return: in_addr struct containing the parsed IP address
- */
-struct in_addr string_to_ip(const char *s);
-
-/* Convert a VLAN id to a string */
-void vlan_to_string(ushort x, char *s);
-
-/* Convert a string to a vlan id */
-ushort string_to_vlan(const char *s);
-
-/* read a VLAN id from an environment variable */
-ushort env_get_vlan(char *);
-
-/* copy a filename (allow for "..." notation, limit length) */
-void copy_filename(char *dst, const char *src, int size);
-
-/* check if serverip is specified in filename from the command line */
-int is_serverip_in_cmd(void);
-
-/**
- * net_parse_bootfile - Parse the bootfile env var / cmd line param
- *
- * @param ipaddr - a pointer to the ipaddr to populate if included in bootfile
- * @param filename - a pointer to the string to save the filename part
- * @param max_len - The longest - 1 that the filename part can be
- *
- * return 1 if parsed, 0 if bootfile is empty
- */
-int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len);
-
-/**
- * update_tftp - Update firmware over TFTP (via DFU)
- *
- * This function updates board's firmware via TFTP
- *
- * @param addr - memory address where data is stored
- * @param interface - the DFU medium name - e.g. "mmc"
- * @param devstring - the DFU medium number - e.g. "1"
- *
- * Return: - 0 on success, other value on failure
- */
-int update_tftp(ulong addr, char *interface, char *devstring);
-
-/**
- * env_get_ip() - Convert an environment value to to an ip address
- *
- * @var: Environment variable to convert. The value of this variable must be
- * in the format format a.b.c.d, where each value is a decimal number from
- * 0 to 255
- * Return: IP address, or 0 if invalid
- */
-static inline struct in_addr env_get_ip(char *var)
-{
- return string_to_ip(env_get(var));
-}
-
-/**
- * reset_phy() - Reset the Ethernet PHY
- *
- * This should be implemented by boards if CONFIG_RESET_PHY_R is enabled
- */
-void reset_phy(void);
-
-#if CONFIG_IS_ENABLED(NET)
-/**
- * eth_set_enable_bootdevs() - Enable or disable binding of Ethernet bootdevs
- *
- * These get in the way of bootstd testing, so are normally disabled by tests.
- * This provide control of this setting. It only affects binding of Ethernet
- * devices, so if that has already happened, this flag does nothing.
- *
- * @enable: true to enable binding of bootdevs when binding new Ethernet
- * devices, false to disable it
- */
-void eth_set_enable_bootdevs(bool enable);
+#if defined(CONFIG_NET_LWIP)
+#include <net-lwip.h>
#else
-static inline void eth_set_enable_bootdevs(bool enable) {}
+#include <net-legacy.h>
#endif
-/**
- * wget_with_dns() - runs dns host IP address resulution before wget
- *
- * @dst_addr: destination address to download the file
- * @uri: uri string of target file of wget
- * Return: downloaded file size, negative if failed
- */
-int wget_with_dns(ulong dst_addr, char *uri);
-
-/**
- * wget_validate_uri() - varidate the uri
- *
- * @uri: uri string of target file of wget
- * Return: true if uri is valid, false if uri is invalid
- */
-bool wget_validate_uri(char *uri);
-
#endif /* __NET_H__ */
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 04/14] net-lwip: build lwIP
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (2 preceding siblings ...)
2024-06-17 15:32 ` [PATCH v4 03/14] net: split include/net.h into net{, -common, -legacy, -lwip}.h Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-17 15:32 ` [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand Jerome Forissier
` (12 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Oleksandr Suvorov, Sean Anderson
Build the lwIP library when NET_LWIP is enabled. The following files
are adaptation layers written specially for U-Boot:
lib/lwip/u-boot/arch/cc.h
lib/lwip/u-boot/arch/sys_arch.h (empty)
lib/lwip/u-boot/limits.h (empty)
lib/lwip/u-boot/lwipopts.h
They were initially contributed by Maxim in a previous RFC patch series.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
Cc: Maxim Uvarov <muvarov@gmail.com>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
lib/Makefile | 2 +
lib/lwip/Makefile | 55 +++++++++
lib/lwip/u-boot/arch/cc.h | 43 +++++++
lib/lwip/u-boot/arch/sys_arch.h | 0
lib/lwip/u-boot/limits.h | 0
lib/lwip/u-boot/lwipopts.h | 197 ++++++++++++++++++++++++++++++++
6 files changed, 297 insertions(+)
create mode 100644 lib/lwip/Makefile
create mode 100644 lib/lwip/u-boot/arch/cc.h
create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
create mode 100644 lib/lwip/u-boot/limits.h
create mode 100644 lib/lwip/u-boot/lwipopts.h
diff --git a/lib/Makefile b/lib/Makefile
index 2a76acf100d..c35786a0576 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -94,6 +94,8 @@ obj-$(CONFIG_LIBAVB) += libavb/
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
+obj-$(CONFIG_NET_LWIP) += lwip/
+
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o
obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
new file mode 100644
index 00000000000..dfcd700ca47
--- /dev/null
+++ b/lib/lwip/Makefile
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2024 Linaro Ltd.
+
+obj-y += \
+ lwip/src/api/api_lib.o \
+ lwip/src/api/api_msg.o \
+ lwip/src/api/err.o \
+ lwip/src/api/if_api.o \
+ lwip/src/api/netbuf.o \
+ lwip/src/api/netdb.o \
+ lwip/src/api/netifapi.o \
+ lwip/src/api/sockets.o \
+ lwip/src/api/tcpip.o \
+ lwip/src/apps/http/http_client.o \
+ lwip/src/apps/tftp/tftp.o \
+ lwip/src/core/altcp_alloc.o \
+ lwip/src/core/altcp.o \
+ lwip/src/core/altcp_tcp.o \
+ lwip/src/core/def.o \
+ lwip/src/core/dns.o \
+ lwip/src/core/inet_chksum.o \
+ lwip/src/core/init.o \
+ lwip/src/core/ip.o \
+ lwip/src/core/ipv4/acd.o \
+ lwip/src/core/ipv4/autoip.o \
+ lwip/src/core/ipv4/dhcp.o \
+ lwip/src/core/ipv4/etharp.o \
+ lwip/src/core/ipv4/icmp.o \
+ lwip/src/core/ipv4/igmp.o \
+ lwip/src/core/ipv4/ip4_addr.o \
+ lwip/src/core/ipv4/ip4.o \
+ lwip/src/core/ipv4/ip4_frag.o \
+ lwip/src/core/ipv6/dhcp6.o \
+ lwip/src/core/ipv6/ethip6.o \
+ lwip/src/core/ipv6/icmp6.o \
+ lwip/src/core/ipv6/inet6.o \
+ lwip/src/core/ipv6/ip6_addr.o \
+ lwip/src/core/ipv6/ip6.o \
+ lwip/src/core/ipv6/ip6_frag.o \
+ lwip/src/core/ipv6/mld6.o \
+ lwip/src/core/ipv6/nd6.o \
+ lwip/src/core/mem.o \
+ lwip/src/core/memp.o \
+ lwip/src/core/netif.o \
+ lwip/src/core/pbuf.o \
+ lwip/src/core/raw.o \
+ lwip/src/core/stats.o \
+ lwip/src/core/sys.o \
+ lwip/src/core/tcp.o \
+ lwip/src/core/tcp_in.o \
+ lwip/src/core/tcp_out.o \
+ lwip/src/core/timeouts.o \
+ lwip/src/core/udp.o \
+ lwip/src/netif/ethernet.o
diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
new file mode 100644
index 00000000000..31c036dc0c5
--- /dev/null
+++ b/lib/lwip/u-boot/arch/cc.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023 Linaro Ltd. <maxim.uvarov@linaro.org> */
+
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <vsprintf.h>
+#include <rand.h>
+
+#define LWIP_ERRNO_INCLUDE <errno.h>
+
+#define LWIP_ERRNO_STDINCLUDE 1
+#define LWIP_NO_UNISTD_H 1
+#define LWIP_TIMEVAL_PRIVATE 1
+
+#ifdef CONFIG_LIB_RAND
+#define LWIP_RAND() ((u32_t)rand())
+#endif
+
+/* different handling for unit test, normally not needed */
+#ifdef LWIP_NOASSERT_ON_ERROR
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+ handler; }} while (0)
+#endif
+
+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
+
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
+ x, __LINE__, __FILE__); } while (0)
+
+#define atoi(str) (int)dectoul(str, NULL)
+#define lwip_strnstr(a, b) strnstr(a, b)
+
+#define LWIP_ERR_T int
+#define LWIP_CONST_CAST(target_type, val) ((target_type)((uintptr_t)val))
+
+#if defined(CONFIG_SYS_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/lib/lwip/u-boot/arch/sys_arch.h b/lib/lwip/u-boot/arch/sys_arch.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/lwip/u-boot/limits.h b/lib/lwip/u-boot/limits.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/lwip/u-boot/lwipopts.h b/lib/lwip/u-boot/lwipopts.h
new file mode 100644
index 00000000000..fd9fd2c2bd9
--- /dev/null
+++ b/lib/lwip/u-boot/lwipopts.h
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/* Copyright (C) 2023 Linaro Ltd. <maxim.uvarov@linaro.org> */
+
+#ifndef LWIP_UBOOT_LWIPOPTS_H
+#define LWIP_UBOOT_LWIPOPTS_H
+
+#if defined(CONFIG_LWIP_DEBUG)
+#define LWIP_DEBUG 1
+#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
+#define LWIP_DBG_TYPES_ON LWIP_DBG_ON
+#define ETHARP_DEBUG LWIP_DBG_ON
+#define NETIF_DEBUG LWIP_DBG_ON
+#define PBUF_DEBUG LWIP_DBG_OFF
+#define API_LIB_DEBUG LWIP_DBG_ON
+#define API_MSG_DEBUG LWIP_DBG_OFF
+#define SOCKETS_DEBUG LWIP_DBG_OFF
+#define ICMP_DEBUG LWIP_DBG_OFF
+#define IGMP_DEBUG LWIP_DBG_OFF
+#define INET_DEBUG LWIP_DBG_OFF
+#define IP_DEBUG LWIP_DBG_ON
+#define IP_REASS_DEBUG LWIP_DBG_OFF
+#define RAW_DEBUG LWIP_DBG_OFF
+#define MEM_DEBUG LWIP_DBG_OFF
+#define MEMP_DEBUG LWIP_DBG_OFF
+#define SYS_DEBUG LWIP_DBG_OFF
+#define TIMERS_DEBUG LWIP_DBG_ON
+#define TCP_DEBUG LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG LWIP_DBG_OFF
+#define TCP_FR_DEBUG LWIP_DBG_OFF
+#define TCP_RTO_DEBUG LWIP_DBG_OFF
+#define TCP_CWND_DEBUG LWIP_DBG_OFF
+#define TCP_WND_DEBUG LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
+#define TCP_RST_DEBUG LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG LWIP_DBG_OFF
+#define UDP_DEBUG LWIP_DBG_OFF
+#define TCPIP_DEBUG LWIP_DBG_OFF
+#define SLIP_DEBUG LWIP_DBG_OFF
+#define DHCP_DEBUG LWIP_DBG_ON
+#define AUTOIP_DEBUG LWIP_DBG_ON
+#define DNS_DEBUG LWIP_DBG_ON
+#define IP6_DEBUG LWIP_DBG_OFF
+#define DHCP6_DEBUG LWIP_DBG_OFF
+#else
+#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
+#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF
+#define ETHARP_DEBUG LWIP_DBG_OFF
+#define NETIF_DEBUG LWIP_DBG_OFF
+#define PBUF_DEBUG LWIP_DBG_OFF
+#define API_LIB_DEBUG LWIP_DBG_OFF
+#define API_MSG_DEBUG LWIP_DBG_OFF
+#define SOCKETS_DEBUG LWIP_DBG_OFF
+#define ICMP_DEBUG LWIP_DBG_OFF
+#define IGMP_DEBUG LWIP_DBG_OFF
+#define INET_DEBUG LWIP_DBG_OFF
+#define IP_DEBUG LWIP_DBG_OFF
+#define IP_REASS_DEBUG LWIP_DBG_OFF
+#define RAW_DEBUG LWIP_DBG_OFF
+#define MEM_DEBUG LWIP_DBG_OFF
+#define MEMP_DEBUG LWIP_DBG_OFF
+#define SYS_DEBUG LWIP_DBG_OFF
+#define TIMERS_DEBUG LWIP_DBG_OFF
+#define TCP_DEBUG LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG LWIP_DBG_OFF
+#define TCP_FR_DEBUG LWIP_DBG_OFF
+#define TCP_RTO_DEBUG LWIP_DBG_OFF
+#define TCP_CWND_DEBUG LWIP_DBG_OFF
+#define TCP_WND_DEBUG LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
+#define TCP_RST_DEBUG LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG LWIP_DBG_OFF
+#define UDP_DEBUG LWIP_DBG_OFF
+#define TCPIP_DEBUG LWIP_DBG_OFF
+#define SLIP_DEBUG LWIP_DBG_OFF
+#define DHCP_DEBUG LWIP_DBG_OFF
+#define AUTOIP_DEBUG LWIP_DBG_OFF
+#define DNS_DEBUG LWIP_DBG_OFF
+#define IP6_DEBUG LWIP_DBG_OFF
+#define DHCP6_DEBUG LWIP_DBG_OFF
+#endif
+#define LWIP_TESTMODE 0
+
+#if !defined(CONFIG_LWIP_ASSERT)
+#define LWIP_NOASSERT 1
+#define LWIP_ASSERT(message, assertion)
+#endif
+
+#include "lwip/debug.h"
+
+#define SYS_LIGHTWEIGHT_PROT 0
+#define NO_SYS 1
+
+#define LWIP_IPV4 1
+#define LWIP_IPV6 0
+
+#define MEM_ALIGNMENT 1
+#define MEM_SIZE 1600
+
+#define MEMP_NUM_PBUF 4
+#define MEMP_NUM_RAW_PCB 2
+#define MEMP_NUM_UDP_PCB 4
+#define MEMP_NUM_TCP_PCB 2
+#define MEMP_NUM_TCP_PCB_LISTEN 2
+#define MEMP_NUM_TCP_SEG 16
+#define MEMP_NUM_REASSDATA 1
+#define MEMP_NUM_ARP_QUEUE 2
+#define MEMP_NUM_SYS_TIMEOUT 4
+#define MEMP_NUM_NETBUF 2
+#define MEMP_NUM_NETCONN 32
+#define MEMP_NUM_TCPIP_MSG_API 8
+#define MEMP_NUM_TCPIP_MSG_INPKT 8
+#define PBUF_POOL_SIZE 8
+
+#define LWIP_ARP 1
+#define ARP_TABLE_SIZE 10
+#define ARP_QUEUEING 1
+
+#define IP_FORWARD 0
+#define IP_OPTIONS_ALLOWED 1
+#define IP_REASSEMBLY 0
+#define IP_FRAG 0
+#define IP_REASS_MAXAGE 3
+#define IP_REASS_MAX_PBUFS 4
+#define IP_FRAG_USES_STATIC_BUF 0
+
+#define IP_DEFAULT_TTL 255
+
+#define LWIP_ICMP 0
+
+#if defined(CONFIG_PROT_RAW_LWIP)
+#define LWIP_RAW 1
+#else
+#define LWIP_RAW 0
+#endif
+
+#if defined(CONFIG_PROT_DHCP_LWIP)
+#define LWIP_DHCP 1
+#define LWIP_DHCP_BOOTP_FILE 1
+#else
+#define LWIP_DHCP 0
+#endif
+
+#define LWIP_DHCP_DOES_ACD_CHECK 0
+
+#define LWIP_AUTOIP 0
+
+#define LWIP_SNMP 0
+
+#define LWIP_IGMP 0
+
+#if defined(CONFIG_PROT_DNS_LWIP)
+#define LWIP_DNS 1
+#define DNS_TABLE_SIZE 1
+#else
+#define LWIP_DNS 0
+#endif
+
+#if defined(CONFIG_PROT_UDP_LWIP)
+#define LWIP_UDP 1
+#else
+#define LWIP_UDP 0
+#endif
+
+#if defined(CONFIG_PROT_TCP_LWIP)
+#define LWIP_TCP 1
+#else
+#define LWIP_TCP 0
+#endif
+
+#define LWIP_LISTEN_BACKLOG 0
+
+#define PBUF_LINK_HLEN 14
+#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN)
+
+#define LWIP_HAVE_LOOPIF 0
+
+#define LWIP_NETCONN 0
+#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1
+
+#define LWIP_SOCKET 0
+#define SO_REUSE 0
+
+#define LWIP_STATS 0
+
+#define PPP_SUPPORT 0
+
+#define LWIP_TCPIP_CORE_LOCKING 0
+
+#define LWIP_NETIF_LOOPBACK 0
+
+/* use malloc instead of pool */
+#define MEMP_MEM_MALLOC 1
+#define MEMP_MEM_INIT 1
+#define MEM_LIBC_MALLOC 1
+
+#endif /* LWIP_UBOOT_LWIPOPTS_H */
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (3 preceding siblings ...)
2024-06-17 15:32 ` [PATCH v4 04/14] net-lwip: build lwIP Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-17 16:54 ` Heinrich Schuchardt
2024-06-17 15:32 ` [PATCH v4 06/14] net-lwip: add TFTP support and tftpboot command Jerome Forissier
` (11 subsequent siblings)
16 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Joe Hershberger, Ramon Fried, Simon Glass, Andrew Davis,
Sumit Garg, Marek Vasut, Heinrich Schuchardt, Bryan Brattlof,
Jesse Taube, Leon M. Busch-George, Eddie James,
Mattijs Korpershoek, AKASHI Takahiro, Francis Laniel,
Peter Robinson, Abdellatif El Khlifi, Shiji Yang, Nikhil M Jain,
Artur Rojek, Yang Xiwen, Yanhong Wang, Kever Yang, Boon Khai Ng,
Neil Armstrong, Jonas Karlman
Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as
well as the dhcp command. CMD_TFTPBOOT is selected by BOOTMETH_EFI due
to this code having an implicit dependency on do_tftpb().
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
Makefile | 6 +
boot/Kconfig | 3 +-
cmd/Kconfig | 26 ++++
cmd/Makefile | 4 +
cmd/net-lwip.c | 13 ++
common/board_r.c | 4 +-
drivers/net/Kconfig | 2 +-
include/net-lwip.h | 2 +
net-lwip/Makefile | 15 +++
net-lwip/dhcp.c | 99 +++++++++++++++
net-lwip/eth_internal.h | 35 ++++++
net-lwip/net-lwip.c | 270 ++++++++++++++++++++++++++++++++++++++++
net-lwip/tftp.c | 11 ++
13 files changed, 486 insertions(+), 4 deletions(-)
create mode 100644 cmd/net-lwip.c
create mode 100644 net-lwip/Makefile
create mode 100644 net-lwip/dhcp.c
create mode 100644 net-lwip/eth_internal.h
create mode 100644 net-lwip/net-lwip.c
create mode 100644 net-lwip/tftp.c
diff --git a/Makefile b/Makefile
index 0fe1623c550..92a0ab770bb 100644
--- a/Makefile
+++ b/Makefile
@@ -862,6 +862,7 @@ libs-y += env/
libs-y += lib/
libs-y += fs/
libs-$(CONFIG_NET) += net/
+libs-$(CONFIG_NET_LWIP) += net-lwip/
libs-y += disk/
libs-y += drivers/
libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
@@ -2132,6 +2133,11 @@ etags:
cscope:
$(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) -name '*.[chS]' -print > \
cscope.files
+ifdef CONFIG_NET_LWIP
+ echo net/eth-uclass.c net/eth_common.c net/eth_bootdev.c \
+ net/mdio-uclass.c net/mdio-mux-uclass.c >> \
+ cscope.files
+endif
@find $(TAG_SUBDIRS) -name '*.[chS]' -type l -print | \
grep -xvf - cscope.files > cscope.files.no-symlinks; \
mv cscope.files.no-symlinks cscope.files
diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a6..004e69dd92a 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -378,7 +378,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_FAT
select CMD_FS_GENERIC
select CMD_PART if PARTITIONS
- select CMD_DHCP if CMD_NET
+ select CMD_DHCP if CMD_NET || CMD_NET_LWIP
select CMD_PING if CMD_NET
select CMD_PXE if CMD_NET
select CMD_BOOTI if ARM64
@@ -540,6 +540,7 @@ config BOOTMETH_EXTLINUX_PXE
config BOOTMETH_EFILOADER
bool "Bootdev support for EFI boot"
depends on EFI_BINARY_EXEC
+ select CMD_TFTPBOOT if CMD_NET_LWIP
default y
help
Enables support for EFI boot using bootdevs. This makes the
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b026439c773..1bfa528e945 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2084,6 +2084,32 @@ config CMD_WOL
endif
+if NET_LWIP
+
+menuconfig CMD_NET_LWIP
+ bool "Network commands (lwIP)"
+ default y
+
+if CMD_NET_LWIP
+
+config CMD_DHCP
+ bool "dhcp"
+ select PROT_DHCP_LWIP
+ help
+ Boot image via network using DHCP/TFTP protocol
+
+config CMD_TFTPBOOT
+ bool "tftp"
+ select PROT_UDP_LWIP
+ default n
+ help
+ tftpboot - load file via network using TFTP protocol
+ Currently a placeholder (not implemented)
+
+endif
+
+endif
+
menu "Misc commands"
config CMD_2048
diff --git a/cmd/Makefile b/cmd/Makefile
index 87133cc27a8..535b6838ca5 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -128,6 +128,10 @@ endif
obj-$(CONFIG_CMD_MUX) += mux.o
obj-$(CONFIG_CMD_NAND) += nand.o
obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+ifdef CONFIG_CMD_NET_LWIP
+CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+endif
obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
obj-$(CONFIG_CMD_ONENAND) += onenand.o
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
new file mode 100644
index 00000000000..82edb5fd2e6
--- /dev/null
+++ b/cmd/net-lwip.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <net.h>
+
+#if defined(CONFIG_CMD_DHCP)
+U_BOOT_CMD(
+ dhcp, 3, 1, do_dhcp,
+ "boot image via network using DHCP/TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/common/board_r.c b/common/board_r.c
index da0b80f24ff..6548eb8fdd5 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -472,7 +472,7 @@ static int initr_status_led(void)
}
#endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
static int initr_net(void)
{
puts("Net: ");
@@ -727,7 +727,7 @@ static init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_PCI_ENDPOINT
pci_ep_init,
#endif
-#ifdef CONFIG_CMD_NET
+#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
INIT_FUNC_WATCHDOG_RESET
initr_net,
#endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index efc55e45ca8..640c4218518 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -97,7 +97,7 @@ config DSA_SANDBOX
menuconfig NETDEVICES
bool "Network device support"
- depends on NET
+ depends on NET || NET_LWIP
select DM_ETH
help
You must select Y to enable any network device support
diff --git a/include/net-lwip.h b/include/net-lwip.h
index f5c743b8d11..46cf6875f7e 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -11,4 +11,6 @@ struct netif *net_lwip_new_netif_noip(void);
void net_lwip_remove_netif(struct netif *netif);
struct netif *net_lwip_get_netif(void);
+int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+
#endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
new file mode 100644
index 00000000000..a56c32bfa74
--- /dev/null
+++ b/net-lwip/Makefile
@@ -0,0 +1,15 @@
+ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+
+obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_ETH) += ../net/eth_bootdev.o
+obj-$(CONFIG_DM_MDIO) += ../net/mdio-uclass.o
+obj-$(CONFIG_DM_MDIO_MUX) += ../net/mdio-mux-uclass.o
+obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
+obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
+obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
+obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
+
+# Disable this warning as it is triggered by:
+# sprintf(buf, index ? "foo%d" : "foo", index)
+# and this is intentional usage.
+CFLAGS_eth_common.o += -Wno-format-extra-args
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
new file mode 100644
index 00000000000..38ea565508f
--- /dev/null
+++ b/net-lwip/dhcp.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <lwip/dhcp.h>
+#include <lwip/dns.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+#define DHCP_TIMEOUT_MS 10000
+
+#ifdef CONFIG_CMD_TFTPBOOT
+/* Boot file obtained from DHCP (if present) */
+static char boot_file_name[DHCP_BOOT_FILE_LEN];
+#endif
+
+static void call_lwip_dhcp_fine_tmr(void *ctx)
+{
+ dhcp_fine_tmr();
+ sys_timeout(10, call_lwip_dhcp_fine_tmr, NULL);
+}
+
+int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long start;
+ struct netif *netif;
+ struct dhcp *dhcp;
+ bool bound;
+
+ netif = net_lwip_new_netif_noip();
+ if (!netif)
+ return CMD_RET_FAILURE;
+
+ start = get_timer(0);
+ dhcp_start(netif);
+ call_lwip_dhcp_fine_tmr(NULL);
+
+ /* Wait for DHCP to complete */
+ do {
+ eth_rx();
+ sys_check_timeouts();
+ bound = dhcp_supplied_address(netif);
+ if (bound)
+ break;
+ if (ctrlc()) {
+ printf("Abort\n");
+ break;
+ }
+ mdelay(1);
+ } while (get_timer(start) < DHCP_TIMEOUT_MS);
+
+ sys_untimeout(call_lwip_dhcp_fine_tmr, NULL);
+
+ if (!bound) {
+ net_lwip_remove_netif(netif);
+ return CMD_RET_FAILURE;
+ }
+
+ dhcp = netif_dhcp_data(netif);
+
+ env_set("bootfile", dhcp->boot_file_name);
+ if (dhcp->offered_gw_addr.addr != 0)
+ env_set("gatewayip", ip4addr_ntoa(&dhcp->offered_gw_addr));
+ env_set("ipaddr", ip4addr_ntoa(&dhcp->offered_ip_addr));
+ env_set("netmask", ip4addr_ntoa(&dhcp->offered_sn_mask));
+ env_set("serverip", ip4addr_ntoa(&dhcp->server_ip_addr));
+#ifdef CONFIG_PROT_DNS_LWIP
+ env_set("dnsip", ip4addr_ntoa(dns_getserver(0)));
+ env_set("dnsip2", ip4addr_ntoa(dns_getserver(1)));
+#endif
+#ifdef CONFIG_CMD_TFTPBOOT
+ if (dhcp->boot_file_name[0] != '\0')
+ strncpy(boot_file_name, dhcp->boot_file_name,
+ sizeof(boot_file_name));
+#endif
+
+ printf("DHCP client bound to address %pI4 (%lu ms)\n",
+ &dhcp->offered_ip_addr, get_timer(start));
+
+ net_lwip_remove_netif(netif);
+ return CMD_RET_SUCCESS;
+}
+
+int dhcp_run(ulong addr, const char *fname, bool autoload)
+{
+ char *dhcp_argv[] = {"dhcp", NULL, };
+ struct cmd_tbl cmdtp = {}; /* dummy */
+
+ if (autoload) {
+ /* Will be supported when TFTP is added */
+ return -EOPNOTSUPP;
+ }
+
+ return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
+}
diff --git a/net-lwip/eth_internal.h b/net-lwip/eth_internal.h
new file mode 100644
index 00000000000..0b829a8d388
--- /dev/null
+++ b/net-lwip/eth_internal.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2001-2015
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Joe Hershberger, National Instruments
+ */
+
+#ifndef __ETH_INTERNAL_H
+#define __ETH_INTERNAL_H
+
+/* Do init that is common to driver model and legacy networking */
+void eth_common_init(void);
+
+/**
+ * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
+ *
+ * This sets up an environment variable with the given MAC address (@enetaddr).
+ * The environment variable to be set is defined by <@base_name><@index>addr.
+ * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
+ * eth1addr, etc.
+ *
+ * @base_name: Base name for variable, typically "eth"
+ * @index: Index of interface being updated (>=0)
+ * @enetaddr: Pointer to MAC address to put into the variable
+ * Return: 0 if OK, other value on error
+ */
+int eth_env_set_enetaddr_by_index(const char *base_name, int index,
+ uchar *enetaddr);
+
+int eth_mac_skip(int index);
+void eth_current_changed(void);
+void eth_set_dev(struct udevice *dev);
+void eth_set_current_to_next(void);
+
+#endif
diff --git a/net-lwip/net-lwip.c b/net-lwip/net-lwip.c
new file mode 100644
index 00000000000..39e7e51e542
--- /dev/null
+++ b/net-lwip/net-lwip.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <lwip/ip4_addr.h>
+#include <lwip/err.h>
+#include <lwip/netif.h>
+#include <lwip/pbuf.h>
+#include <lwip/etharp.h>
+#include <lwip/prot/etharp.h>
+#include <net.h>
+
+/* xx:xx:xx:xx:xx:xx\0 */
+#define MAC_ADDR_STRLEN 18
+
+#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
+void (*push_packet)(void *, int len) = 0;
+#endif
+int net_restart_wrap;
+static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
+uchar *net_rx_packets[PKTBUFSRX];
+uchar *net_rx_packet;
+uchar *net_tx_packet;
+
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+ int err;
+
+ /*
+ * lwIP is alwys configured to use one device, the active one, so
+ * there is no need to use the netif parameter.
+ */
+
+ /* switch dev to active state */
+ eth_init_state_only();
+
+ err = eth_send(p->payload, p->len);
+ if (err) {
+ log_err("eth_send error %d\n", err);
+ return ERR_ABRT;
+ }
+ return ERR_OK;
+}
+
+static err_t net_lwip_if_init(struct netif *netif)
+{
+#if LWIP_IPV4
+ netif->output = etharp_output;
+#endif
+ netif->linkoutput = low_level_output;
+ netif->mtu = 1500;
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+
+ return ERR_OK;
+}
+
+static void eth_init_rings(void)
+{
+ static bool called;
+ int i;
+
+ if (called)
+ return;
+ called = true;
+
+ net_tx_packet = &net_pkt_buf[0] + (PKTALIGN - 1);
+ net_tx_packet -= (ulong)net_tx_packet % PKTALIGN;
+ for (i = 0; i < PKTBUFSRX; i++)
+ net_rx_packets[i] = net_tx_packet + (i + 1) * PKTSIZE_ALIGN;
+}
+
+struct netif *net_lwip_get_netif(void)
+{
+ struct netif *netif, *found = NULL;
+
+ NETIF_FOREACH(netif) {
+ if (!found)
+ found = netif;
+ else
+ printf("Error: more than one netif in lwIP\n");
+ }
+ return found;
+}
+
+static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
+ ip4_addr_t *mask, ip4_addr_t *gw)
+{
+ char ipstr[9] = { 'i', 'p', 'a' , 'd', 'd', 'r', };
+ char maskstr[10] = { 'n', 'e', 't', 'm', 'a', 's', 'k', };
+ char gwstr[12] = { 'g', 'a', 't', 'e', 'w', 'a', 'y', 'i', 'p', };
+ char *env;
+ int ret;
+
+ if (dev_seq(dev) > 0) {
+ ret = snprintf(ipstr, sizeof(ipstr), "ipaddr%d", dev_seq(dev));
+ if (ret < 0 || ret >= sizeof(ipstr))
+ return -1;
+ snprintf(maskstr, sizeof(maskstr), "netmask%d", dev_seq(dev));
+ if (ret < 0 || ret >= sizeof(maskstr))
+ return -1;
+ snprintf(gwstr, sizeof(gwstr), "gw%d", dev_seq(dev));
+ if (ret < 0 || ret >= sizeof(gwstr))
+ return -1;
+ }
+
+ ip4_addr_set_zero(ip);
+ ip4_addr_set_zero(mask);
+ ip4_addr_set_zero(gw);
+
+ env = env_get(ipstr);
+ if (env)
+ ipaddr_aton(env, ip);
+
+ env = env_get(maskstr);
+ if (env)
+ ipaddr_aton(env, mask);
+
+ env = env_get(gwstr);
+ if (env)
+ ipaddr_aton(env, gw);
+
+ return 0;
+}
+
+static struct netif *new_netif(bool with_ip)
+{
+ unsigned char enetaddr[ARP_HLEN];
+ char hwstr[MAC_ADDR_STRLEN];
+ ip4_addr_t ip, mask, gw;
+ struct udevice *dev;
+ struct netif *netif;
+ int ret;
+ static bool first_call = true;
+
+ eth_init_rings();
+
+ if (first_call) {
+ if (eth_init()) {
+ printf("eth_init() error\n");
+ return NULL;
+ }
+ first_call = false;
+ }
+
+ netif_remove(net_lwip_get_netif());
+
+ eth_set_current();
+
+ dev = eth_get_dev();
+ if (!dev)
+ return NULL;
+
+ ip4_addr_set_zero(&ip);
+ ip4_addr_set_zero(&mask);
+ ip4_addr_set_zero(&gw);
+
+ if (with_ip)
+ if (get_udev_ipv4_info(dev, &ip, &mask, &gw) < 0)
+ return NULL;
+
+ eth_env_get_enetaddr_by_index("eth", dev_seq(dev), enetaddr);
+ ret = snprintf(hwstr, MAC_ADDR_STRLEN, "%pM", enetaddr);
+ if (ret < 0 || ret >= MAC_ADDR_STRLEN)
+ return NULL;
+
+ netif = calloc(1, sizeof(struct netif));
+ if (!netif)
+ return NULL;
+
+ netif->name[0] = 'e';
+ netif->name[1] = 't';
+
+ string_to_enetaddr(hwstr, netif->hwaddr);
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+ if (!netif_add(netif, &ip, &mask, &gw, netif, net_lwip_if_init,
+ netif_input)) {
+ printf("error: netif_add() failed\n");
+ free(netif);
+ return NULL;
+ }
+
+ netif_set_up(netif);
+ netif_set_link_up(netif);
+ /* Routing: use this interface to reach the default gateway */
+ netif_set_default(netif);
+
+ return netif;
+}
+
+/* Configure lwIP to use the currently active network device */
+struct netif *net_lwip_new_netif()
+{
+ return new_netif(true);
+}
+
+struct netif *net_lwip_new_netif_noip()
+{
+
+ return new_netif(false);
+}
+
+void net_lwip_remove_netif(struct netif *netif)
+{
+ netif_remove(netif);
+ free(netif);
+}
+
+int net_init(void)
+{
+ net_lwip_new_netif();
+
+ return 0;
+}
+
+static struct pbuf *alloc_pbuf_and_copy(uchar *data, int len)
+{
+ struct pbuf *p, *q;
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (!p) {
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ return NULL;
+ }
+
+ for (q = p; q != NULL; q = q->next) {
+ memcpy(q->payload, data, q->len);
+ data += q->len;
+ }
+
+ LINK_STATS_INC(link.recv);
+
+ return p;
+}
+
+void net_process_received_packet(uchar *in_packet, int len)
+{
+ struct netif *netif;
+ struct pbuf *pbuf;
+
+ if (len < ETHER_HDR_SIZE)
+ return;
+
+#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
+ if (push_packet) {
+ (*push_packet)(in_packet, len);
+ return;
+ }
+#endif
+
+ netif = net_lwip_get_netif();
+ if (!netif)
+ return;
+
+ pbuf = alloc_pbuf_and_copy(in_packet, len);
+ if (!pbuf)
+ return;
+
+ netif->input(pbuf, netif);
+}
+
+u32_t sys_now(void)
+{
+ return get_timer(0);
+}
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
new file mode 100644
index 00000000000..1fa246f55d9
--- /dev/null
+++ b/net-lwip/tftp.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <net-lwip.h>
+
+int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ /* Not implemented */
+ return CMD_RET_FAILURE;
+}
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand
2024-06-17 15:32 ` [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand Jerome Forissier
@ 2024-06-17 16:54 ` Heinrich Schuchardt
2024-06-19 9:37 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Heinrich Schuchardt @ 2024-06-17 16:54 UTC (permalink / raw)
To: Jerome Forissier
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini,
Joe Hershberger, Ramon Fried, Simon Glass, Andrew Davis,
Sumit Garg, Marek Vasut, Bryan Brattlof, Jesse Taube,
Leon M. Busch-George, Eddie James, Mattijs Korpershoek,
AKASHI Takahiro, Francis Laniel, Peter Robinson,
Abdellatif El Khlifi, Shiji Yang, Nikhil M Jain, Artur Rojek,
Yang Xiwen, Yanhong Wang, Kever Yang, Boon Khai Ng,
Neil Armstrong, Jonas Karlman, u-boot
On 17.06.24 17:32, Jerome Forissier wrote:
> Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as
> well as the dhcp command. CMD_TFTPBOOT is selected by BOOTMETH_EFI due
> to this code having an implicit dependency on do_tftpb().
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> ---
> Makefile | 6 +
> boot/Kconfig | 3 +-
> cmd/Kconfig | 26 ++++
> cmd/Makefile | 4 +
> cmd/net-lwip.c | 13 ++
> common/board_r.c | 4 +-
> drivers/net/Kconfig | 2 +-
> include/net-lwip.h | 2 +
> net-lwip/Makefile | 15 +++
> net-lwip/dhcp.c | 99 +++++++++++++++
> net-lwip/eth_internal.h | 35 ++++++
> net-lwip/net-lwip.c | 270 ++++++++++++++++++++++++++++++++++++++++
> net-lwip/tftp.c | 11 ++
> 13 files changed, 486 insertions(+), 4 deletions(-)
> create mode 100644 cmd/net-lwip.c
> create mode 100644 net-lwip/Makefile
> create mode 100644 net-lwip/dhcp.c
> create mode 100644 net-lwip/eth_internal.h
> create mode 100644 net-lwip/net-lwip.c
> create mode 100644 net-lwip/tftp.c
>
> diff --git a/Makefile b/Makefile
> index 0fe1623c550..92a0ab770bb 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -862,6 +862,7 @@ libs-y += env/
> libs-y += lib/
> libs-y += fs/
> libs-$(CONFIG_NET) += net/
> +libs-$(CONFIG_NET_LWIP) += net-lwip/
> libs-y += disk/
> libs-y += drivers/
> libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
> @@ -2132,6 +2133,11 @@ etags:
> cscope:
> $(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) -name '*.[chS]' -print > \
> cscope.files
> +ifdef CONFIG_NET_LWIP
> + echo net/eth-uclass.c net/eth_common.c net/eth_bootdev.c \
> + net/mdio-uclass.c net/mdio-mux-uclass.c >> \
> + cscope.files
> +endif
> @find $(TAG_SUBDIRS) -name '*.[chS]' -type l -print | \
> grep -xvf - cscope.files > cscope.files.no-symlinks; \
> mv cscope.files.no-symlinks cscope.files
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 6f3096c15a6..004e69dd92a 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -378,7 +378,7 @@ config BOOT_DEFAULTS_CMDS
> select CMD_FAT
> select CMD_FS_GENERIC
> select CMD_PART if PARTITIONS
> - select CMD_DHCP if CMD_NET
> + select CMD_DHCP if CMD_NET || CMD_NET_LWIP
> select CMD_PING if CMD_NET
> select CMD_PXE if CMD_NET
> select CMD_BOOTI if ARM64
> @@ -540,6 +540,7 @@ config BOOTMETH_EXTLINUX_PXE
> config BOOTMETH_EFILOADER
> bool "Bootdev support for EFI boot"
> depends on EFI_BINARY_EXEC
> + select CMD_TFTPBOOT if CMD_NET_LWIP
> default y
> help
> Enables support for EFI boot using bootdevs. This makes the
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index b026439c773..1bfa528e945 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2084,6 +2084,32 @@ config CMD_WOL
>
> endif
>
> +if NET_LWIP
> +
> +menuconfig CMD_NET_LWIP
> + bool "Network commands (lwIP)"
> + default y
> +
> +if CMD_NET_LWIP
> +
> +config CMD_DHCP
> + bool "dhcp"
> + select PROT_DHCP_LWIP
> + help
> + Boot image via network using DHCP/TFTP protocol
> +
> +config CMD_TFTPBOOT
> + bool "tftp"
> + select PROT_UDP_LWIP
> + default n
> + help
> + tftpboot - load file via network using TFTP protocol
> + Currently a placeholder (not implemented)
> +
> +endif
> +
> +endif
> +
> menu "Misc commands"
>
> config CMD_2048
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 87133cc27a8..535b6838ca5 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -128,6 +128,10 @@ endif
> obj-$(CONFIG_CMD_MUX) += mux.o
> obj-$(CONFIG_CMD_NAND) += nand.o
> obj-$(CONFIG_CMD_NET) += net.o
> +obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
> +ifdef CONFIG_CMD_NET_LWIP
> +CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
> +endif
> obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
> obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
> obj-$(CONFIG_CMD_ONENAND) += onenand.o
> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
> new file mode 100644
> index 00000000000..82edb5fd2e6
> --- /dev/null
> +++ b/cmd/net-lwip.c
> @@ -0,0 +1,13 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <net.h>
> +
> +#if defined(CONFIG_CMD_DHCP)
> +U_BOOT_CMD(
> + dhcp, 3, 1, do_dhcp,
> + "boot image via network using DHCP/TFTP protocol",
> + "[loadAddress] [[hostIPaddr:]bootfilename]"
> +);
> +#endif
> diff --git a/common/board_r.c b/common/board_r.c
> index da0b80f24ff..6548eb8fdd5 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -472,7 +472,7 @@ static int initr_status_led(void)
> }
> #endif
>
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
> static int initr_net(void)
> {
> puts("Net: ");
> @@ -727,7 +727,7 @@ static init_fnc_t init_sequence_r[] = {
> #ifdef CONFIG_PCI_ENDPOINT
> pci_ep_init,
> #endif
> -#ifdef CONFIG_CMD_NET
> +#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
> INIT_FUNC_WATCHDOG_RESET
> initr_net,
> #endif
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index efc55e45ca8..640c4218518 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -97,7 +97,7 @@ config DSA_SANDBOX
>
> menuconfig NETDEVICES
> bool "Network device support"
> - depends on NET
> + depends on NET || NET_LWIP
> select DM_ETH
> help
> You must select Y to enable any network device support
> diff --git a/include/net-lwip.h b/include/net-lwip.h
> index f5c743b8d11..46cf6875f7e 100644
> --- a/include/net-lwip.h
> +++ b/include/net-lwip.h
> @@ -11,4 +11,6 @@ struct netif *net_lwip_new_netif_noip(void);
> void net_lwip_remove_netif(struct netif *netif);
> struct netif *net_lwip_get_netif(void);
>
> +int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
> +
> #endif /* __NET_LWIP_H__ */
> diff --git a/net-lwip/Makefile b/net-lwip/Makefile
> new file mode 100644
> index 00000000000..a56c32bfa74
> --- /dev/null
> +++ b/net-lwip/Makefile
> @@ -0,0 +1,15 @@
> +ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
> +
> +obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_ETH) += ../net/eth_bootdev.o
> +obj-$(CONFIG_DM_MDIO) += ../net/mdio-uclass.o
> +obj-$(CONFIG_DM_MDIO_MUX) += ../net/mdio-mux-uclass.o
> +obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
> +obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
> +obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
> +obj-$(CONFIG_CMD_DHCP) += dhcp.o
> +obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
> +
> +# Disable this warning as it is triggered by:
> +# sprintf(buf, index ? "foo%d" : "foo", index)
> +# and this is intentional usage.
> +CFLAGS_eth_common.o += -Wno-format-extra-args
> diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
> new file mode 100644
> index 00000000000..38ea565508f
> --- /dev/null
> +++ b/net-lwip/dhcp.c
> @@ -0,0 +1,99 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <console.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <lwip/dhcp.h>
> +#include <lwip/dns.h>
> +#include <lwip/timeouts.h>
> +#include <net.h>
> +#include <time.h>
> +
> +#define DHCP_TIMEOUT_MS 10000
> +
> +#ifdef CONFIG_CMD_TFTPBOOT
> +/* Boot file obtained from DHCP (if present) */
> +static char boot_file_name[DHCP_BOOT_FILE_LEN];
> +#endif
> +
> +static void call_lwip_dhcp_fine_tmr(void *ctx)
> +{
> + dhcp_fine_tmr();
> + sys_timeout(10, call_lwip_dhcp_fine_tmr, NULL);
> +}
> +
> +int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> + unsigned long start;
> + struct netif *netif;
> + struct dhcp *dhcp;
> + bool bound;
> +
> + netif = net_lwip_new_netif_noip();
> + if (!netif)
> + return CMD_RET_FAILURE;
> +
> + start = get_timer(0);
> + dhcp_start(netif);
> + call_lwip_dhcp_fine_tmr(NULL);
> +
> + /* Wait for DHCP to complete */
> + do {
> + eth_rx();
> + sys_check_timeouts();
> + bound = dhcp_supplied_address(netif);
> + if (bound)
> + break;
> + if (ctrlc()) {
> + printf("Abort\n");
> + break;
> + }
> + mdelay(1);
> + } while (get_timer(start) < DHCP_TIMEOUT_MS);
> +
> + sys_untimeout(call_lwip_dhcp_fine_tmr, NULL);
> +
> + if (!bound) {
> + net_lwip_remove_netif(netif);
> + return CMD_RET_FAILURE;
> + }
> +
> + dhcp = netif_dhcp_data(netif);
> +
> + env_set("bootfile", dhcp->boot_file_name);
> + if (dhcp->offered_gw_addr.addr != 0)
> + env_set("gatewayip", ip4addr_ntoa(&dhcp->offered_gw_addr));
> + env_set("ipaddr", ip4addr_ntoa(&dhcp->offered_ip_addr));
> + env_set("netmask", ip4addr_ntoa(&dhcp->offered_sn_mask));
> + env_set("serverip", ip4addr_ntoa(&dhcp->server_ip_addr));
> +#ifdef CONFIG_PROT_DNS_LWIP
> + env_set("dnsip", ip4addr_ntoa(dns_getserver(0)));
> + env_set("dnsip2", ip4addr_ntoa(dns_getserver(1)));
> +#endif
> +#ifdef CONFIG_CMD_TFTPBOOT
> + if (dhcp->boot_file_name[0] != '\0')
> + strncpy(boot_file_name, dhcp->boot_file_name,
> + sizeof(boot_file_name));
> +#endif
> +
> + printf("DHCP client bound to address %pI4 (%lu ms)\n",
> + &dhcp->offered_ip_addr, get_timer(start));
> +
> + net_lwip_remove_netif(netif);
> + return CMD_RET_SUCCESS;
> +}
> +
> +int dhcp_run(ulong addr, const char *fname, bool autoload)
> +{
> + char *dhcp_argv[] = {"dhcp", NULL, };
> + struct cmd_tbl cmdtp = {}; /* dummy */
> +
> + if (autoload) {
> + /* Will be supported when TFTP is added */
> + return -EOPNOTSUPP;
> + }
> +
> + return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
> +}
> diff --git a/net-lwip/eth_internal.h b/net-lwip/eth_internal.h
> new file mode 100644
> index 00000000000..0b829a8d388
> --- /dev/null
> +++ b/net-lwip/eth_internal.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2001-2015
> + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
> + * Joe Hershberger, National Instruments
> + */
> +
> +#ifndef __ETH_INTERNAL_H
> +#define __ETH_INTERNAL_H
> +
> +/* Do init that is common to driver model and legacy networking */
> +void eth_common_init(void);
> +
> +/**
> + * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
> + *
> + * This sets up an environment variable with the given MAC address (@enetaddr).
> + * The environment variable to be set is defined by <@base_name><@index>addr.
> + * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
> + * eth1addr, etc.
> + *
> + * @base_name: Base name for variable, typically "eth"
> + * @index: Index of interface being updated (>=0)
> + * @enetaddr: Pointer to MAC address to put into the variable
> + * Return: 0 if OK, other value on error
> + */
> +int eth_env_set_enetaddr_by_index(const char *base_name, int index,
> + uchar *enetaddr);
> +
> +int eth_mac_skip(int index);
> +void eth_current_changed(void);
> +void eth_set_dev(struct udevice *dev);
> +void eth_set_current_to_next(void);
> +
> +#endif
> diff --git a/net-lwip/net-lwip.c b/net-lwip/net-lwip.c
> new file mode 100644
> index 00000000000..39e7e51e542
> --- /dev/null
> +++ b/net-lwip/net-lwip.c
> @@ -0,0 +1,270 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <dm/device.h>
> +#include <dm/uclass.h>
> +#include <lwip/ip4_addr.h>
> +#include <lwip/err.h>
> +#include <lwip/netif.h>
> +#include <lwip/pbuf.h>
> +#include <lwip/etharp.h>
> +#include <lwip/prot/etharp.h>
> +#include <net.h>
> +
> +/* xx:xx:xx:xx:xx:xx\0 */
> +#define MAC_ADDR_STRLEN 18
> +
> +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
> +void (*push_packet)(void *, int len) = 0;
> +#endif
> +int net_restart_wrap;
> +static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
> +uchar *net_rx_packets[PKTBUFSRX];
> +uchar *net_rx_packet;
> +uchar *net_tx_packet;
> +
> +static err_t low_level_output(struct netif *netif, struct pbuf *p)
> +{
> + int err;
> +
> + /*
> + * lwIP is alwys configured to use one device, the active one, so
> + * there is no need to use the netif parameter.
> + */
> +
> + /* switch dev to active state */
> + eth_init_state_only();
> +
> + err = eth_send(p->payload, p->len);
> + if (err) {
> + log_err("eth_send error %d\n", err);
> + return ERR_ABRT;
> + }
> + return ERR_OK;
> +}
> +
> +static err_t net_lwip_if_init(struct netif *netif)
> +{
> +#if LWIP_IPV4
> + netif->output = etharp_output;
> +#endif
> + netif->linkoutput = low_level_output;
> + netif->mtu = 1500;
> + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
> +
> + return ERR_OK;
> +}
> +
> +static void eth_init_rings(void)
> +{
> + static bool called;
> + int i;
> +
> + if (called)
> + return;
> + called = true;
> +
> + net_tx_packet = &net_pkt_buf[0] + (PKTALIGN - 1);
> + net_tx_packet -= (ulong)net_tx_packet % PKTALIGN;
> + for (i = 0; i < PKTBUFSRX; i++)
> + net_rx_packets[i] = net_tx_packet + (i + 1) * PKTSIZE_ALIGN;
> +}
> +
> +struct netif *net_lwip_get_netif(void)
> +{
> + struct netif *netif, *found = NULL;
> +
> + NETIF_FOREACH(netif) {
> + if (!found)
> + found = netif;
> + else
> + printf("Error: more than one netif in lwIP\n");
> + }
> + return found;
> +}
> +
> +static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
> + ip4_addr_t *mask, ip4_addr_t *gw)
> +{
> + char ipstr[9] = { 'i', 'p', 'a' , 'd', 'd', 'r', };
> + char maskstr[10] = { 'n', 'e', 't', 'm', 'a', 's', 'k', };
> + char gwstr[12] = { 'g', 'a', 't', 'e', 'w', 'a', 'y', 'i', 'p', };
> + char *env;
> + int ret;
> +
> + if (dev_seq(dev) > 0) {
> + ret = snprintf(ipstr, sizeof(ipstr), "ipaddr%d", dev_seq(dev));
> + if (ret < 0 || ret >= sizeof(ipstr))
> + return -1;
> + snprintf(maskstr, sizeof(maskstr), "netmask%d", dev_seq(dev));
> + if (ret < 0 || ret >= sizeof(maskstr))
> + return -1;
> + snprintf(gwstr, sizeof(gwstr), "gw%d", dev_seq(dev));
> + if (ret < 0 || ret >= sizeof(gwstr))
> + return -1;
> + }
> +
> + ip4_addr_set_zero(ip);
> + ip4_addr_set_zero(mask);
> + ip4_addr_set_zero(gw);
> +
> + env = env_get(ipstr);
> + if (env)
> + ipaddr_aton(env, ip);
> +
> + env = env_get(maskstr);
> + if (env)
> + ipaddr_aton(env, mask);
> +
> + env = env_get(gwstr);
> + if (env)
> + ipaddr_aton(env, gw);
> +
> + return 0;
> +}
> +
> +static struct netif *new_netif(bool with_ip)
> +{
> + unsigned char enetaddr[ARP_HLEN];
> + char hwstr[MAC_ADDR_STRLEN];
> + ip4_addr_t ip, mask, gw;
> + struct udevice *dev;
> + struct netif *netif;
This does not fit into the driver model.
In the EFI subsystem we want to implement network protocols like the
EFI_DHCP4_PROTOCOL.
Please, carve out functions to which we can pass a UCLASS_ETH udevice to
execute DHCP.
> + int ret;
> + static bool first_call = true;
> +
> + eth_init_rings();
> +
> + if (first_call) {
> + if (eth_init()) {
> + printf("eth_init() error\n");
> + return NULL;
> + }
> + first_call = false;
> + }
> +
> + netif_remove(net_lwip_get_netif());
> +
> + eth_set_current();
> +
> + dev = eth_get_dev();
> + if (!dev)
> + return NULL;
> +
> + ip4_addr_set_zero(&ip);
> + ip4_addr_set_zero(&mask);
> + ip4_addr_set_zero(&gw);
> +
> + if (with_ip)
> + if (get_udev_ipv4_info(dev, &ip, &mask, &gw) < 0)
> + return NULL;
> +
> + eth_env_get_enetaddr_by_index("eth", dev_seq(dev), enetaddr);
> + ret = snprintf(hwstr, MAC_ADDR_STRLEN, "%pM", enetaddr);
> + if (ret < 0 || ret >= MAC_ADDR_STRLEN)
> + return NULL;
> +
> + netif = calloc(1, sizeof(struct netif));
> + if (!netif)
> + return NULL;
> +
> + netif->name[0] = 'e';
> + netif->name[1] = 't';
> +
> + string_to_enetaddr(hwstr, netif->hwaddr);
> + netif->hwaddr_len = ETHARP_HWADDR_LEN;
> +
> + if (!netif_add(netif, &ip, &mask, &gw, netif, net_lwip_if_init,
> + netif_input)) {
> + printf("error: netif_add() failed\n");
> + free(netif);
> + return NULL;
> + }
> +
> + netif_set_up(netif);
> + netif_set_link_up(netif);
> + /* Routing: use this interface to reach the default gateway */
> + netif_set_default(netif);
> +
> + return netif;
> +}
> +
> +/* Configure lwIP to use the currently active network device */
> +struct netif *net_lwip_new_netif()
> +{
> + return new_netif(true);
> +}
> +
> +struct netif *net_lwip_new_netif_noip()
> +{
> +
> + return new_netif(false);
> +}
> +
> +void net_lwip_remove_netif(struct netif *netif)
> +{
> + netif_remove(netif);
> + free(netif);
> +}
> +
> +int net_init(void)
> +{
> + net_lwip_new_netif();
> +
> + return 0;
> +}
> +
> +static struct pbuf *alloc_pbuf_and_copy(uchar *data, int len)
> +{
> + struct pbuf *p, *q;
> +
> + /* We allocate a pbuf chain of pbufs from the pool. */
> + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
> + if (!p) {
> + LINK_STATS_INC(link.memerr);
> + LINK_STATS_INC(link.drop);
> + return NULL;
> + }
> +
> + for (q = p; q != NULL; q = q->next) {
> + memcpy(q->payload, data, q->len);
> + data += q->len;
> + }
> +
> + LINK_STATS_INC(link.recv);
> +
> + return p;
> +}
> +
> +void net_process_received_packet(uchar *in_packet, int len)
Library functions should take a udevice as an argument. Please, do not
use the concept of "active device" in these library functions.
The command line interface may implement such a concept for backwards
compatibility.
Best regards
Heinrich
> +{
> + struct netif *netif;
> + struct pbuf *pbuf;
> +
> + if (len < ETHER_HDR_SIZE)
> + return;
> +
> +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
> + if (push_packet) {
> + (*push_packet)(in_packet, len);
> + return;
> + }
> +#endif
> +
> + netif = net_lwip_get_netif();
> + if (!netif)
> + return;
> +
> + pbuf = alloc_pbuf_and_copy(in_packet, len);
> + if (!pbuf)
> + return;
> +
> + netif->input(pbuf, netif);
> +}
> +
> +u32_t sys_now(void)
> +{
> + return get_timer(0);
> +}
> diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
> new file mode 100644
> index 00000000000..1fa246f55d9
> --- /dev/null
> +++ b/net-lwip/tftp.c
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <net-lwip.h>
> +
> +int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> + /* Not implemented */
> + return CMD_RET_FAILURE;
> +}
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand
2024-06-17 16:54 ` Heinrich Schuchardt
@ 2024-06-19 9:37 ` Jerome Forissier
2024-06-19 10:07 ` Ilias Apalodimas
0 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-19 9:37 UTC (permalink / raw)
To: Heinrich Schuchardt
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini,
Joe Hershberger, Ramon Fried, Simon Glass, Andrew Davis,
Sumit Garg, Marek Vasut, Bryan Brattlof, Jesse Taube,
Leon M. Busch-George, Eddie James, Mattijs Korpershoek,
AKASHI Takahiro, Francis Laniel, Peter Robinson,
Abdellatif El Khlifi, Shiji Yang, Nikhil M Jain, Artur Rojek,
Yang Xiwen, Yanhong Wang, Kever Yang, Boon Khai Ng,
Neil Armstrong, Jonas Karlman, u-boot
On 6/17/24 18:54, Heinrich Schuchardt wrote:
> On 17.06.24 17:32, Jerome Forissier wrote:
>> Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as
>> well as the dhcp command. CMD_TFTPBOOT is selected by BOOTMETH_EFI due
>> to this code having an implicit dependency on do_tftpb().
>>
>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>> ---
>> Makefile | 6 +
>> boot/Kconfig | 3 +-
>> cmd/Kconfig | 26 ++++
>> cmd/Makefile | 4 +
>> cmd/net-lwip.c | 13 ++
>> common/board_r.c | 4 +-
>> drivers/net/Kconfig | 2 +-
>> include/net-lwip.h | 2 +
>> net-lwip/Makefile | 15 +++
>> net-lwip/dhcp.c | 99 +++++++++++++++
>> net-lwip/eth_internal.h | 35 ++++++
>> net-lwip/net-lwip.c | 270 ++++++++++++++++++++++++++++++++++++++++
>> net-lwip/tftp.c | 11 ++
>> 13 files changed, 486 insertions(+), 4 deletions(-)
>> create mode 100644 cmd/net-lwip.c
>> create mode 100644 net-lwip/Makefile
>> create mode 100644 net-lwip/dhcp.c
>> create mode 100644 net-lwip/eth_internal.h
>> create mode 100644 net-lwip/net-lwip.c
>> create mode 100644 net-lwip/tftp.c
>>
>> diff --git a/Makefile b/Makefile
>> index 0fe1623c550..92a0ab770bb 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -862,6 +862,7 @@ libs-y += env/
>> libs-y += lib/
>> libs-y += fs/
>> libs-$(CONFIG_NET) += net/
>> +libs-$(CONFIG_NET_LWIP) += net-lwip/
>> libs-y += disk/
>> libs-y += drivers/
>> libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
>> @@ -2132,6 +2133,11 @@ etags:
>> cscope:
>> $(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) -name '*.[chS]' -print > \
>> cscope.files
>> +ifdef CONFIG_NET_LWIP
>> + echo net/eth-uclass.c net/eth_common.c net/eth_bootdev.c \
>> + net/mdio-uclass.c net/mdio-mux-uclass.c >> \
>> + cscope.files
>> +endif
>> @find $(TAG_SUBDIRS) -name '*.[chS]' -type l -print | \
>> grep -xvf - cscope.files > cscope.files.no-symlinks; \
>> mv cscope.files.no-symlinks cscope.files
>> diff --git a/boot/Kconfig b/boot/Kconfig
>> index 6f3096c15a6..004e69dd92a 100644
>> --- a/boot/Kconfig
>> +++ b/boot/Kconfig
>> @@ -378,7 +378,7 @@ config BOOT_DEFAULTS_CMDS
>> select CMD_FAT
>> select CMD_FS_GENERIC
>> select CMD_PART if PARTITIONS
>> - select CMD_DHCP if CMD_NET
>> + select CMD_DHCP if CMD_NET || CMD_NET_LWIP
>> select CMD_PING if CMD_NET
>> select CMD_PXE if CMD_NET
>> select CMD_BOOTI if ARM64
>> @@ -540,6 +540,7 @@ config BOOTMETH_EXTLINUX_PXE
>> config BOOTMETH_EFILOADER
>> bool "Bootdev support for EFI boot"
>> depends on EFI_BINARY_EXEC
>> + select CMD_TFTPBOOT if CMD_NET_LWIP
>> default y
>> help
>> Enables support for EFI boot using bootdevs. This makes the
>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>> index b026439c773..1bfa528e945 100644
>> --- a/cmd/Kconfig
>> +++ b/cmd/Kconfig
>> @@ -2084,6 +2084,32 @@ config CMD_WOL
>>
>> endif
>>
>> +if NET_LWIP
>> +
>> +menuconfig CMD_NET_LWIP
>> + bool "Network commands (lwIP)"
>> + default y
>> +
>> +if CMD_NET_LWIP
>> +
>> +config CMD_DHCP
>> + bool "dhcp"
>> + select PROT_DHCP_LWIP
>> + help
>> + Boot image via network using DHCP/TFTP protocol
>> +
>> +config CMD_TFTPBOOT
>> + bool "tftp"
>> + select PROT_UDP_LWIP
>> + default n
>> + help
>> + tftpboot - load file via network using TFTP protocol
>> + Currently a placeholder (not implemented)
>> +
>> +endif
>> +
>> +endif
>> +
>> menu "Misc commands"
>>
>> config CMD_2048
>> diff --git a/cmd/Makefile b/cmd/Makefile
>> index 87133cc27a8..535b6838ca5 100644
>> --- a/cmd/Makefile
>> +++ b/cmd/Makefile
>> @@ -128,6 +128,10 @@ endif
>> obj-$(CONFIG_CMD_MUX) += mux.o
>> obj-$(CONFIG_CMD_NAND) += nand.o
>> obj-$(CONFIG_CMD_NET) += net.o
>> +obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
>> +ifdef CONFIG_CMD_NET_LWIP
>> +CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
>> +endif
>> obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
>> obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
>> obj-$(CONFIG_CMD_ONENAND) += onenand.o
>> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
>> new file mode 100644
>> index 00000000000..82edb5fd2e6
>> --- /dev/null
>> +++ b/cmd/net-lwip.c
>> @@ -0,0 +1,13 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <net.h>
>> +
>> +#if defined(CONFIG_CMD_DHCP)
>> +U_BOOT_CMD(
>> + dhcp, 3, 1, do_dhcp,
>> + "boot image via network using DHCP/TFTP protocol",
>> + "[loadAddress] [[hostIPaddr:]bootfilename]"
>> +);
>> +#endif
>> diff --git a/common/board_r.c b/common/board_r.c
>> index da0b80f24ff..6548eb8fdd5 100644
>> --- a/common/board_r.c
>> +++ b/common/board_r.c
>> @@ -472,7 +472,7 @@ static int initr_status_led(void)
>> }
>> #endif
>>
>> -#ifdef CONFIG_CMD_NET
>> +#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
>> static int initr_net(void)
>> {
>> puts("Net: ");
>> @@ -727,7 +727,7 @@ static init_fnc_t init_sequence_r[] = {
>> #ifdef CONFIG_PCI_ENDPOINT
>> pci_ep_init,
>> #endif
>> -#ifdef CONFIG_CMD_NET
>> +#if defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_NET_LWIP)
>> INIT_FUNC_WATCHDOG_RESET
>> initr_net,
>> #endif
>> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> index efc55e45ca8..640c4218518 100644
>> --- a/drivers/net/Kconfig
>> +++ b/drivers/net/Kconfig
>> @@ -97,7 +97,7 @@ config DSA_SANDBOX
>>
>> menuconfig NETDEVICES
>> bool "Network device support"
>> - depends on NET
>> + depends on NET || NET_LWIP
>> select DM_ETH
>> help
>> You must select Y to enable any network device support
>> diff --git a/include/net-lwip.h b/include/net-lwip.h
>> index f5c743b8d11..46cf6875f7e 100644
>> --- a/include/net-lwip.h
>> +++ b/include/net-lwip.h
>> @@ -11,4 +11,6 @@ struct netif *net_lwip_new_netif_noip(void);
>> void net_lwip_remove_netif(struct netif *netif);
>> struct netif *net_lwip_get_netif(void);
>>
>> +int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>> +
>> #endif /* __NET_LWIP_H__ */
>> diff --git a/net-lwip/Makefile b/net-lwip/Makefile
>> new file mode 100644
>> index 00000000000..a56c32bfa74
>> --- /dev/null
>> +++ b/net-lwip/Makefile
>> @@ -0,0 +1,15 @@
>> +ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
>> +
>> +obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_ETH) += ../net/eth_bootdev.o
>> +obj-$(CONFIG_DM_MDIO) += ../net/mdio-uclass.o
>> +obj-$(CONFIG_DM_MDIO_MUX) += ../net/mdio-mux-uclass.o
>> +obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
>> +obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
>> +obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
>> +obj-$(CONFIG_CMD_DHCP) += dhcp.o
>> +obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>> +
>> +# Disable this warning as it is triggered by:
>> +# sprintf(buf, index ? "foo%d" : "foo", index)
>> +# and this is intentional usage.
>> +CFLAGS_eth_common.o += -Wno-format-extra-args
>> diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
>> new file mode 100644
>> index 00000000000..38ea565508f
>> --- /dev/null
>> +++ b/net-lwip/dhcp.c
>> @@ -0,0 +1,99 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <console.h>
>> +#include <linux/delay.h>
>> +#include <linux/errno.h>
>> +#include <lwip/dhcp.h>
>> +#include <lwip/dns.h>
>> +#include <lwip/timeouts.h>
>> +#include <net.h>
>> +#include <time.h>
>> +
>> +#define DHCP_TIMEOUT_MS 10000
>> +
>> +#ifdef CONFIG_CMD_TFTPBOOT
>> +/* Boot file obtained from DHCP (if present) */
>> +static char boot_file_name[DHCP_BOOT_FILE_LEN];
>> +#endif
>> +
>> +static void call_lwip_dhcp_fine_tmr(void *ctx)
>> +{
>> + dhcp_fine_tmr();
>> + sys_timeout(10, call_lwip_dhcp_fine_tmr, NULL);
>> +}
>> +
>> +int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> + unsigned long start;
>> + struct netif *netif;
>> + struct dhcp *dhcp;
>> + bool bound;
>> +
>> + netif = net_lwip_new_netif_noip();
>> + if (!netif)
>> + return CMD_RET_FAILURE;
>> +
>> + start = get_timer(0);
>> + dhcp_start(netif);
>> + call_lwip_dhcp_fine_tmr(NULL);
>> +
>> + /* Wait for DHCP to complete */
>> + do {
>> + eth_rx();
>> + sys_check_timeouts();
>> + bound = dhcp_supplied_address(netif);
>> + if (bound)
>> + break;
>> + if (ctrlc()) {
>> + printf("Abort\n");
>> + break;
>> + }
>> + mdelay(1);
>> + } while (get_timer(start) < DHCP_TIMEOUT_MS);
>> +
>> + sys_untimeout(call_lwip_dhcp_fine_tmr, NULL);
>> +
>> + if (!bound) {
>> + net_lwip_remove_netif(netif);
>> + return CMD_RET_FAILURE;
>> + }
>> +
>> + dhcp = netif_dhcp_data(netif);
>> +
>> + env_set("bootfile", dhcp->boot_file_name);
>> + if (dhcp->offered_gw_addr.addr != 0)
>> + env_set("gatewayip", ip4addr_ntoa(&dhcp->offered_gw_addr));
>> + env_set("ipaddr", ip4addr_ntoa(&dhcp->offered_ip_addr));
>> + env_set("netmask", ip4addr_ntoa(&dhcp->offered_sn_mask));
>> + env_set("serverip", ip4addr_ntoa(&dhcp->server_ip_addr));
>> +#ifdef CONFIG_PROT_DNS_LWIP
>> + env_set("dnsip", ip4addr_ntoa(dns_getserver(0)));
>> + env_set("dnsip2", ip4addr_ntoa(dns_getserver(1)));
>> +#endif
>> +#ifdef CONFIG_CMD_TFTPBOOT
>> + if (dhcp->boot_file_name[0] != '\0')
>> + strncpy(boot_file_name, dhcp->boot_file_name,
>> + sizeof(boot_file_name));
>> +#endif
>> +
>> + printf("DHCP client bound to address %pI4 (%lu ms)\n",
>> + &dhcp->offered_ip_addr, get_timer(start));
>> +
>> + net_lwip_remove_netif(netif);
>> + return CMD_RET_SUCCESS;
>> +}
>> +
>> +int dhcp_run(ulong addr, const char *fname, bool autoload)
>> +{
>> + char *dhcp_argv[] = {"dhcp", NULL, };
>> + struct cmd_tbl cmdtp = {}; /* dummy */
>> +
>> + if (autoload) {
>> + /* Will be supported when TFTP is added */
>> + return -EOPNOTSUPP;
>> + }
>> +
>> + return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
>> +}
>> diff --git a/net-lwip/eth_internal.h b/net-lwip/eth_internal.h
>> new file mode 100644
>> index 00000000000..0b829a8d388
>> --- /dev/null
>> +++ b/net-lwip/eth_internal.h
>> @@ -0,0 +1,35 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * (C) Copyright 2001-2015
>> + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
>> + * Joe Hershberger, National Instruments
>> + */
>> +
>> +#ifndef __ETH_INTERNAL_H
>> +#define __ETH_INTERNAL_H
>> +
>> +/* Do init that is common to driver model and legacy networking */
>> +void eth_common_init(void);
>> +
>> +/**
>> + * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
>> + *
>> + * This sets up an environment variable with the given MAC address (@enetaddr).
>> + * The environment variable to be set is defined by <@base_name><@index>addr.
>> + * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
>> + * eth1addr, etc.
>> + *
>> + * @base_name: Base name for variable, typically "eth"
>> + * @index: Index of interface being updated (>=0)
>> + * @enetaddr: Pointer to MAC address to put into the variable
>> + * Return: 0 if OK, other value on error
>> + */
>> +int eth_env_set_enetaddr_by_index(const char *base_name, int index,
>> + uchar *enetaddr);
>> +
>> +int eth_mac_skip(int index);
>> +void eth_current_changed(void);
>> +void eth_set_dev(struct udevice *dev);
>> +void eth_set_current_to_next(void);
>> +
>> +#endif
>> diff --git a/net-lwip/net-lwip.c b/net-lwip/net-lwip.c
>> new file mode 100644
>> index 00000000000..39e7e51e542
>> --- /dev/null
>> +++ b/net-lwip/net-lwip.c
>> @@ -0,0 +1,270 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <dm/device.h>
>> +#include <dm/uclass.h>
>> +#include <lwip/ip4_addr.h>
>> +#include <lwip/err.h>
>> +#include <lwip/netif.h>
>> +#include <lwip/pbuf.h>
>> +#include <lwip/etharp.h>
>> +#include <lwip/prot/etharp.h>
>> +#include <net.h>
>> +
>> +/* xx:xx:xx:xx:xx:xx\0 */
>> +#define MAC_ADDR_STRLEN 18
>> +
>> +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
>> +void (*push_packet)(void *, int len) = 0;
>> +#endif
>> +int net_restart_wrap;
>> +static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
>> +uchar *net_rx_packets[PKTBUFSRX];
>> +uchar *net_rx_packet;
>> +uchar *net_tx_packet;
>> +
>> +static err_t low_level_output(struct netif *netif, struct pbuf *p)
>> +{
>> + int err;
>> +
>> + /*
>> + * lwIP is alwys configured to use one device, the active one, so
>> + * there is no need to use the netif parameter.
>> + */
>> +
>> + /* switch dev to active state */
>> + eth_init_state_only();
>> +
>> + err = eth_send(p->payload, p->len);
>> + if (err) {
>> + log_err("eth_send error %d\n", err);
>> + return ERR_ABRT;
>> + }
>> + return ERR_OK;
>> +}
>> +
>> +static err_t net_lwip_if_init(struct netif *netif)
>> +{
>> +#if LWIP_IPV4
>> + netif->output = etharp_output;
>> +#endif
>> + netif->linkoutput = low_level_output;
>> + netif->mtu = 1500;
>> + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
>> +
>> + return ERR_OK;
>> +}
>> +
>> +static void eth_init_rings(void)
>> +{
>> + static bool called;
>> + int i;
>> +
>> + if (called)
>> + return;
>> + called = true;
>> +
>> + net_tx_packet = &net_pkt_buf[0] + (PKTALIGN - 1);
>> + net_tx_packet -= (ulong)net_tx_packet % PKTALIGN;
>> + for (i = 0; i < PKTBUFSRX; i++)
>> + net_rx_packets[i] = net_tx_packet + (i + 1) * PKTSIZE_ALIGN;
>> +}
>> +
>> +struct netif *net_lwip_get_netif(void)
>> +{
>> + struct netif *netif, *found = NULL;
>> +
>> + NETIF_FOREACH(netif) {
>> + if (!found)
>> + found = netif;
>> + else
>> + printf("Error: more than one netif in lwIP\n");
>> + }
>> + return found;
>> +}
>> +
>> +static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
>> + ip4_addr_t *mask, ip4_addr_t *gw)
>> +{
>> + char ipstr[9] = { 'i', 'p', 'a' , 'd', 'd', 'r', };
>> + char maskstr[10] = { 'n', 'e', 't', 'm', 'a', 's', 'k', };
>> + char gwstr[12] = { 'g', 'a', 't', 'e', 'w', 'a', 'y', 'i', 'p', };
>> + char *env;
>> + int ret;
>> +
>> + if (dev_seq(dev) > 0) {
>> + ret = snprintf(ipstr, sizeof(ipstr), "ipaddr%d", dev_seq(dev));
>> + if (ret < 0 || ret >= sizeof(ipstr))
>> + return -1;
>> + snprintf(maskstr, sizeof(maskstr), "netmask%d", dev_seq(dev));
>> + if (ret < 0 || ret >= sizeof(maskstr))
>> + return -1;
>> + snprintf(gwstr, sizeof(gwstr), "gw%d", dev_seq(dev));
>> + if (ret < 0 || ret >= sizeof(gwstr))
>> + return -1;
>> + }
>> +
>> + ip4_addr_set_zero(ip);
>> + ip4_addr_set_zero(mask);
>> + ip4_addr_set_zero(gw);
>> +
>> + env = env_get(ipstr);
>> + if (env)
>> + ipaddr_aton(env, ip);
>> +
>> + env = env_get(maskstr);
>> + if (env)
>> + ipaddr_aton(env, mask);
>> +
>> + env = env_get(gwstr);
>> + if (env)
>> + ipaddr_aton(env, gw);
>> +
>> + return 0;
>> +}
>> +
>> +static struct netif *new_netif(bool with_ip)
>> +{
>> + unsigned char enetaddr[ARP_HLEN];
>> + char hwstr[MAC_ADDR_STRLEN];
>> + ip4_addr_t ip, mask, gw;
>> + struct udevice *dev;
>> + struct netif *netif;
>
> This does not fit into the driver model.
>
> In the EFI subsystem we want to implement network protocols like the
> EFI_DHCP4_PROTOCOL.
>
> Please, carve out functions to which we can pass a UCLASS_ETH udevice to
> execute DHCP.
v6 will have:
static struct netif *new_netif(struct udevice *udev, bool with_ip)
struct netif *net_lwip_new_netif(struct udevice *udev)
struct netif *net_lwip_new_netif_noip(struct udevice *udev)
static int dhcp_loop(struct udevice *udev)
>
>> + int ret;
>> + static bool first_call = true;
>> +
>> + eth_init_rings();
>> +
>> + if (first_call) {
>> + if (eth_init()) {
>> + printf("eth_init() error\n");
>> + return NULL;
>> + }
>> + first_call = false;
>> + }
>> +
>> + netif_remove(net_lwip_get_netif());
>> +
>> + eth_set_current();
>> +
>> + dev = eth_get_dev();
>> + if (!dev)
>> + return NULL;
>> +
>> + ip4_addr_set_zero(&ip);
>> + ip4_addr_set_zero(&mask);
>> + ip4_addr_set_zero(&gw);
>> +
>> + if (with_ip)
>> + if (get_udev_ipv4_info(dev, &ip, &mask, &gw) < 0)
>> + return NULL;
>> +
>> + eth_env_get_enetaddr_by_index("eth", dev_seq(dev), enetaddr);
>> + ret = snprintf(hwstr, MAC_ADDR_STRLEN, "%pM", enetaddr);
>> + if (ret < 0 || ret >= MAC_ADDR_STRLEN)
>> + return NULL;
>> +
>> + netif = calloc(1, sizeof(struct netif));
>> + if (!netif)
>> + return NULL;
>> +
>> + netif->name[0] = 'e';
>> + netif->name[1] = 't';
>> +
>> + string_to_enetaddr(hwstr, netif->hwaddr);
>> + netif->hwaddr_len = ETHARP_HWADDR_LEN;
>> +
>> + if (!netif_add(netif, &ip, &mask, &gw, netif, net_lwip_if_init,
>> + netif_input)) {
>> + printf("error: netif_add() failed\n");
>> + free(netif);
>> + return NULL;
>> + }
>> +
>> + netif_set_up(netif);
>> + netif_set_link_up(netif);
>> + /* Routing: use this interface to reach the default gateway */
>> + netif_set_default(netif);
>> +
>> + return netif;
>> +}
>> +
>> +/* Configure lwIP to use the currently active network device */
>> +struct netif *net_lwip_new_netif()
>> +{
>> + return new_netif(true);
>> +}
>> +
>> +struct netif *net_lwip_new_netif_noip()
>> +{
>> +
>> + return new_netif(false);
>> +}
>> +
>> +void net_lwip_remove_netif(struct netif *netif)
>> +{
>> + netif_remove(netif);
>> + free(netif);
>> +}
>> +
>> +int net_init(void)
>> +{
>> + net_lwip_new_netif();
>> +
>> + return 0;
>> +}
>> +
>> +static struct pbuf *alloc_pbuf_and_copy(uchar *data, int len)
>> +{
>> + struct pbuf *p, *q;
>> +
>> + /* We allocate a pbuf chain of pbufs from the pool. */
>> + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
>> + if (!p) {
>> + LINK_STATS_INC(link.memerr);
>> + LINK_STATS_INC(link.drop);
>> + return NULL;
>> + }
>> +
>> + for (q = p; q != NULL; q = q->next) {
>> + memcpy(q->payload, data, q->len);
>> + data += q->len;
>> + }
>> +
>> + LINK_STATS_INC(link.recv);
>> +
>> + return p;
>> +}
>> +
>> +void net_process_received_packet(uchar *in_packet, int len)
>
> Library functions should take a udevice as an argument. Please, do not
> use the concept of "active device" in these library functions.
OK, I have unified the naming in v6 and all functions will take a udevice:
static int dhcp_loop(struct udevice *udev)
static int dns_loop(struct udevice *udev, const char *name, const char *var)
static int ping_loop(struct udevice *udev, const ip_addr_t* addr)
static int tftp_loop(struct udevice *udev, ulong addr, char *fname,
ip_addr_t srvip)
static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
>
> The command line interface may implement such a concept for backwards
> compatibility.
Sure.
Thanks,
--
Jerome
>
> Best regards
>
> Heinrich
>
>> +{
>> + struct netif *netif;
>> + struct pbuf *pbuf;
>> +
>> + if (len < ETHER_HDR_SIZE)
>> + return;
>> +
>> +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
>> + if (push_packet) {
>> + (*push_packet)(in_packet, len);
>> + return;
>> + }
>> +#endif
>> +
>> + netif = net_lwip_get_netif();
>> + if (!netif)
>> + return;
>> +
>> + pbuf = alloc_pbuf_and_copy(in_packet, len);
>> + if (!pbuf)
>> + return;
>> +
>> + netif->input(pbuf, netif);
>> +}
>> +
>> +u32_t sys_now(void)
>> +{
>> + return get_timer(0);
>> +}
>> diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
>> new file mode 100644
>> index 00000000000..1fa246f55d9
>> --- /dev/null
>> +++ b/net-lwip/tftp.c
>> @@ -0,0 +1,11 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <net-lwip.h>
>> +
>> +int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> + /* Not implemented */
>> + return CMD_RET_FAILURE;
>> +}
>
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand
2024-06-19 9:37 ` Jerome Forissier
@ 2024-06-19 10:07 ` Ilias Apalodimas
0 siblings, 0 replies; 53+ messages in thread
From: Ilias Apalodimas @ 2024-06-19 10:07 UTC (permalink / raw)
To: Jerome Forissier, Heinrich Schuchardt
Cc: Javier Tia, Maxim Uvarov, Tom Rini, Joe Hershberger, Ramon Fried,
Simon Glass, Andrew Davis, Sumit Garg, Marek Vasut,
Bryan Brattlof, Jesse Taube, Leon M. Busch-George, Eddie James,
Mattijs Korpershoek, AKASHI Takahiro, Francis Laniel,
Peter Robinson, Abdellatif El Khlifi, Shiji Yang, Nikhil M Jain,
Artur Rojek, Yang Xiwen, Yanhong Wang, Kever Yang, Boon Khai Ng,
Neil Armstrong, Jonas Karlman, u-boot
[...]
> >> +
> >> +static struct netif *new_netif(bool with_ip)
> >> +{
> >> + unsigned char enetaddr[ARP_HLEN];
> >> + char hwstr[MAC_ADDR_STRLEN];
> >> + ip4_addr_t ip, mask, gw;
> >> + struct udevice *dev;
> >> + struct netif *netif;
> >
> > This does not fit into the driver model.
> >
> > In the EFI subsystem we want to implement network protocols like the
> > EFI_DHCP4_PROTOCOL.
> >
> > Please, carve out functions to which we can pass a UCLASS_ETH udevice to
> > execute DHCP.
>
> v6 will have:
>
> static struct netif *new_netif(struct udevice *udev, bool with_ip)
> struct netif *net_lwip_new_netif(struct udevice *udev)
> struct netif *net_lwip_new_netif_noip(struct udevice *udev)
Heinrich, any other EFI protocols you have in mind that would require
similar tweaking? e.g the EFI_TCP4 and HTTP protocols?
>
> static int dhcp_loop(struct udevice *udev)
>
> >
> >> + int ret;
> >> + static bool first_call = true;
> >> +
> >> + eth_init_rings();
> >> +
> >> + if (first_call) {
> >> + if (eth_init()) {
> >> + printf("eth_init() error\n");
> >> + return NULL;
> >> + }
> >> + first_call = false;
> >> + }
> >> +
> >> + netif_remove(net_lwip_get_netif());
> >> +
> >> + eth_set_current();
> >> +
> >> + dev = eth_get_dev();
> >> + if (!dev)
> >> + return NULL;
> >> +
> >> + ip4_addr_set_zero(&ip);
> >> + ip4_addr_set_zero(&mask);
> >> + ip4_addr_set_zero(&gw);
> >> +
> >> + if (with_ip)
> >> + if (get_udev_ipv4_info(dev, &ip, &mask, &gw) < 0)
> >> + return NULL;
> >> +
> >> + eth_env_get_enetaddr_by_index("eth", dev_seq(dev), enetaddr);
> >> + ret = snprintf(hwstr, MAC_ADDR_STRLEN, "%pM", enetaddr);
> >> + if (ret < 0 || ret >= MAC_ADDR_STRLEN)
> >> + return NULL;
> >> +
> >> + netif = calloc(1, sizeof(struct netif));
> >> + if (!netif)
> >> + return NULL;
> >> +
> >> + netif->name[0] = 'e';
> >> + netif->name[1] = 't';
> >> +
> >> + string_to_enetaddr(hwstr, netif->hwaddr);
> >> + netif->hwaddr_len = ETHARP_HWADDR_LEN;
> >> +
> >> + if (!netif_add(netif, &ip, &mask, &gw, netif, net_lwip_if_init,
> >> + netif_input)) {
> >> + printf("error: netif_add() failed\n");
> >> + free(netif);
> >> + return NULL;
> >> + }
> >> +
> >> + netif_set_up(netif);
> >> + netif_set_link_up(netif);
> >> + /* Routing: use this interface to reach the default gateway */
> >> + netif_set_default(netif);
> >> +
> >> + return netif;
> >> +}
> >> +
> >> +/* Configure lwIP to use the currently active network device */
> >> +struct netif *net_lwip_new_netif()
> >> +{
> >> + return new_netif(true);
> >> +}
> >> +
> >> +struct netif *net_lwip_new_netif_noip()
> >> +{
> >> +
> >> + return new_netif(false);
> >> +}
> >> +
> >> +void net_lwip_remove_netif(struct netif *netif)
> >> +{
> >> + netif_remove(netif);
> >> + free(netif);
> >> +}
> >> +
> >> +int net_init(void)
> >> +{
> >> + net_lwip_new_netif();
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static struct pbuf *alloc_pbuf_and_copy(uchar *data, int len)
> >> +{
> >> + struct pbuf *p, *q;
> >> +
> >> + /* We allocate a pbuf chain of pbufs from the pool. */
> >> + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
> >> + if (!p) {
> >> + LINK_STATS_INC(link.memerr);
> >> + LINK_STATS_INC(link.drop);
> >> + return NULL;
> >> + }
> >> +
> >> + for (q = p; q != NULL; q = q->next) {
> >> + memcpy(q->payload, data, q->len);
> >> + data += q->len;
> >> + }
> >> +
> >> + LINK_STATS_INC(link.recv);
> >> +
> >> + return p;
> >> +}
> >> +
> >> +void net_process_received_packet(uchar *in_packet, int len)
> >
> > Library functions should take a udevice as an argument. Please, do not
> > use the concept of "active device" in these library functions.
>
> OK, I have unified the naming in v6 and all functions will take a udevice:
>
> static int dhcp_loop(struct udevice *udev)
> static int dns_loop(struct udevice *udev, const char *name, const char *var)
> static int ping_loop(struct udevice *udev, const ip_addr_t* addr)
> static int tftp_loop(struct udevice *udev, ulong addr, char *fname,
> ip_addr_t srvip)
> static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
>
> >
> > The command line interface may implement such a concept for backwards
> > compatibility.
>
> Sure.
>
> Thanks,
> --
> Jerome
>
> >
> > Best regards
> >
> > Heinrich
> >
> >> +{
> >> + struct netif *netif;
> >> + struct pbuf *pbuf;
> >> +
> >> + if (len < ETHER_HDR_SIZE)
> >> + return;
> >> +
> >> +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
> >> + if (push_packet) {
> >> + (*push_packet)(in_packet, len);
> >> + return;
> >> + }
> >> +#endif
> >> +
> >> + netif = net_lwip_get_netif();
> >> + if (!netif)
> >> + return;
> >> +
> >> + pbuf = alloc_pbuf_and_copy(in_packet, len);
> >> + if (!pbuf)
> >> + return;
> >> +
> >> + netif->input(pbuf, netif);
> >> +}
> >> +
> >> +u32_t sys_now(void)
> >> +{
> >> + return get_timer(0);
> >> +}
> >> diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
> >> new file mode 100644
> >> index 00000000000..1fa246f55d9
> >> --- /dev/null
> >> +++ b/net-lwip/tftp.c
> >> @@ -0,0 +1,11 @@
> >> +// SPDX-License-Identifier: GPL-2.0+
> >> +/* Copyright (C) 2024 Linaro Ltd. */
> >> +
> >> +#include <command.h>
> >> +#include <net-lwip.h>
> >> +
> >> +int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >> +{
> >> + /* Not implemented */
> >> + return CMD_RET_FAILURE;
> >> +}
> >
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH v4 06/14] net-lwip: add TFTP support and tftpboot command
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (4 preceding siblings ...)
2024-06-17 15:32 ` [PATCH v4 05/14] net-lwip: add DHCP support and dhcp commmand Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-17 15:32 ` [PATCH v4 07/14] net-lwip: add ping command Jerome Forissier
` (10 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
Francis Laniel, Peter Robinson
Implement do_tftpb().
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
cmd/Kconfig | 3 +-
cmd/net-lwip.c | 8 ++
net-lwip/dhcp.c | 11 ++-
net-lwip/tftp.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 237 insertions(+), 6 deletions(-)
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1bfa528e945..94a8de266f6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2101,10 +2101,9 @@ config CMD_DHCP
config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP
- default n
+ default y
help
tftpboot - load file via network using TFTP protocol
- Currently a placeholder (not implemented)
endif
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 82edb5fd2e6..80f0872bb8f 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -11,3 +11,11 @@ U_BOOT_CMD(
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
#endif
+
+#if defined(CONFIG_CMD_TFTPBOOT)
+U_BOOT_CMD(
+ tftpboot, 3, 0, do_tftpb,
+ "boot image via network using TFTP protocol\n",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
diff --git a/net-lwip/dhcp.c b/net-lwip/dhcp.c
index 38ea565508f..af8ac214e81 100644
--- a/net-lwip/dhcp.c
+++ b/net-lwip/dhcp.c
@@ -88,11 +88,20 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
int dhcp_run(ulong addr, const char *fname, bool autoload)
{
char *dhcp_argv[] = {"dhcp", NULL, };
+#ifdef CONFIG_CMD_TFTPBOOT
+ char *tftp_argv[] = {"tftpboot", boot_file_name, NULL, };
+#endif
struct cmd_tbl cmdtp = {}; /* dummy */
if (autoload) {
- /* Will be supported when TFTP is added */
+#ifdef CONFIG_CMD_TFTPBOOT
+ /* Assume DHCP was already performed */
+ if (boot_file_name[0])
+ return do_tftpb(&cmdtp, 0, 2, tftp_argv);
+ return 0;
+#else
return -EOPNOTSUPP;
+#endif
}
return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
diff --git a/net-lwip/tftp.c b/net-lwip/tftp.c
index 1fa246f55d9..295c8a7ebf2 100644
--- a/net-lwip/tftp.c
+++ b/net-lwip/tftp.c
@@ -2,10 +2,225 @@
/* Copyright (C) 2024 Linaro Ltd. */
#include <command.h>
-#include <net-lwip.h>
+#include <console.h>
+#include <image.h>
+#include <linux/delay.h>
+#include <lwip/apps/tftp_client.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+
+enum done_state {
+ NOT_DONE = 0,
+ SUCCESS = 1,
+ FAILURE = 2
+};
+
+struct tftp_ctx {
+ ulong daddr;
+ ulong size;
+ ulong prevsize;
+ ulong start_time;
+ enum done_state done;
+};
+
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write)
+{
+ return NULL;
+}
+
+static void tftp_close(void *handle)
+{
+ struct tftp_ctx *ctx = handle;
+ ulong elapsed;
+
+ if (ctx->done == FAILURE) {
+ /* Closing after an error */
+ return;
+ }
+
+ elapsed = get_timer(ctx->start_time);
+ ctx->done = SUCCESS;
+ printf("\nBytes transferred = %lu (%lx hex)\n", ctx->size, ctx->size);
+
+ if (env_set_hex("filesize", ctx->size)) {
+ log_err("filesize not updated\n");
+ return;
+ }
+}
+
+static int tftp_read(void *handle, void *buf, int bytes)
+{
+ return 0;
+}
+
+static int tftp_write(void *handle, struct pbuf *p)
+{
+ struct tftp_ctx *ctx = handle;
+ struct pbuf *q;
+
+ for (q = p; q != NULL; q = q->next) {
+ memcpy((void *)ctx->daddr, q->payload, q->len);
+ ctx->daddr += q->len;
+ ctx->size += q->len;
+ if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) {
+ printf("#");
+ ctx->prevsize = ctx->size;
+ }
+ }
+
+ return 0;
+}
+
+static void tftp_error(void *handle, int err, const char *msg, int size)
+{
+ struct tftp_ctx *ctx = handle;
+ char message[100];
+
+ ctx->done = FAILURE;
+ memset(message, 0, sizeof(message));
+ memcpy(message, msg, LWIP_MIN(sizeof(message) - 1, (size_t)size));
+
+ printf("\nTFTP error: %d (%s)\n", err, message);
+}
+
+static const struct tftp_context tftp_context = {
+ tftp_open,
+ tftp_close,
+ tftp_read,
+ tftp_write,
+ tftp_error
+};
+
+static int tftp_run(ulong addr, char *fname, ip_addr_t srvip)
+{
+ struct netif *netif;
+ struct tftp_ctx ctx;
+ err_t err;
+
+ if (!fname || addr == 0)
+ return -1;
+
+ netif = net_lwip_new_netif();
+ if (!netif)
+ return -1;
+
+ ctx.done = NOT_DONE;
+ ctx.size = 0;
+ ctx.prevsize = 0;
+ ctx.daddr = addr;
+
+ printf("Using %s device\n", eth_get_name());
+ printf("TFTP from server %s; our IP address is %s\n",
+ ip4addr_ntoa(&srvip), env_get("ipaddr"));
+ printf("Filename '%s'.\n", fname);
+ printf("Load address: 0x%lx\n", ctx.daddr);
+ printf("Loading: ");
+
+ err = tftp_init_client(&tftp_context);
+ if (!(err == ERR_OK || err == ERR_USE))
+ log_err("tftp_init_client err: %d\n", err);
+
+ ctx.start_time = get_timer(0);
+ err = tftp_get(&ctx, &srvip, TFTP_PORT, fname, TFTP_MODE_OCTET);
+ /* might return different errors, like routing problems */
+ if (err != ERR_OK) {
+ printf("tftp_get() error %d\n", err);
+ net_lwip_remove_netif(netif);
+ return -1;
+ }
+
+ while (!ctx.done) {
+ eth_rx();
+ sys_check_timeouts();
+ if (ctrlc())
+ break;
+ }
+
+ tftp_cleanup();
+
+ net_lwip_remove_netif(netif);
+
+ if (ctx.done == SUCCESS) {
+ if (env_set_hex("fileaddr", addr)) {
+ log_err("fileaddr not updated\n");
+ return -1;
+ }
+ return 0;
+ }
+
+ return -1;
+}
int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
- /* Not implemented */
- return CMD_RET_FAILURE;
+ char *fname;
+ char *server_ip;
+ ip_addr_t srvip;
+ ulong addr;
+ char *end;
+ char *col;
+
+ image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr);
+
+ switch (argc) {
+ case 1:
+ fname = env_get("bootfile");
+ break;
+ case 2:
+ /*
+ * Only one arg - accept two forms:
+ * Just load address, or just boot file name. The latter
+ * form must be written in a format which can not be
+ * mis-interpreted as a valid number.
+ */
+ addr = hextoul(argv[1], &end);
+ if (end == (argv[1] + strlen(argv[1]))) {
+ image_load_addr = addr;
+ fname = env_get("bootfile");
+ } else {
+ fname = argv[1];
+ }
+ break;
+ case 3:
+ image_load_addr = hextoul(argv[1], NULL);
+ fname = argv[2];
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ col = strchr(fname, ':');
+ if (col) {
+ server_ip = fname;
+ *col = '\0';
+ fname = col + 1;
+ } else {
+ server_ip = env_get("serverip");
+ if (!server_ip) {
+ log_err("error: serverip variable has to be set\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ if (!ipaddr_aton(server_ip, &srvip)) {
+ log_err("error: ipaddr_aton\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!fname) {
+ log_err("error: no file name\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!image_load_addr) {
+ log_err("error: no load address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (tftp_run(image_load_addr, fname, srvip) < 0)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 07/14] net-lwip: add ping command
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (5 preceding siblings ...)
2024-06-17 15:32 ` [PATCH v4 06/14] net-lwip: add TFTP support and tftpboot command Jerome Forissier
@ 2024-06-17 15:32 ` Jerome Forissier
2024-06-17 15:33 ` [PATCH v4 08/14] net-lwip: add dns command Jerome Forissier
` (9 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:32 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Eddie James, Mattijs Korpershoek,
AKASHI Takahiro, Francis Laniel, Peter Robinson
Add support for the the ping command with NET_LWIP. The implementation
is derived from lwIP's contrib/apps/ping/ping.c.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
boot/Kconfig | 2 +-
cmd/Kconfig | 6 ++
cmd/net-lwip.c | 8 +++
include/net-lwip.h | 1 +
net-lwip/Makefile | 1 +
net-lwip/ping.c | 174 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 191 insertions(+), 1 deletion(-)
create mode 100644 net-lwip/ping.c
diff --git a/boot/Kconfig b/boot/Kconfig
index 004e69dd92a..983a284ec52 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -379,7 +379,7 @@ config BOOT_DEFAULTS_CMDS
select CMD_FS_GENERIC
select CMD_PART if PARTITIONS
select CMD_DHCP if CMD_NET || CMD_NET_LWIP
- select CMD_PING if CMD_NET
+ select CMD_PING if CMD_NET || CMD_NET_LWIP
select CMD_PXE if CMD_NET
select CMD_BOOTI if ARM64
select CMD_BOOTZ if ARM && !ARM64
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 94a8de266f6..07cfe824e3f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
help
Boot image via network using DHCP/TFTP protocol
+config CMD_PING
+ bool "ping"
+ select PROT_RAW_LWIP
+ help
+ Send ICMP ECHO_REQUEST to network host
+
config CMD_TFTPBOOT
bool "tftp"
select PROT_UDP_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index 80f0872bb8f..feed719beef 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -12,6 +12,14 @@ U_BOOT_CMD(
);
#endif
+#if defined(CONFIG_CMD_PING)
+U_BOOT_CMD(
+ ping, 2, 1, do_ping,
+ "send ICMP ECHO_REQUEST to network host",
+ "pingAddress"
+);
+#endif
+
#if defined(CONFIG_CMD_TFTPBOOT)
U_BOOT_CMD(
tftpboot, 3, 0, do_tftpb,
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 46cf6875f7e..b34f53b4891 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -12,5 +12,6 @@ void net_lwip_remove_netif(struct netif *netif);
struct netif *net_lwip_get_netif(void);
int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
#endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index a56c32bfa74..e68d4e24197 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
# Disable this warning as it is triggered by:
diff --git a/net-lwip/ping.c b/net-lwip/ping.c
new file mode 100644
index 00000000000..de0b633dc32
--- /dev/null
+++ b/net-lwip/ping.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <lwip/icmp.h>
+#include <lwip/inet_chksum.h>
+#include <lwip/raw.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+#define PING_DELAY_MS 1000
+#define PING_COUNT 5
+/* Ping identifier - must fit on a u16_t */
+#define PING_ID 0xAFAF
+
+struct ping_ctx {
+ ip_addr_t target;
+ struct raw_pcb *pcb;
+ struct icmp_echo_hdr *iecho;
+ uint16_t seq_num;
+ bool alive;
+};
+
+static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p,
+ const ip_addr_t *addr)
+{
+ struct ping_ctx *ctx = arg;
+ struct icmp_echo_hdr *iecho = ctx->iecho;
+
+ if (addr->addr != ctx->target.addr)
+ return 0;
+
+ if ((p->tot_len >= (IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
+ pbuf_remove_header(p, IP_HLEN) == 0) {
+ iecho = (struct icmp_echo_hdr *)p->payload;
+
+ if ((iecho->id == PING_ID) &&
+ (iecho->seqno == lwip_htons(ctx->seq_num))) {
+ ctx->alive = true;
+ printf("host %s is alive\n", ipaddr_ntoa(addr));
+ pbuf_free(p);
+ return 1; /* eat the packet */
+ }
+ /* not eaten, restore original packet */
+ pbuf_add_header(p, IP_HLEN);
+ }
+
+ return 0; /* don't eat the packet */
+}
+
+static int ping_raw_init(struct ping_ctx *ctx)
+{
+ ctx->pcb = raw_new(IP_PROTO_ICMP);
+ if (!ctx->pcb)
+ return -ENOMEM;
+
+ raw_recv(ctx->pcb, ping_recv, ctx);
+ raw_bind(ctx->pcb, IP_ADDR_ANY);
+
+ return 0;
+}
+
+static void ping_raw_stop(struct ping_ctx *ctx)
+{
+ if (ctx->pcb)
+ raw_remove(ctx->pcb);
+}
+
+static void ping_prepare_echo(struct ping_ctx *ctx)
+{
+ struct icmp_echo_hdr *iecho = ctx->iecho;
+
+ ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+ ICMPH_CODE_SET(iecho, 0);
+ iecho->chksum = 0;
+ iecho->id = PING_ID;
+ iecho->seqno = lwip_htons(ctx->seq_num);
+
+ iecho->chksum = inet_chksum(iecho, sizeof(*iecho));
+}
+
+static void ping_send_icmp(struct ping_ctx *ctx)
+{
+ struct pbuf *p;
+ size_t ping_size = sizeof(struct icmp_echo_hdr);
+
+ p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
+ if (!p)
+ return;
+
+ if ((p->len == p->tot_len) && !p->next) {
+ ctx->iecho = (struct icmp_echo_hdr *)p->payload;
+ ping_prepare_echo(ctx);
+ raw_sendto(ctx->pcb, p, &ctx->target);
+ }
+
+ pbuf_free(p);
+}
+
+static void _ping_send(void *arg)
+{
+ struct ping_ctx *ctx = arg;
+
+ ctx->seq_num++;
+ if (ctx->seq_num <= PING_COUNT) {
+ ping_send_icmp(ctx);
+ sys_timeout(PING_DELAY_MS, _ping_send, ctx);
+ }
+}
+
+int ping_send(const ip_addr_t* addr)
+{
+ struct ping_ctx ctx = {};
+ struct netif *netif;
+ int ret;
+
+ netif = net_lwip_new_netif();
+ if (!netif)
+ return CMD_RET_FAILURE;
+
+ printf("Using %s device\n", eth_get_name());
+
+ ret = ping_raw_init(&ctx);
+ if (ret < 0) {
+ net_lwip_remove_netif(netif);
+ return ret;
+ }
+
+ ctx.target = *addr;
+
+ _ping_send(&ctx);
+
+ do {
+ sys_check_timeouts();
+ eth_rx();
+ if (ctx.alive)
+ break;
+ if (ctrlc()) {
+ printf("\nAbort\n");
+ break;
+ }
+ } while (ctx.seq_num <= PING_COUNT);
+
+ sys_untimeout(_ping_send, &ctx);
+ ping_raw_stop(&ctx);
+
+ net_lwip_remove_netif(netif);
+
+ if (ctx.alive)
+ return 0;
+
+ printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr));
+ return -1;
+}
+
+int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ip_addr_t addr;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (!ipaddr_aton(argv[1], &addr))
+ return CMD_RET_USAGE;
+
+ if (ping_send(&addr) < 0)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 08/14] net-lwip: add dns command
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (6 preceding siblings ...)
2024-06-17 15:32 ` [PATCH v4 07/14] net-lwip: add ping command Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-17 15:33 ` [PATCH v4 09/14] net: split cmd/net.c into cmd/net.c and cmd/net-common.c Jerome Forissier
` (8 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
Michal Simek, Francis Laniel, Peter Robinson
Add CMD_DNS when NET_LWIP is enabled to provide the dns command using
lwIP.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
cmd/Kconfig | 6 +++
cmd/net-lwip.c | 8 ++++
include/net-lwip.h | 1 +
net-lwip/Makefile | 1 +
net-lwip/dns.c | 117 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 133 insertions(+)
create mode 100644 net-lwip/dns.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07cfe824e3f..6ef0b52cd34 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2098,6 +2098,12 @@ config CMD_DHCP
help
Boot image via network using DHCP/TFTP protocol
+config CMD_DNS
+ bool "dns"
+ select PROT_DNS_LWIP
+ help
+ Lookup the IP of a hostname
+
config CMD_PING
bool "ping"
select PROT_RAW_LWIP
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index feed719beef..c021da6a674 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -27,3 +27,11 @@ U_BOOT_CMD(
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
#endif
+
+#if defined(CONFIG_CMD_DNS)
+U_BOOT_CMD(
+ dns, 3, 1, do_dns,
+ "lookup the IP of a hostname",
+ "hostname [envvar]"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index b34f53b4891..4d41b0208a3 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -12,6 +12,7 @@ void net_lwip_remove_netif(struct netif *netif);
struct netif *net_lwip_get_netif(void);
int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
#endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index e68d4e24197..aa247859483 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth_common.o
obj-$(CONFIG_$(SPL_)DM_ETH) += ../net/eth-uclass.o
obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_CMD_DNS) += dns.o
obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
diff --git a/net-lwip/dns.c b/net-lwip/dns.c
new file mode 100644
index 00000000000..081f0933715
--- /dev/null
+++ b/net-lwip/dns.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <lwip/dns.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+#define DNS_RESEND_MS 1000
+#define DNS_TIMEOUT_MS 10000
+
+struct dns_cb_arg {
+ ip_addr_t host_ipaddr;
+ const char *var;
+ bool done;
+};
+
+static void do_dns_tmr(void *arg)
+{
+ dns_tmr();
+}
+
+static void dns_cb(const char *name, const ip_addr_t *ipaddr, void *arg)
+{
+ struct dns_cb_arg *dns_cb_arg = arg;
+ char *ipstr = ip4addr_ntoa(ipaddr);
+
+ dns_cb_arg->done = true;
+
+ if (!ipaddr) {
+ printf("DNS: host not found\n");
+ dns_cb_arg->host_ipaddr.addr = 0;
+ return;
+ }
+
+ if (dns_cb_arg->var)
+ env_set(dns_cb_arg->var, ipstr);
+
+ printf("%s\n", ipstr);
+}
+
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct dns_cb_arg dns_cb_arg = { };
+ bool has_server = false;
+ struct netif *netif;
+ ip_addr_t ipaddr;
+ ip_addr_t ns;
+ ulong start;
+ char *nsenv;
+ char *name;
+ int ret;
+
+ if (argc == 1 || argc > 3)
+ return CMD_RET_USAGE;
+
+ if (argc >= 2)
+ name = argv[1];
+
+ if (argc == 3)
+ dns_cb_arg.var = argv[2];
+
+ netif = net_lwip_new_netif();
+ if (!netif)
+ return -1;
+
+ dns_init();
+
+ nsenv = env_get("dnsip");
+ if (nsenv && ipaddr_aton(nsenv, &ns)) {
+ dns_setserver(0, &ns);
+ has_server = true;
+ }
+
+ nsenv = env_get("dnsip2");
+ if (nsenv && ipaddr_aton(nsenv, &ns)) {
+ dns_setserver(1, &ns);
+ has_server = true;
+ }
+
+ if (!has_server) {
+ log_err("No valid name server (dnsip/dnsip2)\n");
+ net_lwip_remove_netif(netif);
+ return CMD_RET_FAILURE;
+ }
+
+ dns_cb_arg.done = false;
+
+ ret = dns_gethostbyname(name, &ipaddr, dns_cb, &dns_cb_arg);
+
+ if (ret == ERR_OK) {
+ dns_cb(name, &ipaddr, &dns_cb_arg);
+ } else if (ret == ERR_INPROGRESS) {
+ start = get_timer(0);
+ sys_timeout(DNS_RESEND_MS, do_dns_tmr, NULL);
+ do {
+ eth_rx();
+ if (dns_cb_arg.done)
+ break;
+ sys_check_timeouts();
+ if (ctrlc()) {
+ printf("\nAbort\n");
+ break;
+ }
+ } while (get_timer(start) < DNS_TIMEOUT_MS);
+ sys_untimeout(do_dns_tmr, NULL);
+ }
+
+ net_lwip_remove_netif(netif);
+
+ if (dns_cb_arg.done && dns_cb_arg.host_ipaddr.addr != 0)
+ return CMD_RET_SUCCESS;
+
+ return CMD_RET_FAILURE;
+}
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 09/14] net: split cmd/net.c into cmd/net.c and cmd/net-common.c
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (7 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 08/14] net-lwip: add dns command Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-17 15:33 ` [PATCH v4 10/14] net-lwip: add wget command Jerome Forissier
` (7 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Francis Laniel, Abdellatif El Khlifi,
Heinrich Schuchardt
Extract some code from cmd/net.c that will be useful in a subsequent
commit to implement wget with NET_LWIP.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
cmd/Makefile | 5 ++-
cmd/net-common.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
cmd/net.c | 115 -----------------------------------------------
3 files changed, 113 insertions(+), 116 deletions(-)
create mode 100644 cmd/net-common.c
diff --git a/cmd/Makefile b/cmd/Makefile
index 535b6838ca5..e90f2f68211 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -129,8 +129,11 @@ obj-$(CONFIG_CMD_MUX) += mux.o
obj-$(CONFIG_CMD_NAND) += nand.o
obj-$(CONFIG_CMD_NET) += net.o
obj-$(CONFIG_CMD_NET_LWIP) += net-lwip.o
+obj-$(filter y,$(CONFIG_CMD_NET) $(CONFIG_CMD_NET_LWIP)) += net-common.o
ifdef CONFIG_CMD_NET_LWIP
-CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+lwip-includes := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
+CFLAGS_net-lwip.o := $(lwip-includes)
+CFLAGS_net-common.o := $(lwip-includes)
endif
obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
diff --git a/cmd/net-common.c b/cmd/net-common.c
new file mode 100644
index 00000000000..1c9fb83b896
--- /dev/null
+++ b/cmd/net-common.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <command.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <net.h>
+#include <linux/compat.h>
+#include <linux/ethtool.h>
+
+static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const struct udevice *current = eth_get_dev();
+ unsigned char env_enetaddr[ARP_HLEN];
+ const struct udevice *dev;
+ struct uclass *uc;
+
+ uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
+ eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
+ printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
+ current == dev ? "active" : "");
+ }
+ return CMD_RET_SUCCESS;
+}
+
+static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int nstats, err, i, off;
+ struct udevice *dev;
+ u64 *values;
+ u8 *strings;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
+ if (err) {
+ printf("Could not find device %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ if (!eth_get_ops(dev)->get_sset_count ||
+ !eth_get_ops(dev)->get_strings ||
+ !eth_get_ops(dev)->get_stats) {
+ printf("Driver does not implement stats dump!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ nstats = eth_get_ops(dev)->get_sset_count(dev);
+ strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
+ if (!strings)
+ return CMD_RET_FAILURE;
+
+ values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
+ if (!values)
+ goto err_free_strings;
+
+ eth_get_ops(dev)->get_strings(dev, strings);
+ eth_get_ops(dev)->get_stats(dev, values);
+
+ off = 0;
+ for (i = 0; i < nstats; i++) {
+ printf(" %s: %llu\n", &strings[off], values[i]);
+ off += ETH_GSTRING_LEN;
+ };
+
+ kfree(strings);
+ kfree(values);
+
+ return CMD_RET_SUCCESS;
+
+err_free_strings:
+ kfree(strings);
+
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_net[] = {
+ U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
+ U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
+};
+
+static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
+
+ /* Drop the net command */
+ argc--;
+ argv++;
+
+ if (!cp || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+ return CMD_RET_SUCCESS;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ net, 3, 1, do_net,
+ "NET sub-system",
+ "list - list available devices\n"
+ "stats <device> - dump statistics for specified device\n"
+);
diff --git a/cmd/net.c b/cmd/net.c
index d407d8320a3..03b4582204f 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -676,118 +676,3 @@ U_BOOT_CMD(
);
#endif /* CONFIG_CMD_LINK_LOCAL */
-
-static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
- const struct udevice *current = eth_get_dev();
- unsigned char env_enetaddr[ARP_HLEN];
- const struct udevice *dev;
- struct uclass *uc;
-
- uclass_id_foreach_dev(UCLASS_ETH, dev, uc) {
- eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr);
- printf("eth%d : %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr,
- current == dev ? "active" : "");
- }
- return CMD_RET_SUCCESS;
-}
-
-static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
- int nstats, err, i, off;
- struct udevice *dev;
- u64 *values;
- u8 *strings;
-
- if (argc < 2)
- return CMD_RET_USAGE;
-
- err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev);
- if (err) {
- printf("Could not find device %s\n", argv[1]);
- return CMD_RET_FAILURE;
- }
-
- if (!eth_get_ops(dev)->get_sset_count ||
- !eth_get_ops(dev)->get_strings ||
- !eth_get_ops(dev)->get_stats) {
- printf("Driver does not implement stats dump!\n");
- return CMD_RET_FAILURE;
- }
-
- nstats = eth_get_ops(dev)->get_sset_count(dev);
- strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL);
- if (!strings)
- return CMD_RET_FAILURE;
-
- values = kcalloc(nstats, sizeof(u64), GFP_KERNEL);
- if (!values)
- goto err_free_strings;
-
- eth_get_ops(dev)->get_strings(dev, strings);
- eth_get_ops(dev)->get_stats(dev, values);
-
- off = 0;
- for (i = 0; i < nstats; i++) {
- printf(" %s: %llu\n", &strings[off], values[i]);
- off += ETH_GSTRING_LEN;
- };
-
- return CMD_RET_SUCCESS;
-
-err_free_strings:
- kfree(strings);
-
- return CMD_RET_FAILURE;
-}
-
-static struct cmd_tbl cmd_net[] = {
- U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""),
- U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""),
-};
-
-static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
- struct cmd_tbl *cp;
-
- cp = find_cmd_tbl(argv[1], cmd_net, ARRAY_SIZE(cmd_net));
-
- /* Drop the net command */
- argc--;
- argv++;
-
- if (!cp || argc > cp->maxargs)
- return CMD_RET_USAGE;
- if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
- return CMD_RET_SUCCESS;
-
- return cp->cmd(cmdtp, flag, argc, argv);
-}
-
-U_BOOT_CMD(
- net, 3, 1, do_net,
- "NET sub-system",
- "list - list available devices\n"
- "stats <device> - dump statistics for specified device\n"
-);
-
-#if defined(CONFIG_CMD_NCSI)
-static int do_ncsi(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
-{
- if (!phy_interface_is_ncsi() || !ncsi_active()) {
- printf("Device not configured for NC-SI\n");
- return CMD_RET_FAILURE;
- }
-
- if (net_loop(NCSI) < 0)
- return CMD_RET_FAILURE;
-
- return CMD_RET_SUCCESS;
-}
-
-U_BOOT_CMD(
- ncsi, 1, 1, do_ncsi,
- "Configure attached NIC via NC-SI",
- ""
-);
-#endif /* CONFIG_CMD_NCSI */
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 10/14] net-lwip: add wget command
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (8 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 09/14] net: split cmd/net.c into cmd/net.c and cmd/net-common.c Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-24 6:21 ` Jon Humphreys
2024-06-17 15:33 ` [PATCH v4 11/14] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y Jerome Forissier
` (6 subsequent siblings)
16 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
Michal Simek, Francis Laniel, Peter Robinson
Add support for the wget command with NET_LWIP.
Based on code initially developed by Maxim U.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
Cc: Maxim Uvarov <muvarov@gmail.com>
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
cmd/Kconfig | 7 ++
cmd/net-lwip.c | 8 ++
include/net-lwip.h | 18 +++
net-lwip/Makefile | 1 +
net-lwip/wget.c | 269 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 303 insertions(+)
create mode 100644 net-lwip/wget.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6ef0b52cd34..d9a86540be6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
help
tftpboot - load file via network using TFTP protocol
+config CMD_WGET
+ bool "wget"
+ select PROT_TCP_LWIP
+ help
+ wget is a simple command to download kernel, or other files,
+ from a http server over TCP.
+
endif
endif
diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
index c021da6a674..42f8bd6b259 100644
--- a/cmd/net-lwip.c
+++ b/cmd/net-lwip.c
@@ -35,3 +35,11 @@ U_BOOT_CMD(
"hostname [envvar]"
);
#endif
+
+#if defined(CONFIG_CMD_WGET)
+U_BOOT_CMD(
+ wget, 3, 1, do_wget,
+ "boot image via network using HTTP protocol",
+ "[loadAddress] URL"
+);
+#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 4d41b0208a3..ddf25e61417 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -11,8 +11,26 @@ struct netif *net_lwip_new_netif_noip(void);
void net_lwip_remove_netif(struct netif *netif);
struct netif *net_lwip_get_netif(void);
+/**
+ * wget_with_dns() - runs dns host IP address resulution before wget
+ *
+ * @dst_addr: destination address to download the file
+ * @uri: uri string of target file of wget
+ * Return: downloaded file size, negative if failed
+ */
+
+int wget_with_dns(ulong dst_addr, char *uri);
+/**
+ * wget_validate_uri() - varidate the uri
+ *
+ * @uri: uri string of target file of wget
+ * Return: true if uri is valid, false if uri is invalid
+ */
+bool wget_validate_uri(char *uri);
+
int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
#endif /* __NET_LWIP_H__ */
diff --git a/net-lwip/Makefile b/net-lwip/Makefile
index aa247859483..bc011bb0e32 100644
--- a/net-lwip/Makefile
+++ b/net-lwip/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
obj-$(CONFIG_CMD_DNS) += dns.o
obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
+obj-$(CONFIG_CMD_WGET) += wget.o
# Disable this warning as it is triggered by:
# sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
new file mode 100644
index 00000000000..069299bd469
--- /dev/null
+++ b/net-lwip/wget.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2024 Linaro Ltd. */
+
+#include <command.h>
+#include <console.h>
+#include <display_options.h>
+#include <image.h>
+#include <lwip/apps/http_client.h>
+#include <lwip/timeouts.h>
+#include <net.h>
+#include <time.h>
+
+#define SERVER_NAME_SIZE 200
+#define HTTP_PORT_DEFAULT 80
+#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
+
+enum done_state {
+ NOT_DONE = 0,
+ SUCCESS = 1,
+ FAILURE = 2
+};
+
+struct wget_ctx {
+ ulong daddr;
+ ulong saved_daddr;
+ ulong size;
+ ulong prevsize;
+ ulong start_time;
+ enum done_state done;
+};
+
+static int parse_url(char *url, char *host, u16 *port, char **path)
+{
+ char *p, *pp;
+ long lport;
+
+ p = strstr(url, "http://");
+ if (!p)
+ return -EINVAL;
+
+ p += strlen("http://");
+
+ /* Parse hostname */
+ pp = strchr(p, ':');
+ if (!pp)
+ pp = strchr(p, '/');
+ if (!pp)
+ return -EINVAL;
+
+ if (p + SERVER_NAME_SIZE <= pp)
+ return -EINVAL;
+
+ memcpy(host, p, pp - p);
+ host[pp - p + 1] = '\0';
+
+ if (*pp == ':') {
+ /* Parse port number */
+ p = pp + 1;
+ lport = simple_strtol(p, &pp, 10);
+ if (pp && *pp != '/')
+ return -EINVAL;
+ if (lport > 65535)
+ return -EINVAL;
+ *port = (u16)lport;
+ } else {
+ *port = HTTP_PORT_DEFAULT;
+ }
+ if (*pp != '/')
+ return -EINVAL;
+ *path = pp;
+
+ return 0;
+}
+
+static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf,
+ err_t err)
+{
+ struct wget_ctx *ctx = arg;
+ struct pbuf *buf;
+
+ if (!pbuf)
+ return ERR_BUF;
+
+ for (buf = pbuf; buf; buf = buf->next) {
+ memcpy((void *)ctx->daddr, buf->payload, buf->len);
+ ctx->daddr += buf->len;
+ ctx->size += buf->len;
+ if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) {
+ printf("#");
+ ctx->prevsize = ctx->size;
+ }
+ }
+
+ altcp_recved(pcb, pbuf->tot_len);
+ pbuf_free(pbuf);
+ return ERR_OK;
+}
+
+static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
+ u32_t rx_content_len, u32_t srv_res, err_t err)
+{
+ struct wget_ctx *ctx = arg;
+ ulong elapsed;
+
+ if (httpc_result != HTTPC_RESULT_OK) {
+ log_err("\nHTTP client error %d\n", httpc_result);
+ ctx->done = FAILURE;
+ return;
+ }
+
+ elapsed = get_timer(ctx->start_time);
+ if (rx_content_len > PROGRESS_PRINT_STEP_BYTES)
+ printf("\n");
+ printf("%u bytes transferred in %lu ms (", rx_content_len,
+ get_timer(ctx->start_time));
+ print_size(rx_content_len / elapsed * 1000, "/s)\n");
+
+ if (env_set_hex("filesize", rx_content_len) ||
+ env_set_hex("fileaddr", ctx->saved_daddr)) {
+ log_err("Could not set filesize or fileaddr\n");
+ ctx->done = FAILURE;
+ return;
+ }
+
+ ctx->done = SUCCESS;
+}
+
+int wget_with_dns(ulong dst_addr, char *uri)
+{
+ char server_name[SERVER_NAME_SIZE];
+ httpc_connection_t conn;
+ httpc_state_t *state;
+ struct netif *netif;
+ struct wget_ctx ctx;
+ char *path;
+ u16 port;
+
+ ctx.daddr = dst_addr;
+ ctx.saved_daddr = dst_addr;
+ ctx.done = NOT_DONE;
+ ctx.size = 0;
+ ctx.prevsize = 0;
+
+ if (parse_url(uri, server_name, &port, &path))
+ return CMD_RET_USAGE;
+
+ netif = net_lwip_new_netif();
+ if (!netif)
+ return -1;
+
+ memset(&conn, 0, sizeof(conn));
+ conn.result_fn = httpc_result_cb;
+ ctx.start_time = get_timer(0);
+ if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
+ &ctx, &state)) {
+ net_lwip_remove_netif(netif);
+ return CMD_RET_FAILURE;
+ }
+
+ while (!ctx.done) {
+ eth_rx();
+ sys_check_timeouts();
+ if (ctrlc())
+ break;
+ }
+
+ net_lwip_remove_netif(netif);
+
+ if (ctx.done == SUCCESS)
+ return 0;
+
+ return -1;
+}
+
+int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ char *end;
+ char *url;
+ ulong dst_addr;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ dst_addr = hextoul(argv[1], &end);
+ if (end == (argv[1] + strlen(argv[1]))) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ url = argv[2];
+ } else {
+ dst_addr = image_load_addr;
+ url = argv[1];
+ }
+
+ if (wget_with_dns(dst_addr, url))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * wget_validate_uri() - validate the uri for wget
+ *
+ * @uri: uri string
+ *
+ * This function follows the current U-Boot wget implementation.
+ * scheme: only "http:" is supported
+ * authority:
+ * - user information: not supported
+ * - host: supported
+ * - port: not supported(always use the default port)
+ *
+ * Uri is expected to be correctly percent encoded.
+ * This is the minimum check, control codes(0x1-0x19, 0x7F, except '\0')
+ * and space character(0x20) are not allowed.
+ *
+ * TODO: stricter uri conformance check
+ *
+ * Return: true on success, false on failure
+ */
+bool wget_validate_uri(char *uri)
+{
+ char c;
+ bool ret = true;
+ char *str_copy, *s, *authority;
+
+ for (c = 0x1; c < 0x21; c++) {
+ if (strchr(uri, c)) {
+ log_err("invalid character is used\n");
+ return false;
+ }
+ }
+ if (strchr(uri, 0x7f)) {
+ log_err("invalid character is used\n");
+ return false;
+ }
+
+ if (strncmp(uri, "http://", 7)) {
+ log_err("only http:// is supported\n");
+ return false;
+ }
+ str_copy = strdup(uri);
+ if (!str_copy)
+ return false;
+
+ s = str_copy + strlen("http://");
+ authority = strsep(&s, "/");
+ if (!s) {
+ log_err("invalid uri, no file path\n");
+ ret = false;
+ goto out;
+ }
+ s = strchr(authority, '@');
+ if (s) {
+ log_err("user information is not supported\n");
+ ret = false;
+ goto out;
+ }
+ s = strchr(authority, ':');
+ if (s) {
+ log_err("user defined port is not supported\n");
+ ret = false;
+ goto out;
+ }
+
+out:
+ free(str_copy);
+
+ return ret;
+}
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-17 15:33 ` [PATCH v4 10/14] net-lwip: add wget command Jerome Forissier
@ 2024-06-24 6:21 ` Jon Humphreys
2024-06-24 6:25 ` Jon Humphreys
` (2 more replies)
0 siblings, 3 replies; 53+ messages in thread
From: Jon Humphreys @ 2024-06-24 6:21 UTC (permalink / raw)
To: Jerome Forissier, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
Michal Simek, Francis Laniel, Peter Robinson
Jerome Forissier <jerome.forissier@linaro.org> writes:
> Add support for the wget command with NET_LWIP.
>
> Based on code initially developed by Maxim U.
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
> Cc: Maxim Uvarov <muvarov@gmail.com>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> ---
> cmd/Kconfig | 7 ++
> cmd/net-lwip.c | 8 ++
> include/net-lwip.h | 18 +++
> net-lwip/Makefile | 1 +
> net-lwip/wget.c | 269 +++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 303 insertions(+)
> create mode 100644 net-lwip/wget.c
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 6ef0b52cd34..d9a86540be6 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
> help
> tftpboot - load file via network using TFTP protocol
>
> +config CMD_WGET
> + bool "wget"
> + select PROT_TCP_LWIP
> + help
> + wget is a simple command to download kernel, or other files,
> + from a http server over TCP.
> +
> endif
>
> endif
> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
> index c021da6a674..42f8bd6b259 100644
> --- a/cmd/net-lwip.c
> +++ b/cmd/net-lwip.c
> @@ -35,3 +35,11 @@ U_BOOT_CMD(
> "hostname [envvar]"
> );
> #endif
> +
> +#if defined(CONFIG_CMD_WGET)
> +U_BOOT_CMD(
> + wget, 3, 1, do_wget,
> + "boot image via network using HTTP protocol",
> + "[loadAddress] URL"
> +);
> +#endif
> diff --git a/include/net-lwip.h b/include/net-lwip.h
> index 4d41b0208a3..ddf25e61417 100644
> --- a/include/net-lwip.h
> +++ b/include/net-lwip.h
> @@ -11,8 +11,26 @@ struct netif *net_lwip_new_netif_noip(void);
> void net_lwip_remove_netif(struct netif *netif);
> struct netif *net_lwip_get_netif(void);
>
> +/**
> + * wget_with_dns() - runs dns host IP address resulution before wget
> + *
> + * @dst_addr: destination address to download the file
> + * @uri: uri string of target file of wget
> + * Return: downloaded file size, negative if failed
> + */
> +
> +int wget_with_dns(ulong dst_addr, char *uri);
> +/**
> + * wget_validate_uri() - varidate the uri
> + *
> + * @uri: uri string of target file of wget
> + * Return: true if uri is valid, false if uri is invalid
> + */
> +bool wget_validate_uri(char *uri);
> +
> int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
> int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
> int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
>
> #endif /* __NET_LWIP_H__ */
> diff --git a/net-lwip/Makefile b/net-lwip/Makefile
> index aa247859483..bc011bb0e32 100644
> --- a/net-lwip/Makefile
> +++ b/net-lwip/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
> obj-$(CONFIG_CMD_DNS) += dns.o
> obj-$(CONFIG_CMD_PING) += ping.o
> obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
> +obj-$(CONFIG_CMD_WGET) += wget.o
>
> # Disable this warning as it is triggered by:
> # sprintf(buf, index ? "foo%d" : "foo", index)
> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
> new file mode 100644
> index 00000000000..069299bd469
> --- /dev/null
> +++ b/net-lwip/wget.c
> @@ -0,0 +1,269 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (C) 2024 Linaro Ltd. */
> +
> +#include <command.h>
> +#include <console.h>
> +#include <display_options.h>
> +#include <image.h>
> +#include <lwip/apps/http_client.h>
> +#include <lwip/timeouts.h>
> +#include <net.h>
> +#include <time.h>
> +
> +#define SERVER_NAME_SIZE 200
> +#define HTTP_PORT_DEFAULT 80
> +#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
> +
> +enum done_state {
> + NOT_DONE = 0,
> + SUCCESS = 1,
> + FAILURE = 2
> +};
> +
> +struct wget_ctx {
> + ulong daddr;
> + ulong saved_daddr;
> + ulong size;
> + ulong prevsize;
> + ulong start_time;
> + enum done_state done;
> +};
> +
> +static int parse_url(char *url, char *host, u16 *port, char **path)
> +{
> + char *p, *pp;
> + long lport;
> +
> + p = strstr(url, "http://");
> + if (!p)
> + return -EINVAL;
> +
> + p += strlen("http://");
> +
> + /* Parse hostname */
> + pp = strchr(p, ':');
> + if (!pp)
> + pp = strchr(p, '/');
> + if (!pp)
> + return -EINVAL;
> +
> + if (p + SERVER_NAME_SIZE <= pp)
> + return -EINVAL;
> +
> + memcpy(host, p, pp - p);
> + host[pp - p + 1] = '\0';
> +
> + if (*pp == ':') {
> + /* Parse port number */
> + p = pp + 1;
> + lport = simple_strtol(p, &pp, 10);
> + if (pp && *pp != '/')
> + return -EINVAL;
> + if (lport > 65535)
> + return -EINVAL;
> + *port = (u16)lport;
> + } else {
> + *port = HTTP_PORT_DEFAULT;
> + }
> + if (*pp != '/')
> + return -EINVAL;
> + *path = pp;
> +
> + return 0;
> +}
> +
> +static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf,
> + err_t err)
> +{
> + struct wget_ctx *ctx = arg;
> + struct pbuf *buf;
> +
> + if (!pbuf)
> + return ERR_BUF;
> +
> + for (buf = pbuf; buf; buf = buf->next) {
> + memcpy((void *)ctx->daddr, buf->payload, buf->len);
> + ctx->daddr += buf->len;
> + ctx->size += buf->len;
> + if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) {
> + printf("#");
> + ctx->prevsize = ctx->size;
> + }
> + }
> +
> + altcp_recved(pcb, pbuf->tot_len);
> + pbuf_free(pbuf);
> + return ERR_OK;
> +}
> +
> +static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
> + u32_t rx_content_len, u32_t srv_res, err_t err)
> +{
> + struct wget_ctx *ctx = arg;
> + ulong elapsed;
> +
> + if (httpc_result != HTTPC_RESULT_OK) {
> + log_err("\nHTTP client error %d\n", httpc_result);
> + ctx->done = FAILURE;
> + return;
> + }
> +
> + elapsed = get_timer(ctx->start_time);
> + if (rx_content_len > PROGRESS_PRINT_STEP_BYTES)
> + printf("\n");
> + printf("%u bytes transferred in %lu ms (", rx_content_len,
> + get_timer(ctx->start_time));
> + print_size(rx_content_len / elapsed * 1000, "/s)\n");
> +
> + if (env_set_hex("filesize", rx_content_len) ||
> + env_set_hex("fileaddr", ctx->saved_daddr)) {
> + log_err("Could not set filesize or fileaddr\n");
> + ctx->done = FAILURE;
> + return;
> + }
> +
> + ctx->done = SUCCESS;
> +}
> +
> +int wget_with_dns(ulong dst_addr, char *uri)
> +{
> + char server_name[SERVER_NAME_SIZE];
> + httpc_connection_t conn;
> + httpc_state_t *state;
> + struct netif *netif;
> + struct wget_ctx ctx;
> + char *path;
> + u16 port;
> +
> + ctx.daddr = dst_addr;
> + ctx.saved_daddr = dst_addr;
> + ctx.done = NOT_DONE;
> + ctx.size = 0;
> + ctx.prevsize = 0;
> +
> + if (parse_url(uri, server_name, &port, &path))
> + return CMD_RET_USAGE;
> +
> + netif = net_lwip_new_netif();
> + if (!netif)
> + return -1;
> +
> + memset(&conn, 0, sizeof(conn));
> + conn.result_fn = httpc_result_cb;
> + ctx.start_time = get_timer(0);
> + if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
> + &ctx, &state)) {
> + net_lwip_remove_netif(netif);
> + return CMD_RET_FAILURE;
> + }
> +
> + while (!ctx.done) {
> + eth_rx();
> + sys_check_timeouts();
> + if (ctrlc())
> + break;
> + }
> +
> + net_lwip_remove_netif(netif);
> +
> + if (ctx.done == SUCCESS)
> + return 0;
> +
> + return -1;
> +}
> +
> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
> +{
> + char *end;
> + char *url;
> + ulong dst_addr;
> +
> + if (argc < 2 || argc > 3)
> + return CMD_RET_USAGE;
> +
> + dst_addr = hextoul(argv[1], &end);
> + if (end == (argv[1] + strlen(argv[1]))) {
> + if (argc < 3)
> + return CMD_RET_USAGE;
> + url = argv[2];
> + } else {
> + dst_addr = image_load_addr;
> + url = argv[1];
> + }
> +
> + if (wget_with_dns(dst_addr, url))
> + return CMD_RET_FAILURE;
> +
> + return CMD_RET_SUCCESS;
> +}
> +
> +/**
> + * wget_validate_uri() - validate the uri for wget
> + *
> + * @uri: uri string
> + *
> + * This function follows the current U-Boot wget implementation.
> + * scheme: only "http:" is supported
> + * authority:
> + * - user information: not supported
> + * - host: supported
> + * - port: not supported(always use the default port)
> + *
> + * Uri is expected to be correctly percent encoded.
> + * This is the minimum check, control codes(0x1-0x19, 0x7F, except '\0')
> + * and space character(0x20) are not allowed.
> + *
> + * TODO: stricter uri conformance check
> + *
> + * Return: true on success, false on failure
> + */
> +bool wget_validate_uri(char *uri)
> +{
> + char c;
> + bool ret = true;
> + char *str_copy, *s, *authority;
> +
> + for (c = 0x1; c < 0x21; c++) {
> + if (strchr(uri, c)) {
> + log_err("invalid character is used\n");
> + return false;
> + }
> + }
> + if (strchr(uri, 0x7f)) {
> + log_err("invalid character is used\n");
> + return false;
> + }
> +
> + if (strncmp(uri, "http://", 7)) {
> + log_err("only http:// is supported\n");
> + return false;
> + }
> + str_copy = strdup(uri);
> + if (!str_copy)
> + return false;
> +
> + s = str_copy + strlen("http://");
> + authority = strsep(&s, "/");
> + if (!s) {
> + log_err("invalid uri, no file path\n");
> + ret = false;
> + goto out;
> + }
> + s = strchr(authority, '@');
> + if (s) {
> + log_err("user information is not supported\n");
> + ret = false;
> + goto out;
> + }
> + s = strchr(authority, ':');
> + if (s) {
> + log_err("user defined port is not supported\n");
> + ret = false;
> + goto out;
> + }
> +
> +out:
> + free(str_copy);
> +
> + return ret;
> +}
> --
> 2.40.1
Hi Jerome, I am trying out the lwIP stack on TI boards.
For wget, I noticed a bug and a user experience improvement. The bug is an
off-by-one array access when parsing the url. The improvement emits a
message if the url isn't an http://, since that is all we are supporting,
and without the message, the wget command silently fails, which is
confusing to the user.
I will post the 2 patches as a reply to this email. LMK if you want to use
another method to collaborate. I can already see that efi http boot support
will not work. wget_validate_uri() looks to be copied vertabim from the
current implementation, and IMO we should completely remove it.
Jon
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-24 6:21 ` Jon Humphreys
@ 2024-06-24 6:25 ` Jon Humphreys
2024-06-24 8:50 ` Jerome Forissier
2024-06-24 6:26 ` Jon Humphreys
2024-06-24 8:49 ` Jerome Forissier
2 siblings, 1 reply; 53+ messages in thread
From: Jon Humphreys @ 2024-06-24 6:25 UTC (permalink / raw)
To: Jerome Forissier, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
Michal Simek, Francis Laniel, Peter Robinson
Subject: [PATCH] net-lwip: fixes off-by-one array access error with wget
When wget parses the url and extracts the host, it is off by one on the
index to terminate the character array.
Signed-off-by: Jonathan Humphreys <j-humphreys@ti.com>
---
net-lwip/wget.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
index 069299bd469..63b19b99112 100644
--- a/net-lwip/wget.c
+++ b/net-lwip/wget.c
@@ -51,7 +51,7 @@ static int parse_url(char *url, char *host, u16 *port, char **path)
return -EINVAL;
memcpy(host, p, pp - p);
- host[pp - p + 1] = '\0';
+ host[pp - p] = '\0';
if (*pp == ':') {
/* Parse port number */
--
2.34.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-24 6:25 ` Jon Humphreys
@ 2024-06-24 8:50 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-24 8:50 UTC (permalink / raw)
To: Jon Humphreys, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
Francis Laniel, Peter Robinson
On 6/24/24 08:25, Jon Humphreys wrote:
> Subject: [PATCH] net-lwip: fixes off-by-one array access error with wget
>
> When wget parses the url and extracts the host, it is off by one on the
> index to terminate the character array.
>
> Signed-off-by: Jonathan Humphreys <j-humphreys@ti.com>
> ---
> net-lwip/wget.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
> index 069299bd469..63b19b99112 100644
> --- a/net-lwip/wget.c
> +++ b/net-lwip/wget.c
> @@ -51,7 +51,7 @@ static int parse_url(char *url, char *host, u16 *port, char **path)
> return -EINVAL;
>
> memcpy(host, p, pp - p);
> - host[pp - p + 1] = '\0';
> + host[pp - p] = '\0';
>
> if (*pp == ':') {
> /* Parse port number */
Hi Jon,
As I said previously I am ignoring this patch since I already have it in
my working tree. Thanks for reporting.
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-24 6:21 ` Jon Humphreys
2024-06-24 6:25 ` Jon Humphreys
@ 2024-06-24 6:26 ` Jon Humphreys
2024-06-24 8:52 ` Jerome Forissier
2024-06-24 8:49 ` Jerome Forissier
2 siblings, 1 reply; 53+ messages in thread
From: Jon Humphreys @ 2024-06-24 6:26 UTC (permalink / raw)
To: Jerome Forissier, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, AKASHI Takahiro,
Michal Simek, Francis Laniel, Peter Robinson
Subject: [PATCH] net-lwip: Add message if not using http:// for wget
U-Boot's wget only supports http://, so give the user a clue if they don't
use it.
Signed-off-by: Jonathan Humphreys <j-humphreys@ti.com>
---
net-lwip/wget.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
index 63b19b99112..6b9c953ef51 100644
--- a/net-lwip/wget.c
+++ b/net-lwip/wget.c
@@ -35,8 +35,10 @@ static int parse_url(char *url, char *host, u16 *port, char **path)
long lport;
p = strstr(url, "http://");
- if (!p)
+ if (!p) {
+ log_err("only http:// is supported\n");
return -EINVAL;
+ }
p += strlen("http://");
--
2.34.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-24 6:26 ` Jon Humphreys
@ 2024-06-24 8:52 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-24 8:52 UTC (permalink / raw)
To: Jon Humphreys, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
Francis Laniel, Peter Robinson
On 6/24/24 08:26, Jon Humphreys wrote:
> Subject: [PATCH] net-lwip: Add message if not using http:// for wget
>
> U-Boot's wget only supports http://, so give the user a clue if they don't
> use it.
>
> Signed-off-by: Jonathan Humphreys <j-humphreys@ti.com>
> ---
> net-lwip/wget.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
> index 63b19b99112..6b9c953ef51 100644
> --- a/net-lwip/wget.c
> +++ b/net-lwip/wget.c
> @@ -35,8 +35,10 @@ static int parse_url(char *url, char *host, u16 *port, char **path)
> long lport;
>
> p = strstr(url, "http://");
> - if (!p)
> + if (!p) {
> + log_err("only http:// is supported\n");
> return -EINVAL;
> + }
>
> p += strlen("http://");
>
I am folding that into "net-lwip: add wget command" if you don't mind.
Thanks!
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-24 6:21 ` Jon Humphreys
2024-06-24 6:25 ` Jon Humphreys
2024-06-24 6:26 ` Jon Humphreys
@ 2024-06-24 8:49 ` Jerome Forissier
2024-06-25 3:20 ` Jon Humphreys
2 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-24 8:49 UTC (permalink / raw)
To: Jon Humphreys, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
Francis Laniel, Peter Robinson
On 6/24/24 08:21, Jon Humphreys wrote:
> Jerome Forissier <jerome.forissier@linaro.org> writes:
>
>> Add support for the wget command with NET_LWIP.
>>
>> Based on code initially developed by Maxim U.
>>
>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
>> Cc: Maxim Uvarov <muvarov@gmail.com>
>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>> ---
>> cmd/Kconfig | 7 ++
>> cmd/net-lwip.c | 8 ++
>> include/net-lwip.h | 18 +++
>> net-lwip/Makefile | 1 +
>> net-lwip/wget.c | 269 +++++++++++++++++++++++++++++++++++++++++++++
>> 5 files changed, 303 insertions(+)
>> create mode 100644 net-lwip/wget.c
>>
>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>> index 6ef0b52cd34..d9a86540be6 100644
>> --- a/cmd/Kconfig
>> +++ b/cmd/Kconfig
>> @@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
>> help
>> tftpboot - load file via network using TFTP protocol
>>
>> +config CMD_WGET
>> + bool "wget"
>> + select PROT_TCP_LWIP
>> + help
>> + wget is a simple command to download kernel, or other files,
>> + from a http server over TCP.
>> +
>> endif
>>
>> endif
>> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
>> index c021da6a674..42f8bd6b259 100644
>> --- a/cmd/net-lwip.c
>> +++ b/cmd/net-lwip.c
>> @@ -35,3 +35,11 @@ U_BOOT_CMD(
>> "hostname [envvar]"
>> );
>> #endif
>> +
>> +#if defined(CONFIG_CMD_WGET)
>> +U_BOOT_CMD(
>> + wget, 3, 1, do_wget,
>> + "boot image via network using HTTP protocol",
>> + "[loadAddress] URL"
>> +);
>> +#endif
>> diff --git a/include/net-lwip.h b/include/net-lwip.h
>> index 4d41b0208a3..ddf25e61417 100644
>> --- a/include/net-lwip.h
>> +++ b/include/net-lwip.h
>> @@ -11,8 +11,26 @@ struct netif *net_lwip_new_netif_noip(void);
>> void net_lwip_remove_netif(struct netif *netif);
>> struct netif *net_lwip_get_netif(void);
>>
>> +/**
>> + * wget_with_dns() - runs dns host IP address resulution before wget
>> + *
>> + * @dst_addr: destination address to download the file
>> + * @uri: uri string of target file of wget
>> + * Return: downloaded file size, negative if failed
>> + */
>> +
>> +int wget_with_dns(ulong dst_addr, char *uri);
>> +/**
>> + * wget_validate_uri() - varidate the uri
>> + *
>> + * @uri: uri string of target file of wget
>> + * Return: true if uri is valid, false if uri is invalid
>> + */
>> +bool wget_validate_uri(char *uri);
>> +
>> int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>> int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>> int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
>>
>> #endif /* __NET_LWIP_H__ */
>> diff --git a/net-lwip/Makefile b/net-lwip/Makefile
>> index aa247859483..bc011bb0e32 100644
>> --- a/net-lwip/Makefile
>> +++ b/net-lwip/Makefile
>> @@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
>> obj-$(CONFIG_CMD_DNS) += dns.o
>> obj-$(CONFIG_CMD_PING) += ping.o
>> obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>> +obj-$(CONFIG_CMD_WGET) += wget.o
>>
>> # Disable this warning as it is triggered by:
>> # sprintf(buf, index ? "foo%d" : "foo", index)
>> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
>> new file mode 100644
>> index 00000000000..069299bd469
>> --- /dev/null
>> +++ b/net-lwip/wget.c
>> @@ -0,0 +1,269 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/* Copyright (C) 2024 Linaro Ltd. */
>> +
>> +#include <command.h>
>> +#include <console.h>
>> +#include <display_options.h>
>> +#include <image.h>
>> +#include <lwip/apps/http_client.h>
>> +#include <lwip/timeouts.h>
>> +#include <net.h>
>> +#include <time.h>
>> +
>> +#define SERVER_NAME_SIZE 200
>> +#define HTTP_PORT_DEFAULT 80
>> +#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
>> +
>> +enum done_state {
>> + NOT_DONE = 0,
>> + SUCCESS = 1,
>> + FAILURE = 2
>> +};
>> +
>> +struct wget_ctx {
>> + ulong daddr;
>> + ulong saved_daddr;
>> + ulong size;
>> + ulong prevsize;
>> + ulong start_time;
>> + enum done_state done;
>> +};
>> +
>> +static int parse_url(char *url, char *host, u16 *port, char **path)
>> +{
>> + char *p, *pp;
>> + long lport;
>> +
>> + p = strstr(url, "http://");
>> + if (!p)
>> + return -EINVAL;
>> +
>> + p += strlen("http://");
>> +
>> + /* Parse hostname */
>> + pp = strchr(p, ':');
>> + if (!pp)
>> + pp = strchr(p, '/');
>> + if (!pp)
>> + return -EINVAL;
>> +
>> + if (p + SERVER_NAME_SIZE <= pp)
>> + return -EINVAL;
>> +
>> + memcpy(host, p, pp - p);
>> + host[pp - p + 1] = '\0';
>> +
>> + if (*pp == ':') {
>> + /* Parse port number */
>> + p = pp + 1;
>> + lport = simple_strtol(p, &pp, 10);
>> + if (pp && *pp != '/')
>> + return -EINVAL;
>> + if (lport > 65535)
>> + return -EINVAL;
>> + *port = (u16)lport;
>> + } else {
>> + *port = HTTP_PORT_DEFAULT;
>> + }
>> + if (*pp != '/')
>> + return -EINVAL;
>> + *path = pp;
>> +
>> + return 0;
>> +}
>> +
>> +static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf,
>> + err_t err)
>> +{
>> + struct wget_ctx *ctx = arg;
>> + struct pbuf *buf;
>> +
>> + if (!pbuf)
>> + return ERR_BUF;
>> +
>> + for (buf = pbuf; buf; buf = buf->next) {
>> + memcpy((void *)ctx->daddr, buf->payload, buf->len);
>> + ctx->daddr += buf->len;
>> + ctx->size += buf->len;
>> + if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) {
>> + printf("#");
>> + ctx->prevsize = ctx->size;
>> + }
>> + }
>> +
>> + altcp_recved(pcb, pbuf->tot_len);
>> + pbuf_free(pbuf);
>> + return ERR_OK;
>> +}
>> +
>> +static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
>> + u32_t rx_content_len, u32_t srv_res, err_t err)
>> +{
>> + struct wget_ctx *ctx = arg;
>> + ulong elapsed;
>> +
>> + if (httpc_result != HTTPC_RESULT_OK) {
>> + log_err("\nHTTP client error %d\n", httpc_result);
>> + ctx->done = FAILURE;
>> + return;
>> + }
>> +
>> + elapsed = get_timer(ctx->start_time);
>> + if (rx_content_len > PROGRESS_PRINT_STEP_BYTES)
>> + printf("\n");
>> + printf("%u bytes transferred in %lu ms (", rx_content_len,
>> + get_timer(ctx->start_time));
>> + print_size(rx_content_len / elapsed * 1000, "/s)\n");
>> +
>> + if (env_set_hex("filesize", rx_content_len) ||
>> + env_set_hex("fileaddr", ctx->saved_daddr)) {
>> + log_err("Could not set filesize or fileaddr\n");
>> + ctx->done = FAILURE;
>> + return;
>> + }
>> +
>> + ctx->done = SUCCESS;
>> +}
>> +
>> +int wget_with_dns(ulong dst_addr, char *uri)
>> +{
>> + char server_name[SERVER_NAME_SIZE];
>> + httpc_connection_t conn;
>> + httpc_state_t *state;
>> + struct netif *netif;
>> + struct wget_ctx ctx;
>> + char *path;
>> + u16 port;
>> +
>> + ctx.daddr = dst_addr;
>> + ctx.saved_daddr = dst_addr;
>> + ctx.done = NOT_DONE;
>> + ctx.size = 0;
>> + ctx.prevsize = 0;
>> +
>> + if (parse_url(uri, server_name, &port, &path))
>> + return CMD_RET_USAGE;
>> +
>> + netif = net_lwip_new_netif();
>> + if (!netif)
>> + return -1;
>> +
>> + memset(&conn, 0, sizeof(conn));
>> + conn.result_fn = httpc_result_cb;
>> + ctx.start_time = get_timer(0);
>> + if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
>> + &ctx, &state)) {
>> + net_lwip_remove_netif(netif);
>> + return CMD_RET_FAILURE;
>> + }
>> +
>> + while (!ctx.done) {
>> + eth_rx();
>> + sys_check_timeouts();
>> + if (ctrlc())
>> + break;
>> + }
>> +
>> + net_lwip_remove_netif(netif);
>> +
>> + if (ctx.done == SUCCESS)
>> + return 0;
>> +
>> + return -1;
>> +}
>> +
>> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
>> +{
>> + char *end;
>> + char *url;
>> + ulong dst_addr;
>> +
>> + if (argc < 2 || argc > 3)
>> + return CMD_RET_USAGE;
>> +
>> + dst_addr = hextoul(argv[1], &end);
>> + if (end == (argv[1] + strlen(argv[1]))) {
>> + if (argc < 3)
>> + return CMD_RET_USAGE;
>> + url = argv[2];
>> + } else {
>> + dst_addr = image_load_addr;
>> + url = argv[1];
>> + }
>> +
>> + if (wget_with_dns(dst_addr, url))
>> + return CMD_RET_FAILURE;
>> +
>> + return CMD_RET_SUCCESS;
>> +}
>> +
>> +/**
>> + * wget_validate_uri() - validate the uri for wget
>> + *
>> + * @uri: uri string
>> + *
>> + * This function follows the current U-Boot wget implementation.
>> + * scheme: only "http:" is supported
>> + * authority:
>> + * - user information: not supported
>> + * - host: supported
>> + * - port: not supported(always use the default port)
>> + *
>> + * Uri is expected to be correctly percent encoded.
>> + * This is the minimum check, control codes(0x1-0x19, 0x7F, except '\0')
>> + * and space character(0x20) are not allowed.
>> + *
>> + * TODO: stricter uri conformance check
>> + *
>> + * Return: true on success, false on failure
>> + */
>> +bool wget_validate_uri(char *uri)
>> +{
>> + char c;
>> + bool ret = true;
>> + char *str_copy, *s, *authority;
>> +
>> + for (c = 0x1; c < 0x21; c++) {
>> + if (strchr(uri, c)) {
>> + log_err("invalid character is used\n");
>> + return false;
>> + }
>> + }
>> + if (strchr(uri, 0x7f)) {
>> + log_err("invalid character is used\n");
>> + return false;
>> + }
>> +
>> + if (strncmp(uri, "http://", 7)) {
>> + log_err("only http:// is supported\n");
>> + return false;
>> + }
>> + str_copy = strdup(uri);
>> + if (!str_copy)
>> + return false;
>> +
>> + s = str_copy + strlen("http://");
>> + authority = strsep(&s, "/");
>> + if (!s) {
>> + log_err("invalid uri, no file path\n");
>> + ret = false;
>> + goto out;
>> + }
>> + s = strchr(authority, '@');
>> + if (s) {
>> + log_err("user information is not supported\n");
>> + ret = false;
>> + goto out;
>> + }
>> + s = strchr(authority, ':');
>> + if (s) {
>> + log_err("user defined port is not supported\n");
>> + ret = false;
>> + goto out;
>> + }
>> +
>> +out:
>> + free(str_copy);
>> +
>> + return ret;
>> +}
>> --
>> 2.40.1
Hi Jon,
> Hi Jerome, I am trying out the lwIP stack on TI boards.
>
> For wget, I noticed a bug and a user experience improvement. The bug is an
> off-by-one array access when parsing the url.
Indeed, someone reported this bug to me off-list and it's already fixed in
my WIP branch.
> The improvement emits a
> message if the url isn't an http://, since that is all we are supporting,
> and without the message, the wget command silently fails, which is
> confusing to the user.
I agree.
> I will post the 2 patches as a reply to this email. LMK if you want to use
> another method to collaborate. I can already see that efi http boot support
> will not work. wget_validate_uri() looks to be copied vertabim from the
> current implementation, and IMO we should completely remove it.
It is indeed copied. It is needed to avoid an unresolved symbol but I
understand more work may be needed for EFI HTTP boot support (not tested by
me).
If you are willing to help with this then you are welcome to post patches as
replies and I will integrate them in the series.
Thanks,
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-24 8:49 ` Jerome Forissier
@ 2024-06-25 3:20 ` Jon Humphreys
2024-06-25 7:43 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Jon Humphreys @ 2024-06-25 3:20 UTC (permalink / raw)
To: Jerome Forissier, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
Francis Laniel, Peter Robinson
Jerome Forissier <jerome.forissier@linaro.org> writes:
> On 6/24/24 08:21, Jon Humphreys wrote:
>> Jerome Forissier <jerome.forissier@linaro.org> writes:
>>
>>> Add support for the wget command with NET_LWIP.
>>>
>>> Based on code initially developed by Maxim U.
>>>
>>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>>> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
>>> Cc: Maxim Uvarov <muvarov@gmail.com>
>>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>>> ---
>>> cmd/Kconfig | 7 ++
>>> cmd/net-lwip.c | 8 ++
>>> include/net-lwip.h | 18 +++
>>> net-lwip/Makefile | 1 +
>>> net-lwip/wget.c | 269 +++++++++++++++++++++++++++++++++++++++++++++
>>> 5 files changed, 303 insertions(+)
>>> create mode 100644 net-lwip/wget.c
>>>
>>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>>> index 6ef0b52cd34..d9a86540be6 100644
>>> --- a/cmd/Kconfig
>>> +++ b/cmd/Kconfig
>>> @@ -2117,6 +2117,13 @@ config CMD_TFTPBOOT
>>> help
>>> tftpboot - load file via network using TFTP protocol
>>>
>>> +config CMD_WGET
>>> + bool "wget"
>>> + select PROT_TCP_LWIP
>>> + help
>>> + wget is a simple command to download kernel, or other files,
>>> + from a http server over TCP.
>>> +
>>> endif
>>>
>>> endif
>>> diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c
>>> index c021da6a674..42f8bd6b259 100644
>>> --- a/cmd/net-lwip.c
>>> +++ b/cmd/net-lwip.c
>>> @@ -35,3 +35,11 @@ U_BOOT_CMD(
>>> "hostname [envvar]"
>>> );
>>> #endif
>>> +
>>> +#if defined(CONFIG_CMD_WGET)
>>> +U_BOOT_CMD(
>>> + wget, 3, 1, do_wget,
>>> + "boot image via network using HTTP protocol",
>>> + "[loadAddress] URL"
>>> +);
>>> +#endif
>>> diff --git a/include/net-lwip.h b/include/net-lwip.h
>>> index 4d41b0208a3..ddf25e61417 100644
>>> --- a/include/net-lwip.h
>>> +++ b/include/net-lwip.h
>>> @@ -11,8 +11,26 @@ struct netif *net_lwip_new_netif_noip(void);
>>> void net_lwip_remove_netif(struct netif *netif);
>>> struct netif *net_lwip_get_netif(void);
>>>
>>> +/**
>>> + * wget_with_dns() - runs dns host IP address resulution before wget
>>> + *
>>> + * @dst_addr: destination address to download the file
>>> + * @uri: uri string of target file of wget
>>> + * Return: downloaded file size, negative if failed
>>> + */
>>> +
>>> +int wget_with_dns(ulong dst_addr, char *uri);
>>> +/**
>>> + * wget_validate_uri() - varidate the uri
>>> + *
>>> + * @uri: uri string of target file of wget
>>> + * Return: true if uri is valid, false if uri is invalid
>>> + */
>>> +bool wget_validate_uri(char *uri);
>>> +
>>> int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>>> int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>>> int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
>>> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
>>>
>>> #endif /* __NET_LWIP_H__ */
>>> diff --git a/net-lwip/Makefile b/net-lwip/Makefile
>>> index aa247859483..bc011bb0e32 100644
>>> --- a/net-lwip/Makefile
>>> +++ b/net-lwip/Makefile
>>> @@ -10,6 +10,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
>>> obj-$(CONFIG_CMD_DNS) += dns.o
>>> obj-$(CONFIG_CMD_PING) += ping.o
>>> obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
>>> +obj-$(CONFIG_CMD_WGET) += wget.o
>>>
>>> # Disable this warning as it is triggered by:
>>> # sprintf(buf, index ? "foo%d" : "foo", index)
>>> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
>>> new file mode 100644
>>> index 00000000000..069299bd469
>>> --- /dev/null
>>> +++ b/net-lwip/wget.c
>>> @@ -0,0 +1,269 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/* Copyright (C) 2024 Linaro Ltd. */
>>> +
>>> +#include <command.h>
>>> +#include <console.h>
>>> +#include <display_options.h>
>>> +#include <image.h>
>>> +#include <lwip/apps/http_client.h>
>>> +#include <lwip/timeouts.h>
>>> +#include <net.h>
>>> +#include <time.h>
>>> +
>>> +#define SERVER_NAME_SIZE 200
>>> +#define HTTP_PORT_DEFAULT 80
>>> +#define PROGRESS_PRINT_STEP_BYTES (100 * 1024)
>>> +
>>> +enum done_state {
>>> + NOT_DONE = 0,
>>> + SUCCESS = 1,
>>> + FAILURE = 2
>>> +};
>>> +
>>> +struct wget_ctx {
>>> + ulong daddr;
>>> + ulong saved_daddr;
>>> + ulong size;
>>> + ulong prevsize;
>>> + ulong start_time;
>>> + enum done_state done;
>>> +};
>>> +
>>> +static int parse_url(char *url, char *host, u16 *port, char **path)
>>> +{
>>> + char *p, *pp;
>>> + long lport;
>>> +
>>> + p = strstr(url, "http://");
>>> + if (!p)
>>> + return -EINVAL;
>>> +
>>> + p += strlen("http://");
>>> +
>>> + /* Parse hostname */
>>> + pp = strchr(p, ':');
>>> + if (!pp)
>>> + pp = strchr(p, '/');
>>> + if (!pp)
>>> + return -EINVAL;
>>> +
>>> + if (p + SERVER_NAME_SIZE <= pp)
>>> + return -EINVAL;
>>> +
>>> + memcpy(host, p, pp - p);
>>> + host[pp - p + 1] = '\0';
>>> +
>>> + if (*pp == ':') {
>>> + /* Parse port number */
>>> + p = pp + 1;
>>> + lport = simple_strtol(p, &pp, 10);
>>> + if (pp && *pp != '/')
>>> + return -EINVAL;
>>> + if (lport > 65535)
>>> + return -EINVAL;
>>> + *port = (u16)lport;
>>> + } else {
>>> + *port = HTTP_PORT_DEFAULT;
>>> + }
>>> + if (*pp != '/')
>>> + return -EINVAL;
>>> + *path = pp;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf,
>>> + err_t err)
>>> +{
>>> + struct wget_ctx *ctx = arg;
>>> + struct pbuf *buf;
>>> +
>>> + if (!pbuf)
>>> + return ERR_BUF;
>>> +
>>> + for (buf = pbuf; buf; buf = buf->next) {
>>> + memcpy((void *)ctx->daddr, buf->payload, buf->len);
>>> + ctx->daddr += buf->len;
>>> + ctx->size += buf->len;
>>> + if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) {
>>> + printf("#");
>>> + ctx->prevsize = ctx->size;
>>> + }
>>> + }
>>> +
>>> + altcp_recved(pcb, pbuf->tot_len);
>>> + pbuf_free(pbuf);
>>> + return ERR_OK;
>>> +}
>>> +
>>> +static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
>>> + u32_t rx_content_len, u32_t srv_res, err_t err)
>>> +{
>>> + struct wget_ctx *ctx = arg;
>>> + ulong elapsed;
>>> +
>>> + if (httpc_result != HTTPC_RESULT_OK) {
>>> + log_err("\nHTTP client error %d\n", httpc_result);
>>> + ctx->done = FAILURE;
>>> + return;
>>> + }
>>> +
>>> + elapsed = get_timer(ctx->start_time);
>>> + if (rx_content_len > PROGRESS_PRINT_STEP_BYTES)
>>> + printf("\n");
>>> + printf("%u bytes transferred in %lu ms (", rx_content_len,
>>> + get_timer(ctx->start_time));
>>> + print_size(rx_content_len / elapsed * 1000, "/s)\n");
>>> +
>>> + if (env_set_hex("filesize", rx_content_len) ||
>>> + env_set_hex("fileaddr", ctx->saved_daddr)) {
>>> + log_err("Could not set filesize or fileaddr\n");
>>> + ctx->done = FAILURE;
>>> + return;
>>> + }
>>> +
>>> + ctx->done = SUCCESS;
>>> +}
>>> +
>>> +int wget_with_dns(ulong dst_addr, char *uri)
>>> +{
>>> + char server_name[SERVER_NAME_SIZE];
>>> + httpc_connection_t conn;
>>> + httpc_state_t *state;
>>> + struct netif *netif;
>>> + struct wget_ctx ctx;
>>> + char *path;
>>> + u16 port;
>>> +
>>> + ctx.daddr = dst_addr;
>>> + ctx.saved_daddr = dst_addr;
>>> + ctx.done = NOT_DONE;
>>> + ctx.size = 0;
>>> + ctx.prevsize = 0;
>>> +
>>> + if (parse_url(uri, server_name, &port, &path))
>>> + return CMD_RET_USAGE;
>>> +
>>> + netif = net_lwip_new_netif();
>>> + if (!netif)
>>> + return -1;
>>> +
>>> + memset(&conn, 0, sizeof(conn));
>>> + conn.result_fn = httpc_result_cb;
>>> + ctx.start_time = get_timer(0);
>>> + if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
>>> + &ctx, &state)) {
>>> + net_lwip_remove_netif(netif);
>>> + return CMD_RET_FAILURE;
>>> + }
>>> +
>>> + while (!ctx.done) {
>>> + eth_rx();
>>> + sys_check_timeouts();
>>> + if (ctrlc())
>>> + break;
>>> + }
>>> +
>>> + net_lwip_remove_netif(netif);
>>> +
>>> + if (ctx.done == SUCCESS)
>>> + return 0;
>>> +
>>> + return -1;
>>> +}
>>> +
>>> +int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
>>> +{
>>> + char *end;
>>> + char *url;
>>> + ulong dst_addr;
>>> +
>>> + if (argc < 2 || argc > 3)
>>> + return CMD_RET_USAGE;
>>> +
>>> + dst_addr = hextoul(argv[1], &end);
>>> + if (end == (argv[1] + strlen(argv[1]))) {
>>> + if (argc < 3)
>>> + return CMD_RET_USAGE;
>>> + url = argv[2];
>>> + } else {
>>> + dst_addr = image_load_addr;
>>> + url = argv[1];
>>> + }
>>> +
>>> + if (wget_with_dns(dst_addr, url))
>>> + return CMD_RET_FAILURE;
>>> +
>>> + return CMD_RET_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * wget_validate_uri() - validate the uri for wget
>>> + *
>>> + * @uri: uri string
>>> + *
>>> + * This function follows the current U-Boot wget implementation.
>>> + * scheme: only "http:" is supported
>>> + * authority:
>>> + * - user information: not supported
>>> + * - host: supported
>>> + * - port: not supported(always use the default port)
>>> + *
>>> + * Uri is expected to be correctly percent encoded.
>>> + * This is the minimum check, control codes(0x1-0x19, 0x7F, except '\0')
>>> + * and space character(0x20) are not allowed.
>>> + *
>>> + * TODO: stricter uri conformance check
>>> + *
>>> + * Return: true on success, false on failure
>>> + */
>>> +bool wget_validate_uri(char *uri)
>>> +{
>>> + char c;
>>> + bool ret = true;
>>> + char *str_copy, *s, *authority;
>>> +
>>> + for (c = 0x1; c < 0x21; c++) {
>>> + if (strchr(uri, c)) {
>>> + log_err("invalid character is used\n");
>>> + return false;
>>> + }
>>> + }
>>> + if (strchr(uri, 0x7f)) {
>>> + log_err("invalid character is used\n");
>>> + return false;
>>> + }
>>> +
>>> + if (strncmp(uri, "http://", 7)) {
>>> + log_err("only http:// is supported\n");
>>> + return false;
>>> + }
>>> + str_copy = strdup(uri);
>>> + if (!str_copy)
>>> + return false;
>>> +
>>> + s = str_copy + strlen("http://");
>>> + authority = strsep(&s, "/");
>>> + if (!s) {
>>> + log_err("invalid uri, no file path\n");
>>> + ret = false;
>>> + goto out;
>>> + }
>>> + s = strchr(authority, '@');
>>> + if (s) {
>>> + log_err("user information is not supported\n");
>>> + ret = false;
>>> + goto out;
>>> + }
>>> + s = strchr(authority, ':');
>>> + if (s) {
>>> + log_err("user defined port is not supported\n");
>>> + ret = false;
>>> + goto out;
>>> + }
>>> +
>>> +out:
>>> + free(str_copy);
>>> +
>>> + return ret;
>>> +}
>>> --
>>> 2.40.1
>
> Hi Jon,
>
>> Hi Jerome, I am trying out the lwIP stack on TI boards.
>>
>> For wget, I noticed a bug and a user experience improvement. The bug is an
>> off-by-one array access when parsing the url.
>
> Indeed, someone reported this bug to me off-list and it's already fixed in
> my WIP branch.
>
>> The improvement emits a
>> message if the url isn't an http://, since that is all we are supporting,
>> and without the message, the wget command silently fails, which is
>> confusing to the user.
>
> I agree.
>
>> I will post the 2 patches as a reply to this email. LMK if you want to use
>> another method to collaborate. I can already see that efi http boot support
>> will not work. wget_validate_uri() looks to be copied vertabim from the
>> current implementation, and IMO we should completely remove it.
>
> It is indeed copied. It is needed to avoid an unresolved symbol but I
> understand more work may be needed for EFI HTTP boot support (not tested by
> me).
>
> If you are willing to help with this then you are welcome to post patches as
> replies and I will integrate them in the series.
>
> Thanks,
> --
> Jerome
Jerome, here is a patch to allow a port specifier in wget's uri, which lwIP
supports.
thanks
Jon
Subject: [PATCH] net-lwip: lwIP wget supports user defined port in the uri, so
allow it.
Signed-off-by: Jonathan Humphreys <j-humphreys@ti.com>
---
net-lwip/wget.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/net-lwip/wget.c b/net-lwip/wget.c
index 6b9c953ef51..d3fdd44a29e 100644
--- a/net-lwip/wget.c
+++ b/net-lwip/wget.c
@@ -257,12 +257,6 @@ bool wget_validate_uri(char *uri)
ret = false;
goto out;
}
- s = strchr(authority, ':');
- if (s) {
- log_err("user defined port is not supported\n");
- ret = false;
- goto out;
- }
out:
free(str_copy);
--
2.34.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 10/14] net-lwip: add wget command
2024-06-25 3:20 ` Jon Humphreys
@ 2024-06-25 7:43 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-25 7:43 UTC (permalink / raw)
To: Jon Humphreys, u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Tom Rini, Simon Glass,
Mattijs Korpershoek, AKASHI Takahiro, Michal Simek,
Francis Laniel, Peter Robinson
On 6/25/24 05:20, Jon Humphreys wrote:
> Jerome Forissier <jerome.forissier@linaro.org> writes:
>
>> On 6/24/24 08:21, Jon Humphreys wrote:
>>> Jerome Forissier <jerome.forissier@linaro.org> writes:
>>>
>>>> Add support for the wget command with NET_LWIP.
>>>>
>>>> Based on code initially developed by Maxim U.
>>>>
>>>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>>>> Co-developed-by: Maxim Uvarov <muvarov@gmail.com>
>>>> Cc: Maxim Uvarov <muvarov@gmail.com>
>>>> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
>>>> ---
>>>> cmd/Kconfig | 7 ++
>>>> cmd/net-lwip.c | 8 ++
>>>> include/net-lwip.h | 18 +++
>>>> net-lwip/Makefile | 1 +
>>>> net-lwip/wget.c | 269 +++++++++++++++++++++++++++++++++++++++++++++
>>>> 5 files changed, 303 insertions(+)
>>>> create mode 100644 net-lwip/wget.c
>>>>
<snip>
>>>> +/**
>>>> + * wget_validate_uri() - validate the uri for wget
>>>> + *
>>>> + * @uri: uri string
>>>> + *
>>>> + * This function follows the current U-Boot wget implementation.
>>>> + * scheme: only "http:" is supported
>>>> + * authority:
>>>> + * - user information: not supported
>>>> + * - host: supported
>>>> + * - port: not supported(always use the default port)
>>>> + *
>>>> + * Uri is expected to be correctly percent encoded.
>>>> + * This is the minimum check, control codes(0x1-0x19, 0x7F, except '\0')
>>>> + * and space character(0x20) are not allowed.
>>>> + *
>>>> + * TODO: stricter uri conformance check
>>>> + *
>>>> + * Return: true on success, false on failure
>>>> + */
>>>> +bool wget_validate_uri(char *uri)
>>>> +{
>>>> + char c;
>>>> + bool ret = true;
>>>> + char *str_copy, *s, *authority;
>>>> +
>>>> + for (c = 0x1; c < 0x21; c++) {
>>>> + if (strchr(uri, c)) {
>>>> + log_err("invalid character is used\n");
>>>> + return false;
>>>> + }
>>>> + }
>>>> + if (strchr(uri, 0x7f)) {
>>>> + log_err("invalid character is used\n");
>>>> + return false;
>>>> + }
>>>> +
>>>> + if (strncmp(uri, "http://", 7)) {
>>>> + log_err("only http:// is supported\n");
>>>> + return false;
>>>> + }
>>>> + str_copy = strdup(uri);
>>>> + if (!str_copy)
>>>> + return false;
>>>> +
>>>> + s = str_copy + strlen("http://");
>>>> + authority = strsep(&s, "/");
>>>> + if (!s) {
>>>> + log_err("invalid uri, no file path\n");
>>>> + ret = false;
>>>> + goto out;
>>>> + }
>>>> + s = strchr(authority, '@');
>>>> + if (s) {
>>>> + log_err("user information is not supported\n");
>>>> + ret = false;
>>>> + goto out;
>>>> + }
>>>> + s = strchr(authority, ':');
>>>> + if (s) {
>>>> + log_err("user defined port is not supported\n");
>>>> + ret = false;
>>>> + goto out;
>>>> + }
>>>> +
>>>> +out:
>>>> + free(str_copy);
>>>> +
>>>> + return ret;
>>>> +}
>>>> --
>>>> 2.40.1
>>
>> Hi Jon,
>>
>>> Hi Jerome, I am trying out the lwIP stack on TI boards.
>>>
>>> For wget, I noticed a bug and a user experience improvement. The bug is an
>>> off-by-one array access when parsing the url.
>>
>> Indeed, someone reported this bug to me off-list and it's already fixed in
>> my WIP branch.
>>
>>> The improvement emits a
>>> message if the url isn't an http://, since that is all we are supporting,
>>> and without the message, the wget command silently fails, which is
>>> confusing to the user.
>>
>> I agree.
>>
>>> I will post the 2 patches as a reply to this email. LMK if you want to use
>>> another method to collaborate. I can already see that efi http boot support
>>> will not work. wget_validate_uri() looks to be copied vertabim from the
>>> current implementation, and IMO we should completely remove it.
>>
>> It is indeed copied. It is needed to avoid an unresolved symbol but I
>> understand more work may be needed for EFI HTTP boot support (not tested by
>> me).
>>
>> If you are willing to help with this then you are welcome to post patches as
>> replies and I will integrate them in the series.
>>
>> Thanks,
>> --
>> Jerome
>
> Jerome, here is a patch to allow a port specifier in wget's uri, which lwIP
> supports.
>
> thanks
> Jon
>
> Subject: [PATCH] net-lwip: lwIP wget supports user defined port in the uri, so
> allow it.
>
> Signed-off-by: Jonathan Humphreys <j-humphreys@ti.com>
> ---
> net-lwip/wget.c | 6 ------
> 1 file changed, 6 deletions(-)
>
> diff --git a/net-lwip/wget.c b/net-lwip/wget.c
> index 6b9c953ef51..d3fdd44a29e 100644
> --- a/net-lwip/wget.c
> +++ b/net-lwip/wget.c
> @@ -257,12 +257,6 @@ bool wget_validate_uri(char *uri)
> ret = false;
> goto out;
> }
> - s = strchr(authority, ':');
> - if (s) {
> - log_err("user defined port is not supported\n");
> - ret = false;
> - goto out;
> - }
>
> out:
> free(str_copy);
Patch added to v5, thanks!
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH v4 11/14] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (9 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 10/14] net-lwip: add wget command Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-17 15:33 ` [PATCH v4 12/14] configs: add qemu_arm64_lwip_defconfig Jerome Forissier
` (5 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Bin Meng, Marek Vasut, Nikhil M Jain
Support "bdinfo -e" when lwIP is selected.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
---
cmd/bdinfo.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 79106caeec2..690fb894bf6 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -152,7 +152,7 @@ static int bdinfo_print_all(struct bd_info *bd)
bdinfo_print_num_l("relocaddr", gd->relocaddr);
bdinfo_print_num_l("reloc off", gd->reloc_off);
printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
- if (IS_ENABLED(CONFIG_CMD_NET))
+ if (IS_ENABLED(CONFIG_CMD_NET) || IS_ENABLED(CONFIG_CMD_NET_LWIP))
print_eth();
bdinfo_print_num_l("fdt_blob", (ulong)map_to_sysmem(gd->fdt_blob));
bdinfo_print_num_l("new_fdt", (ulong)map_to_sysmem(gd->new_fdt));
@@ -198,7 +198,8 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
case 'a':
return bdinfo_print_all(bd);
case 'e':
- if (!IS_ENABLED(CONFIG_CMD_NET))
+ if (!IS_ENABLED(CONFIG_CMD_NET) &&
+ !IS_ENABLED(CONFIG_CMD_NET_LWIP))
return CMD_RET_USAGE;
print_eth();
return CMD_RET_SUCCESS;
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 12/14] configs: add qemu_arm64_lwip_defconfig
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (10 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 11/14] cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-19 12:14 ` Ilias Apalodimas
2024-06-17 15:33 ` [PATCH v4 13/14] MAINTAINERS: net-lwip: add myself as a maintainer Jerome Forissier
` (4 subsequent siblings)
16 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini
Add qemu_arm64_lwip_defconfig which #include's qemu_arm64_defconfig and
selects NET_LWIP instead of NET. This config has all the supported net
commands enabled.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
configs/qemu_arm64_lwip_defconfig | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 configs/qemu_arm64_lwip_defconfig
diff --git a/configs/qemu_arm64_lwip_defconfig b/configs/qemu_arm64_lwip_defconfig
new file mode 100644
index 00000000000..1f5fd097f0e
--- /dev/null
+++ b/configs/qemu_arm64_lwip_defconfig
@@ -0,0 +1,4 @@
+#include <configs/qemu_arm64_defconfig>
+CONFIG_NET_LWIP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_WGET=y
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 12/14] configs: add qemu_arm64_lwip_defconfig
2024-06-17 15:33 ` [PATCH v4 12/14] configs: add qemu_arm64_lwip_defconfig Jerome Forissier
@ 2024-06-19 12:14 ` Ilias Apalodimas
0 siblings, 0 replies; 53+ messages in thread
From: Ilias Apalodimas @ 2024-06-19 12:14 UTC (permalink / raw)
To: Jerome Forissier; +Cc: u-boot, Javier Tia, Maxim Uvarov, Tom Rini
On Mon, 17 Jun 2024 at 18:33, Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> Add qemu_arm64_lwip_defconfig which #include's qemu_arm64_defconfig and
> selects NET_LWIP instead of NET. This config has all the supported net
> commands enabled.
>
> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
> ---
> configs/qemu_arm64_lwip_defconfig | 4 ++++
> 1 file changed, 4 insertions(+)
> create mode 100644 configs/qemu_arm64_lwip_defconfig
>
> diff --git a/configs/qemu_arm64_lwip_defconfig b/configs/qemu_arm64_lwip_defconfig
> new file mode 100644
> index 00000000000..1f5fd097f0e
> --- /dev/null
> +++ b/configs/qemu_arm64_lwip_defconfig
> @@ -0,0 +1,4 @@
> +#include <configs/qemu_arm64_defconfig>
> +CONFIG_NET_LWIP=y
> +CONFIG_CMD_DNS=y
> +CONFIG_CMD_WGET=y
> --
> 2.40.1
>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH v4 13/14] MAINTAINERS: net-lwip: add myself as a maintainer
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (11 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 12/14] configs: add qemu_arm64_lwip_defconfig Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-17 15:33 ` [PATCH v4 14/14] CI: add qemu_arm64_lwip to the test matrix Jerome Forissier
` (3 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Mattijs Korpershoek, Abdellatif El Khlifi,
Sumit Garg, Marek Vasut, Caleb Connolly, Sam Protsenko,
Nathan Barrett-Morrison
Add myself as a maintainer for the lwIP network stack integration code
and network commands. The library code itself (i.e., most files under
lib/lwip/ except README, Makefile and integration files in u-boot) is
unmodified from upstream and therefore does not need a maintainer.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
MAINTAINERS | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index f8afd7d51e2..11105869304 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1310,6 +1310,17 @@ F: drivers/net/
F: include/net.h
F: net/
+NETWORK (LWIP)
+M: Jerome Forissier <jerome.forissier@linaro.org>
+S: Maintained
+F: cmd/net-lwip.c
+F: configs/qemu_arm64_lwip_defconfig
+F: include/net-lwip.h
+F: lib/lwip/Makefile
+F: lib/lwip/README
+F: lib/lwip/u-boot/
+F: net-lwip/
+
NIOS
M: Thomas Chou <thomas@wytron.com.tw>
S: Maintained
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH v4 14/14] CI: add qemu_arm64_lwip to the test matrix
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (12 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 13/14] MAINTAINERS: net-lwip: add myself as a maintainer Jerome Forissier
@ 2024-06-17 15:33 ` Jerome Forissier
2024-06-18 20:21 ` [PATCH v4 00/14] Introduce the lwIP network stack Tom Rini
` (2 subsequent siblings)
16 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-17 15:33 UTC (permalink / raw)
To: u-boot
Cc: Ilias Apalodimas, Javier Tia, Maxim Uvarov, Jerome Forissier,
Tom Rini, Simon Glass, Leo Yu-Chi Liang
Build and run qemu_arm64_lwip_defconfig in CI. This tests the lightweight
IP (lwIP) implementation of the dhcp, tftpboot and ping commands.
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
---
.azure-pipelines.yml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 27f69583c65..4da1bb12fab 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -199,6 +199,10 @@ stages:
cd \${WORK_DIR}
git config --global --add safe.directory \${WORK_DIR}
git clone --depth=1 https://source.denx.de/u-boot/u-boot-test-hooks /tmp/uboot-test-hooks
+ # qemu_arm64_lwip_defconfig is the same as qemu_arm64 but with NET_LWIP enabled.
+ # The test config and the boardenv file from qemu_arm64 can be re-used so create symlinks
+ ln -s conf.qemu_arm64_na /tmp/uboot-test-hooks/bin/travis-ci/conf.qemu_arm64_lwip_na
+ ln -s u_boot_boardenv_qemu_arm64_na.py /tmp/uboot-test-hooks/py/travis-ci/u_boot_boardenv_qemu_arm64_lwip_na.py
ln -s travis-ci /tmp/uboot-test-hooks/bin/\`hostname\`
ln -s travis-ci /tmp/uboot-test-hooks/py/\`hostname\`
grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
@@ -371,6 +375,9 @@ stages:
qemu_arm64:
TEST_PY_BD: "qemu_arm64"
TEST_PY_TEST_SPEC: "not sleep"
+ qemu_arm64_lwip:
+ TEST_PY_BD: "qemu_arm64_lwip"
+ TEST_PY_TEST_SPEC: "test_net_dhcp or test_net_ping or test_net_tftpboot"
qemu_m68k:
TEST_PY_BD: "M5208EVBE"
TEST_PY_ID: "--id qemu"
--
2.40.1
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (13 preceding siblings ...)
2024-06-17 15:33 ` [PATCH v4 14/14] CI: add qemu_arm64_lwip to the test matrix Jerome Forissier
@ 2024-06-18 20:21 ` Tom Rini
2024-06-19 7:24 ` Ilias Apalodimas
2024-06-20 17:10 ` Tim Harvey
2024-06-21 14:57 ` Simon Glass
16 siblings, 1 reply; 53+ messages in thread
From: Tom Rini @ 2024-06-18 20:21 UTC (permalink / raw)
To: Jerome Forissier; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
[-- Attachment #1: Type: text/plain, Size: 3077 bytes --]
On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> stack [2] [3] as an alternative to the current implementation in net/,
> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> reasons for doing so are:
> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> has some additional lwIP and Mbed TLS patches to do so. With that it
> becomes possible to fetch and launch a distro installer such as Debian
> etc. using a secure, authenticated connection directly from the U-Boot
> shell. Several use cases:
> * Authentication: prevent MITM attack (third party replacing the
> binary with a different one)
> * Confidentiality: prevent third parties from grabbing a copy of the
> image as it is being downloaded
> * Allow connection to servers that do not support plain HTTP anymore
> (this is becoming more and more common on the Internet these days)
> - Possibly benefit from additional features implemented in lwIP
> - Less code to maintain in U-Boot
So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
========================================== FAILURES ===========================================
___________________________________ test_efi_helloworld_net ___________________________________
test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
assert expected_text in output
E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
------------------------------------ Captured stdout call -------------------------------------
U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
Using smsc95xx_eth device
TFTP from server 192.168.1.10; our IP address is 192.168.1.100
Filename 'EFI/arm64/helloworld.efi'.
Load address: 0x200000
Loading:
Bytes transferred = 4528 (11b0 hex)
U-Boot> U-Boot> crc32 200000 $filesize
CRC32 for 00200000 ... 002011af ==> 2b466005
U-Boot> U-Boot> bootefi 200000
No UEFI binary known at 200000
U-Boot>
=================================== short test summary info ===================================
If I disable that test, it moves on to failing the same exact way for
grub. If I disable the grub test too. After that, oh, a bunch of other
tests get skipped because CMD_NET and similar aren't enabled now, and
the tests are wrong. I'll post that as another patch by itself. After
correcting for that, we're seemingly noticeably slower as I need to
increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
testing. We no longer have the estimated speed message, so I can't as
easily say how much slower it is. After increasing the timeout, the
kernel boot test does work.
I can note that normally it takes ~18ms to get a dhcp reply, but with
lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
(which, not great) but if that has a similar level of slowdown, could
well explain it.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-18 20:21 ` [PATCH v4 00/14] Introduce the lwIP network stack Tom Rini
@ 2024-06-19 7:24 ` Ilias Apalodimas
2024-06-19 14:47 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Ilias Apalodimas @ 2024-06-19 7:24 UTC (permalink / raw)
To: Tom Rini; +Cc: Jerome Forissier, u-boot, Javier Tia, Maxim Uvarov
Hi Tom
On Tue, 18 Jun 2024 at 23:21, Tom Rini <trini@konsulko.com> wrote:
>
> On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
>
> > This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> > library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> > stack [2] [3] as an alternative to the current implementation in net/,
> > selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> > reasons for doing so are:
> > - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> > has some additional lwIP and Mbed TLS patches to do so. With that it
> > becomes possible to fetch and launch a distro installer such as Debian
> > etc. using a secure, authenticated connection directly from the U-Boot
> > shell. Several use cases:
> > * Authentication: prevent MITM attack (third party replacing the
> > binary with a different one)
> > * Confidentiality: prevent third parties from grabbing a copy of the
> > image as it is being downloaded
> > * Allow connection to servers that do not support plain HTTP anymore
> > (this is becoming more and more common on the Internet these days)
> > - Possibly benefit from additional features implemented in lwIP
> > - Less code to maintain in U-Boot
>
> So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
> ========================================== FAILURES ===========================================
> ___________________________________ test_efi_helloworld_net ___________________________________
> test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
> assert expected_text in output
> E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
> ------------------------------------ Captured stdout call -------------------------------------
> U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
> Using smsc95xx_eth device
> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> Filename 'EFI/arm64/helloworld.efi'.
> Load address: 0x200000
> Loading:
> Bytes transferred = 4528 (11b0 hex)
> U-Boot> U-Boot> crc32 200000 $filesize
> CRC32 for 00200000 ... 002011af ==> 2b466005
> U-Boot> U-Boot> bootefi 200000
> No UEFI binary known at 200000
> U-Boot>
> =================================== short test summary info ===================================
> If I disable that test, it moves on to failing the same exact way for
> grub. If I disable the grub test too. After that, oh, a bunch of other
> tests get skipped because CMD_NET and similar aren't enabled now, and
> the tests are wrong. I'll post that as another patch by itself. After
> correcting for that, we're seemingly noticeably slower as I need to
> increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
> testing. We no longer have the estimated speed message, so I can't as
> easily say how much slower it is. After increasing the timeout, the
> kernel boot test does work.
>
> I can note that normally it takes ~18ms to get a dhcp reply, but with
> lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
> (which, not great) but if that has a similar level of slowdown, could
> well explain it.
>
Thanks for taking the time. We'll run the pytests before v5. That
being said, my wget tests were faster with lwIP last time I checked.
Thanks
/Ilias
> --
> Tom
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-19 7:24 ` Ilias Apalodimas
@ 2024-06-19 14:47 ` Jerome Forissier
2024-06-19 15:07 ` Tom Rini
2024-06-19 17:19 ` Peter Robinson
0 siblings, 2 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-19 14:47 UTC (permalink / raw)
To: Ilias Apalodimas, Tom Rini; +Cc: u-boot, Javier Tia, Maxim Uvarov
On 6/19/24 09:24, Ilias Apalodimas wrote:
> Hi Tom
>
> On Tue, 18 Jun 2024 at 23:21, Tom Rini <trini@konsulko.com> wrote:
>>
>> On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
>>
>>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>>> stack [2] [3] as an alternative to the current implementation in net/,
>>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>>> reasons for doing so are:
>>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>>> has some additional lwIP and Mbed TLS patches to do so. With that it
>>> becomes possible to fetch and launch a distro installer such as Debian
>>> etc. using a secure, authenticated connection directly from the U-Boot
>>> shell. Several use cases:
>>> * Authentication: prevent MITM attack (third party replacing the
>>> binary with a different one)
>>> * Confidentiality: prevent third parties from grabbing a copy of the
>>> image as it is being downloaded
>>> * Allow connection to servers that do not support plain HTTP anymore
>>> (this is becoming more and more common on the Internet these days)
>>> - Possibly benefit from additional features implemented in lwIP
>>> - Less code to maintain in U-Boot
>>
>> So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
>> ========================================== FAILURES ===========================================
>> ___________________________________ test_efi_helloworld_net ___________________________________
>> test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
>> assert expected_text in output
>> E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
>> ------------------------------------ Captured stdout call -------------------------------------
>> U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
>> Using smsc95xx_eth device
>> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
>> Filename 'EFI/arm64/helloworld.efi'.
>> Load address: 0x200000
>> Loading:
>> Bytes transferred = 4528 (11b0 hex)
>> U-Boot> U-Boot> crc32 200000 $filesize
>> CRC32 for 00200000 ... 002011af ==> 2b466005
>> U-Boot> U-Boot> bootefi 200000
>> No UEFI binary known at 200000
>> U-Boot>
>> =================================== short test summary info ===================================
>> If I disable that test, it moves on to failing the same exact way for
>> grub. If I disable the grub test too. After that, oh, a bunch of other
>> tests get skipped because CMD_NET and similar aren't enabled now, and
>> the tests are wrong. I'll post that as another patch by itself. After
>> correcting for that, we're seemingly noticeably slower as I need to
>> increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
>> testing. We no longer have the estimated speed message, so I can't as
>> easily say how much slower it is. After increasing the timeout, the
>> kernel boot test does work.
>>
>> I can note that normally it takes ~18ms to get a dhcp reply, but with
>> lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
>> (which, not great) but if that has a similar level of slowdown, could
>> well explain it.
>>
>
> Thanks for taking the time. We'll run the pytests before v5. That
> being said, my wget tests were faster with lwIP last time I checked.
The reason for the slower TFTP is the block size. lwIP supports only the
default (512 bytes), while the legacy stack supports the 'blksize' option
and sets CONFIG_TFTP_BLOCKSIZE=1468 by default.
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-19 14:47 ` Jerome Forissier
@ 2024-06-19 15:07 ` Tom Rini
2024-06-19 16:45 ` Jerome Forissier
2024-06-19 17:19 ` Peter Robinson
1 sibling, 1 reply; 53+ messages in thread
From: Tom Rini @ 2024-06-19 15:07 UTC (permalink / raw)
To: Jerome Forissier; +Cc: Ilias Apalodimas, u-boot, Javier Tia, Maxim Uvarov
[-- Attachment #1: Type: text/plain, Size: 4251 bytes --]
On Wed, Jun 19, 2024 at 04:47:08PM +0200, Jerome Forissier wrote:
>
>
> On 6/19/24 09:24, Ilias Apalodimas wrote:
> > Hi Tom
> >
> > On Tue, 18 Jun 2024 at 23:21, Tom Rini <trini@konsulko.com> wrote:
> >>
> >> On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
> >>
> >>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> >>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> >>> stack [2] [3] as an alternative to the current implementation in net/,
> >>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> >>> reasons for doing so are:
> >>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> >>> has some additional lwIP and Mbed TLS patches to do so. With that it
> >>> becomes possible to fetch and launch a distro installer such as Debian
> >>> etc. using a secure, authenticated connection directly from the U-Boot
> >>> shell. Several use cases:
> >>> * Authentication: prevent MITM attack (third party replacing the
> >>> binary with a different one)
> >>> * Confidentiality: prevent third parties from grabbing a copy of the
> >>> image as it is being downloaded
> >>> * Allow connection to servers that do not support plain HTTP anymore
> >>> (this is becoming more and more common on the Internet these days)
> >>> - Possibly benefit from additional features implemented in lwIP
> >>> - Less code to maintain in U-Boot
> >>
> >> So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
> >> ========================================== FAILURES ===========================================
> >> ___________________________________ test_efi_helloworld_net ___________________________________
> >> test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
> >> assert expected_text in output
> >> E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
> >> ------------------------------------ Captured stdout call -------------------------------------
> >> U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
> >> Using smsc95xx_eth device
> >> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> >> Filename 'EFI/arm64/helloworld.efi'.
> >> Load address: 0x200000
> >> Loading:
> >> Bytes transferred = 4528 (11b0 hex)
> >> U-Boot> U-Boot> crc32 200000 $filesize
> >> CRC32 for 00200000 ... 002011af ==> 2b466005
> >> U-Boot> U-Boot> bootefi 200000
> >> No UEFI binary known at 200000
> >> U-Boot>
> >> =================================== short test summary info ===================================
> >> If I disable that test, it moves on to failing the same exact way for
> >> grub. If I disable the grub test too. After that, oh, a bunch of other
> >> tests get skipped because CMD_NET and similar aren't enabled now, and
> >> the tests are wrong. I'll post that as another patch by itself. After
> >> correcting for that, we're seemingly noticeably slower as I need to
> >> increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
> >> testing. We no longer have the estimated speed message, so I can't as
> >> easily say how much slower it is. After increasing the timeout, the
> >> kernel boot test does work.
> >>
> >> I can note that normally it takes ~18ms to get a dhcp reply, but with
> >> lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
> >> (which, not great) but if that has a similar level of slowdown, could
> >> well explain it.
> >>
> >
> > Thanks for taking the time. We'll run the pytests before v5. That
> > being said, my wget tests were faster with lwIP last time I checked.
>
> The reason for the slower TFTP is the block size. lwIP supports only the
> default (512 bytes), while the legacy stack supports the 'blksize' option
> and sets CONFIG_TFTP_BLOCKSIZE=1468 by default.
Ouch. Can we ask if upstream is agreeable to making that configurable
some way, and then we utilize that? I'm not looking forward to lots of
performance hit reports.
But please note that my dhcp request/reply is also taking 10x as long,
and in v3 it wasn't working at all? I feel like there's possibly another
issue lurking here.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-19 15:07 ` Tom Rini
@ 2024-06-19 16:45 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-19 16:45 UTC (permalink / raw)
To: Tom Rini; +Cc: Ilias Apalodimas, u-boot, Javier Tia, Maxim Uvarov
On 6/19/24 17:07, Tom Rini wrote:
> On Wed, Jun 19, 2024 at 04:47:08PM +0200, Jerome Forissier wrote:
>>
>>
>> On 6/19/24 09:24, Ilias Apalodimas wrote:
>>> Hi Tom
>>>
>>> On Tue, 18 Jun 2024 at 23:21, Tom Rini <trini@konsulko.com> wrote:
>>>>
>>>> On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
>>>>
>>>>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>>>>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>>>>> stack [2] [3] as an alternative to the current implementation in net/,
>>>>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>>>>> reasons for doing so are:
>>>>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>>>>> has some additional lwIP and Mbed TLS patches to do so. With that it
>>>>> becomes possible to fetch and launch a distro installer such as Debian
>>>>> etc. using a secure, authenticated connection directly from the U-Boot
>>>>> shell. Several use cases:
>>>>> * Authentication: prevent MITM attack (third party replacing the
>>>>> binary with a different one)
>>>>> * Confidentiality: prevent third parties from grabbing a copy of the
>>>>> image as it is being downloaded
>>>>> * Allow connection to servers that do not support plain HTTP anymore
>>>>> (this is becoming more and more common on the Internet these days)
>>>>> - Possibly benefit from additional features implemented in lwIP
>>>>> - Less code to maintain in U-Boot
>>>>
>>>> So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
>>>> ========================================== FAILURES ===========================================
>>>> ___________________________________ test_efi_helloworld_net ___________________________________
>>>> test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
>>>> assert expected_text in output
>>>> E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
>>>> ------------------------------------ Captured stdout call -------------------------------------
>>>> U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
>>>> Using smsc95xx_eth device
>>>> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
>>>> Filename 'EFI/arm64/helloworld.efi'.
>>>> Load address: 0x200000
>>>> Loading:
>>>> Bytes transferred = 4528 (11b0 hex)
>>>> U-Boot> U-Boot> crc32 200000 $filesize
>>>> CRC32 for 00200000 ... 002011af ==> 2b466005
>>>> U-Boot> U-Boot> bootefi 200000
>>>> No UEFI binary known at 200000
>>>> U-Boot>
>>>> =================================== short test summary info ===================================
>>>> If I disable that test, it moves on to failing the same exact way for
>>>> grub. If I disable the grub test too. After that, oh, a bunch of other
>>>> tests get skipped because CMD_NET and similar aren't enabled now, and
>>>> the tests are wrong. I'll post that as another patch by itself. After
>>>> correcting for that, we're seemingly noticeably slower as I need to
>>>> increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
>>>> testing. We no longer have the estimated speed message, so I can't as
>>>> easily say how much slower it is. After increasing the timeout, the
>>>> kernel boot test does work.
>>>>
>>>> I can note that normally it takes ~18ms to get a dhcp reply, but with
>>>> lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
>>>> (which, not great) but if that has a similar level of slowdown, could
>>>> well explain it.
>>>>
>>>
>>> Thanks for taking the time. We'll run the pytests before v5. That
>>> being said, my wget tests were faster with lwIP last time I checked.
>>
>> The reason for the slower TFTP is the block size. lwIP supports only the
>> default (512 bytes), while the legacy stack supports the 'blksize' option
>> and sets CONFIG_TFTP_BLOCKSIZE=1468 by default.
>
> Ouch. Can we ask if upstream is agreeable to making that configurable
> some way, and then we utilize that? I'm not looking forward to lots of
> performance hit reports.
I tried a quick & dirty hack to hardcode the blksize option in the lwIP
stack and I can confirm I get the same speed as with the legacy
implementation or even slightly better (legacy: 822 KB/s, hacked lwIP:
843 KB/s, upstream lwIP: 343 KB/s). That's on QEMU with py3tftp running on
my laptop as a TFTP server. I would probably get better results with a
good TFTP server and real hardware (RPi...) but at least this shows lwIP
can be on par with the U-Boot stack.
I can consider writing a better patch for lwIP and submitting it upstream.
> But please note that my dhcp request/reply is also taking 10x as long,
> and in v3 it wasn't working at all? I feel like there's possibly another
> issue lurking here.
This I need to investigate more on my RPi. I'll keep you posted. Thanks
again for testing.
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-19 14:47 ` Jerome Forissier
2024-06-19 15:07 ` Tom Rini
@ 2024-06-19 17:19 ` Peter Robinson
2024-06-20 8:05 ` Jerome Forissier
1 sibling, 1 reply; 53+ messages in thread
From: Peter Robinson @ 2024-06-19 17:19 UTC (permalink / raw)
To: Jerome Forissier
Cc: Ilias Apalodimas, Tom Rini, u-boot, Javier Tia, Maxim Uvarov
On Wed, 19 Jun 2024 at 16:06, Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
>
>
> On 6/19/24 09:24, Ilias Apalodimas wrote:
> > Hi Tom
> >
> > On Tue, 18 Jun 2024 at 23:21, Tom Rini <trini@konsulko.com> wrote:
> >>
> >> On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
> >>
> >>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> >>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> >>> stack [2] [3] as an alternative to the current implementation in net/,
> >>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> >>> reasons for doing so are:
> >>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> >>> has some additional lwIP and Mbed TLS patches to do so. With that it
> >>> becomes possible to fetch and launch a distro installer such as Debian
> >>> etc. using a secure, authenticated connection directly from the U-Boot
> >>> shell. Several use cases:
> >>> * Authentication: prevent MITM attack (third party replacing the
> >>> binary with a different one)
> >>> * Confidentiality: prevent third parties from grabbing a copy of the
> >>> image as it is being downloaded
> >>> * Allow connection to servers that do not support plain HTTP anymore
> >>> (this is becoming more and more common on the Internet these days)
> >>> - Possibly benefit from additional features implemented in lwIP
> >>> - Less code to maintain in U-Boot
> >>
> >> So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
> >> ========================================== FAILURES ===========================================
> >> ___________________________________ test_efi_helloworld_net ___________________________________
> >> test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
> >> assert expected_text in output
> >> E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
> >> ------------------------------------ Captured stdout call -------------------------------------
> >> U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
> >> Using smsc95xx_eth device
> >> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
> >> Filename 'EFI/arm64/helloworld.efi'.
> >> Load address: 0x200000
> >> Loading:
> >> Bytes transferred = 4528 (11b0 hex)
> >> U-Boot> U-Boot> crc32 200000 $filesize
> >> CRC32 for 00200000 ... 002011af ==> 2b466005
> >> U-Boot> U-Boot> bootefi 200000
> >> No UEFI binary known at 200000
> >> U-Boot>
> >> =================================== short test summary info ===================================
> >> If I disable that test, it moves on to failing the same exact way for
> >> grub. If I disable the grub test too. After that, oh, a bunch of other
> >> tests get skipped because CMD_NET and similar aren't enabled now, and
> >> the tests are wrong. I'll post that as another patch by itself. After
> >> correcting for that, we're seemingly noticeably slower as I need to
> >> increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
> >> testing. We no longer have the estimated speed message, so I can't as
> >> easily say how much slower it is. After increasing the timeout, the
> >> kernel boot test does work.
> >>
> >> I can note that normally it takes ~18ms to get a dhcp reply, but with
> >> lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
> >> (which, not great) but if that has a similar level of slowdown, could
> >> well explain it.
> >>
> >
> > Thanks for taking the time. We'll run the pytests before v5. That
> > being said, my wget tests were faster with lwIP last time I checked.
>
> The reason for the slower TFTP is the block size. lwIP supports only the
> default (512 bytes), while the legacy stack supports the 'blksize' option
> and sets CONFIG_TFTP_BLOCKSIZE=1468 by default.
This number looks like it's derived from standard ethernet frame
(1500) minus default packet sizes to get to 1468. Does LWIP have a
concept of MTU? I would have thought it would be better to use MTU if
so because it then means it's not hard coded and it can change based
on what the driver/HW supports?
Peter
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-19 17:19 ` Peter Robinson
@ 2024-06-20 8:05 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-20 8:05 UTC (permalink / raw)
To: Peter Robinson
Cc: Ilias Apalodimas, Tom Rini, u-boot, Javier Tia, Maxim Uvarov
On 6/19/24 19:19, Peter Robinson wrote:
> On Wed, 19 Jun 2024 at 16:06, Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>>
>>
>> On 6/19/24 09:24, Ilias Apalodimas wrote:
>>> Hi Tom
>>>
>>> On Tue, 18 Jun 2024 at 23:21, Tom Rini <trini@konsulko.com> wrote:
>>>>
>>>> On Mon, Jun 17, 2024 at 05:32:52PM +0200, Jerome Forissier wrote:
>>>>
>>>>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>>>>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>>>>> stack [2] [3] as an alternative to the current implementation in net/,
>>>>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>>>>> reasons for doing so are:
>>>>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>>>>> has some additional lwIP and Mbed TLS patches to do so. With that it
>>>>> becomes possible to fetch and launch a distro installer such as Debian
>>>>> etc. using a secure, authenticated connection directly from the U-Boot
>>>>> shell. Several use cases:
>>>>> * Authentication: prevent MITM attack (third party replacing the
>>>>> binary with a different one)
>>>>> * Confidentiality: prevent third parties from grabbing a copy of the
>>>>> image as it is being downloaded
>>>>> * Allow connection to servers that do not support plain HTTP anymore
>>>>> (this is becoming more and more common on the Internet these days)
>>>>> - Possibly benefit from additional features implemented in lwIP
>>>>> - Less code to maintain in U-Boot
>>>>
>>>> So, on a Pi 3 (rpi_3_defconfig) I see this now (and it passes normally):
>>>> ========================================== FAILURES ===========================================
>>>> ___________________________________ test_efi_helloworld_net ___________________________________
>>>> test/py/tests/test_efi_loader.py:163: in test_efi_helloworld_net
>>>> assert expected_text in output
>>>> E AssertionError: assert 'Hello, world' in 'No UEFI binary known at 200000'
>>>> ------------------------------------ Captured stdout call -------------------------------------
>>>> U-Boot> tftpboot 200000 EFI/arm64/helloworld.efi
>>>> Using smsc95xx_eth device
>>>> TFTP from server 192.168.1.10; our IP address is 192.168.1.100
>>>> Filename 'EFI/arm64/helloworld.efi'.
>>>> Load address: 0x200000
>>>> Loading:
>>>> Bytes transferred = 4528 (11b0 hex)
>>>> U-Boot> U-Boot> crc32 200000 $filesize
>>>> CRC32 for 00200000 ... 002011af ==> 2b466005
>>>> U-Boot> U-Boot> bootefi 200000
>>>> No UEFI binary known at 200000
>>>> U-Boot>
>>>> =================================== short test summary info ===================================
>>>> If I disable that test, it moves on to failing the same exact way for
>>>> grub. If I disable the grub test too. After that, oh, a bunch of other
>>>> tests get skipped because CMD_NET and similar aren't enabled now, and
>>>> the tests are wrong. I'll post that as another patch by itself. After
>>>> correcting for that, we're seemingly noticeably slower as I need to
>>>> increase the timeout for tftp'ing my 83MiB FIT image I use for kernel
>>>> testing. We no longer have the estimated speed message, so I can't as
>>>> easily say how much slower it is. After increasing the timeout, the
>>>> kernel boot test does work.
>>>>
>>>> I can note that normally it takes ~18ms to get a dhcp reply, but with
>>>> lwIP it's now 132ms, and previously the kernel loaded at 2.7MiB/s
>>>> (which, not great) but if that has a similar level of slowdown, could
>>>> well explain it.
>>>>
>>>
>>> Thanks for taking the time. We'll run the pytests before v5. That
>>> being said, my wget tests were faster with lwIP last time I checked.
>>
>> The reason for the slower TFTP is the block size. lwIP supports only the
>> default (512 bytes), while the legacy stack supports the 'blksize' option
>> and sets CONFIG_TFTP_BLOCKSIZE=1468 by default.
>
> This number looks like it's derived from standard ethernet frame
> (1500) minus default packet sizes to get to 1468. Does LWIP have a
> concept of MTU?
It does (netif->mtu), although it does not have path MTU discovery. But for
the use cases we consider (mostly booting from the LAN) it shouldn't matter.
> I would have thought it would be better to use MTU if
> so because it then means it's not hard coded and it can change based
> on what the driver/HW supports?
I agree but for maximum flexibility I plan to extend the lwIP API and set
blksize to the mtu in the caller (net-lwip/tftp.c):
tftp_init_client(&ctx); // Provide the callbacks
tftp_client_set_bksize(netif->mtu); // New function
tftp_get(&ctx, addr, port, fname, mode); // Start the transfer
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (14 preceding siblings ...)
2024-06-18 20:21 ` [PATCH v4 00/14] Introduce the lwIP network stack Tom Rini
@ 2024-06-20 17:10 ` Tim Harvey
2024-06-21 12:59 ` Jerome Forissier
2024-06-21 14:57 ` Simon Glass
16 siblings, 1 reply; 53+ messages in thread
From: Tim Harvey @ 2024-06-20 17:10 UTC (permalink / raw)
To: Jerome Forissier; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
On Mon, Jun 17, 2024 at 8:33 AM Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> stack [2] [3] as an alternative to the current implementation in net/,
> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> reasons for doing so are:
> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> has some additional lwIP and Mbed TLS patches to do so. With that it
> becomes possible to fetch and launch a distro installer such as Debian
> etc. using a secure, authenticated connection directly from the U-Boot
> shell. Several use cases:
> * Authentication: prevent MITM attack (third party replacing the
> binary with a different one)
> * Confidentiality: prevent third parties from grabbing a copy of the
> image as it is being downloaded
> * Allow connection to servers that do not support plain HTTP anymore
> (this is becoming more and more common on the Internet these days)
> - Possibly benefit from additional features implemented in lwIP
> - Less code to maintain in U-Boot
>
> Prior to applying this series, the lwIP stack needs to be added as a
> Git subtree with the following command:
>
> $ git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE
>
> The first patch renames some enums in order to avoid a conflict when a
> later patch enables the lwIP library.
>
> The second patch introduces a new Kconfig symbol: NET_LWIP, which selects
> the lwIP implementation instead of the current one (NET). Contrary to the
> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
> simultaneously. The rationale is we want to start from a clean state and
> not pull potentially duplicated functionality from both stacks. Note
> however that a few files are still built in net/, they are the ones
> related to ethernet device management and the ethernet bootflow.
>
> The third patch splits the net.h header into net-legacy.h, net-common.h,
> net-lwip.h, leaving net.h as a simple wrapper.
>
> The fourth patch introduces the Makefile to build lwIP when NET_LWIP is
> enabled.
>
> The subsequent patches implement various network-oriented commands and
> features: dhcp, dns, ping, tftpboot, wget.
>
> A number of features are currently incompatible with NET_LWIP: SANDBOX,
> DFU_TFTP, FASTBOOT, SPL_NET. All make assumptions on how the network
> stack is implemented and/or pull sybols that are not trivially exported
> from lwIP. Some interface rework may be needed.
>
> Due to the above and in order to provide some level of testing, a new QEMU
> configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
> as qemu_arm64_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
> Tests are added to test/py/tests/test_net.py for that configuration.
>
Hi Jermone,
I've given this a spin on an imx8mm-venice-gw73xx-0x via
imx8mm_venice_defconfig and I can't get DHCP to work (didn't work in
v3 either):
$ diff defconfig configs/imx8mm_venice_defconfig
68,69c68,71
< CONFIG_CMD_DNS_LWIP=y
< CONFIG_CMD_WGET_LWIP=y
---
> CONFIG_CMD_DHCP6=y
> CONFIG_CMD_TFTPPUT=y
> CONFIG_SYS_DISABLE_AUTOLOAD=y
> CONFIG_CMD_WGET=y
88,90c90,94
< CONFIG_NET_LWIP=y
< CONFIG_LWIP_DEBUG=y
< CONFIG_LWIP_ASSERT=y
---
> CONFIG_NET_RANDOM_ETHADDR=y
> CONFIG_IP_DEFRAG=y
> CONFIG_TFTP_BLOCKSIZE=4096
> CONFIG_PROT_TCP_SACK=y
> CONFIG_IPV6=y
Target:
u-boot=> net list
eth0 : ethernet@30be0000 00:d0:12:b5:f8:41 active
u-boot=> dhcp || echo fail
eth0: ethernet@30be0000 00:d0:12:b5:f8:41 active
netif_set_ipaddr: netif address being changed
netif: added interface 0 addr 192.168.1.1 netmask 0.0.0.0 gw 0.0.0.0
etharp_request: sending ARP request.
etharp_raw: sending raw ARP packet.
ethernet_output: sending packet 000000007df00bf0
dhcp_start(netif=000000007df2af40) 0dhcp_start(): mallocing new DHCP client
dhcp_start(): allocated dhcp
dhcp_start(): starting DHCP configuration
dhcp_discover()
transaction id xid(42021)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
ip4_output_if: 0IP header:
+-------------------------------+
| 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
+-------------------------------+
| 0 |000| 0 | (id, flags, offset)
+-------------------------------+
| 255 | 17 | 0xba9d | (ttl, proto, chksum)
+-------------------------------+
| 0 | 0 | 0 | 0 | (src)
+-------------------------------+
| 255 | 255 | 255 | 255 | (dest)
+-------------------------------+
ip4_output_if: call netif->output()
ethernet_output: sending packet 000000007df2c010
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 2000 msecs
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:28:28:5d:bb:16:9f, type:8899
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:00:27:0e:0d:74:ba, type:806
etharp_update_arp_entry: 172.24.20.24 - 00:27:0e:0d:74:ba
etharp_find_entry: found empty entry 0
etharp_find_entry: no empty entry found and not allowed to recycle
etharp_input: incoming ARP request
etharp_input: ARP request was not for us.
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:98:90:96:ac:d7:63, type:806
etharp_update_arp_entry: 172.24.20.3 - 98:90:96:ac:d7:63
etharp_find_entry: found empty entry 0
etharp_find_entry: no empty entry found and not allowed to recycle
etharp_input: incoming ARP request
etharp_input: ARP request was not for us.
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:84:2b:2b:4e:5a:9a, type:806
etharp_update_arp_entry: 172.24.0.1 - 84:2b:2b:4e:5a:9a
etharp_find_entry: found empty entry 0
etharp_find_entry: no empty entry found and not allowed to recycle
etharp_input: incoming ARP request
etharp_input: ARP request was not for us.
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:cc:96:e5:1e:a0:7b, type:800
ip_input: iphdr->dest 0xffff1fac netif->ip_addr 0x101a8c0 (0x0, 0x0, 0xffff1fac)
ip4_input: UDP packet to DHCP client port 138
ip4_input: packet not for us.
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:d4:be:d9:9f:5a:b4, type:800
ip_input: iphdr->dest 0xffffffff netif->ip_addr 0x101a8c0 (0x0, 0x0, 0xffffffff)
ip4_input: packet accepted on interface 0ip4_input:
IP header:
+-------------------------------+
| 4 | 5 | 0x00 | 68 | (v, hl, tos, len)
+-------------------------------+
| 19472 |000| 0 | (id, flags, offset)
+-------------------------------+
| 128 | 17 | 0x2e51 | (ttl, proto, chksum)
+-------------------------------+
| 172 | 24 | 20 | 48 | (src)
+-------------------------------+
| 255 | 255 | 255 | 255 | (dest)
+-------------------------------+
ip4_input: p->len 68 p->tot_len 68
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:00:0b:ab:2e:fa:51, type:806
etharp_update_arp_entry: 172.24.24.181 - 00:0b:ab:2e:fa:51
etharp_find_entry: found empty entry 0
etharp_find_entry: no empty entry found and not allowed to recycle
etharp_input: incoming ARP request
etharp_input: ARP request was not for us.
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:98:90:96:ac:d7:63, type:806
etharp_update_arp_entry: 172.24.20.3 - 98:90:96:ac:d7:63
etharp_find_entry: found empty entry 0
etharp_find_entry: no empty entry found and not allowed to recycle
etharp_input: incoming ARP request
etharp_input: ARP request was not for us.
ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:84:2b:2b:4e:5a:9a, type:806
etharp_update_arp_entry: 172.24.0.1 - 84:2b:2b:4e:5a:9a
etharp_find_entry: found empty entry 0
etharp_find_entry: no empty entry found and not allowed to recycle
etharp_input: incoming ARP request
etharp_input: ARP request was not for us.
fail
Even using ping before DHCP fails:
u-boot=> setenv ipaddr 192.168.1.1; ping 192.168.1.146 || echo fail
Using ethernet@30be0000 device
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ip4_route: No route to 192.168.1.146
ping failed; host 192.168.1.146 is not alive
fail
Best Regards,
Tim
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-20 17:10 ` Tim Harvey
@ 2024-06-21 12:59 ` Jerome Forissier
2024-06-21 16:08 ` Tim Harvey
0 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-21 12:59 UTC (permalink / raw)
To: Tim Harvey; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
On 6/20/24 19:10, Tim Harvey wrote:
> On Mon, Jun 17, 2024 at 8:33 AM Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>> stack [2] [3] as an alternative to the current implementation in net/,
>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>> reasons for doing so are:
>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>> has some additional lwIP and Mbed TLS patches to do so. With that it
>> becomes possible to fetch and launch a distro installer such as Debian
>> etc. using a secure, authenticated connection directly from the U-Boot
>> shell. Several use cases:
>> * Authentication: prevent MITM attack (third party replacing the
>> binary with a different one)
>> * Confidentiality: prevent third parties from grabbing a copy of the
>> image as it is being downloaded
>> * Allow connection to servers that do not support plain HTTP anymore
>> (this is becoming more and more common on the Internet these days)
>> - Possibly benefit from additional features implemented in lwIP
>> - Less code to maintain in U-Boot
>>
>> Prior to applying this series, the lwIP stack needs to be added as a
>> Git subtree with the following command:
>>
>> $ git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE
>>
>> The first patch renames some enums in order to avoid a conflict when a
>> later patch enables the lwIP library.
>>
>> The second patch introduces a new Kconfig symbol: NET_LWIP, which selects
>> the lwIP implementation instead of the current one (NET). Contrary to the
>> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
>> simultaneously. The rationale is we want to start from a clean state and
>> not pull potentially duplicated functionality from both stacks. Note
>> however that a few files are still built in net/, they are the ones
>> related to ethernet device management and the ethernet bootflow.
>>
>> The third patch splits the net.h header into net-legacy.h, net-common.h,
>> net-lwip.h, leaving net.h as a simple wrapper.
>>
>> The fourth patch introduces the Makefile to build lwIP when NET_LWIP is
>> enabled.
>>
>> The subsequent patches implement various network-oriented commands and
>> features: dhcp, dns, ping, tftpboot, wget.
>>
>> A number of features are currently incompatible with NET_LWIP: SANDBOX,
>> DFU_TFTP, FASTBOOT, SPL_NET. All make assumptions on how the network
>> stack is implemented and/or pull sybols that are not trivially exported
>> from lwIP. Some interface rework may be needed.
>>
>> Due to the above and in order to provide some level of testing, a new QEMU
>> configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
>> as qemu_arm64_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
>> Tests are added to test/py/tests/test_net.py for that configuration.
>>
>
> Hi Jermone,
>
> I've given this a spin on an imx8mm-venice-gw73xx-0x via
> imx8mm_venice_defconfig and I can't get DHCP to work (didn't work in
> v3 either):
>
> $ diff defconfig configs/imx8mm_venice_defconfig
> 68,69c68,71
> < CONFIG_CMD_DNS_LWIP=y
> < CONFIG_CMD_WGET_LWIP=y
> ---
>> CONFIG_CMD_DHCP6=y
>> CONFIG_CMD_TFTPPUT=y
>> CONFIG_SYS_DISABLE_AUTOLOAD=y
>> CONFIG_CMD_WGET=y
> 88,90c90,94
> < CONFIG_NET_LWIP=y
> < CONFIG_LWIP_DEBUG=y
> < CONFIG_LWIP_ASSERT=y
> ---
>> CONFIG_NET_RANDOM_ETHADDR=y
>> CONFIG_IP_DEFRAG=y
>> CONFIG_TFTP_BLOCKSIZE=4096
>> CONFIG_PROT_TCP_SACK=y
>> CONFIG_IPV6=y
>
> Target:
> u-boot=> net list
> eth0 : ethernet@30be0000 00:d0:12:b5:f8:41 active
> u-boot=> dhcp || echo fail
> eth0: ethernet@30be0000 00:d0:12:b5:f8:41 active
> netif_set_ipaddr: netif address being changed
> netif: added interface 0 addr 192.168.1.1 netmask 0.0.0.0 gw 0.0.0.0
> etharp_request: sending ARP request.
> etharp_raw: sending raw ARP packet.
> ethernet_output: sending packet 000000007df00bf0
> dhcp_start(netif=000000007df2af40) 0dhcp_start(): mallocing new DHCP client
> dhcp_start(): allocated dhcp
> dhcp_start(): starting DHCP configuration
> dhcp_discover()
> transaction id xid(42021)
> dhcp_discover: making request
> dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
> ip4_output_if: 0IP header:
> +-------------------------------+
> | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
> +-------------------------------+
> | 0 |000| 0 | (id, flags, offset)
> +-------------------------------+
> | 255 | 17 | 0xba9d | (ttl, proto, chksum)
> +-------------------------------+
> | 0 | 0 | 0 | 0 | (src)
> +-------------------------------+
> | 255 | 255 | 255 | 255 | (dest)
> +-------------------------------+
> ip4_output_if: call netif->output()
> ethernet_output: sending packet 000000007df2c010
> dhcp_discover: deleting()
> dhcp_discover: SELECTING
> dhcp_discover(): set request timeout 2000 msecs
> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:28:28:5d:bb:16:9f, type:8899
> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:00:27:0e:0d:74:ba, type:806
> etharp_update_arp_entry: 172.24.20.24 - 00:27:0e:0d:74:ba
> etharp_find_entry: found empty entry 0
> etharp_find_entry: no empty entry found and not allowed to recycle
> etharp_input: incoming ARP request
> etharp_input: ARP request was not for us.
> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:98:90:96:ac:d7:63, type:806
> etharp_update_arp_entry: 172.24.20.3 - 98:90:96:ac:d7:63
> etharp_find_entry: found empty entry 0
> etharp_find_entry: no empty entry found and not allowed to recycle
> etharp_input: incoming ARP request
> etharp_input: ARP request was not for us.
> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:84:2b:2b:4e:5a:9a, type:806
> etharp_update_arp_entry: 172.24.0.1 - 84:2b:2b:4e:5a:9a
> etharp_find_entry: found empty entry 0
> etharp_find_entry: no empty entry found and not allowed to recycle
> etharp_input: incoming ARP request
> etharp_input: ARP request was not for us.
> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:cc:96:e5:1e:a0:7b, type:800
> ip_input: iphdr->dest 0xffff1fac netif->ip_addr 0x101a8c0 (0x0, 0x0, 0xffff1fac)
> ip4_input: UDP packet to DHCP client port 138
> ip4_input: packet not for us.
That's weird. I think what could happen is the interface already has
a static IP assigned when it is registered to the lwIP stack and thus
DHCP never receives the packed because it is dropped before.
I have reworked the initialization code in v5, lwIP will get to know
only one interface at a time and I make sure that interface is registered
without an IP address when doing DHCP. Hopefully that should fix the issue.
Thanks for testing!
--
Jerome
>
> Best Regards,
>
> Tim
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-21 12:59 ` Jerome Forissier
@ 2024-06-21 16:08 ` Tim Harvey
2024-06-21 17:56 ` Jerome Forissier
2024-06-21 18:42 ` Fabio Estevam
0 siblings, 2 replies; 53+ messages in thread
From: Tim Harvey @ 2024-06-21 16:08 UTC (permalink / raw)
To: Jerome Forissier; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
On Fri, Jun 21, 2024 at 5:59 AM Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
>
>
> On 6/20/24 19:10, Tim Harvey wrote:
> > On Mon, Jun 17, 2024 at 8:33 AM Jerome Forissier
> > <jerome.forissier@linaro.org> wrote:
> >>
> >> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> >> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> >> stack [2] [3] as an alternative to the current implementation in net/,
> >> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> >> reasons for doing so are:
> >> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> >> has some additional lwIP and Mbed TLS patches to do so. With that it
> >> becomes possible to fetch and launch a distro installer such as Debian
> >> etc. using a secure, authenticated connection directly from the U-Boot
> >> shell. Several use cases:
> >> * Authentication: prevent MITM attack (third party replacing the
> >> binary with a different one)
> >> * Confidentiality: prevent third parties from grabbing a copy of the
> >> image as it is being downloaded
> >> * Allow connection to servers that do not support plain HTTP anymore
> >> (this is becoming more and more common on the Internet these days)
> >> - Possibly benefit from additional features implemented in lwIP
> >> - Less code to maintain in U-Boot
> >>
> >> Prior to applying this series, the lwIP stack needs to be added as a
> >> Git subtree with the following command:
> >>
> >> $ git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE
> >>
> >> The first patch renames some enums in order to avoid a conflict when a
> >> later patch enables the lwIP library.
> >>
> >> The second patch introduces a new Kconfig symbol: NET_LWIP, which selects
> >> the lwIP implementation instead of the current one (NET). Contrary to the
> >> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
> >> simultaneously. The rationale is we want to start from a clean state and
> >> not pull potentially duplicated functionality from both stacks. Note
> >> however that a few files are still built in net/, they are the ones
> >> related to ethernet device management and the ethernet bootflow.
> >>
> >> The third patch splits the net.h header into net-legacy.h, net-common.h,
> >> net-lwip.h, leaving net.h as a simple wrapper.
> >>
> >> The fourth patch introduces the Makefile to build lwIP when NET_LWIP is
> >> enabled.
> >>
> >> The subsequent patches implement various network-oriented commands and
> >> features: dhcp, dns, ping, tftpboot, wget.
> >>
> >> A number of features are currently incompatible with NET_LWIP: SANDBOX,
> >> DFU_TFTP, FASTBOOT, SPL_NET. All make assumptions on how the network
> >> stack is implemented and/or pull sybols that are not trivially exported
> >> from lwIP. Some interface rework may be needed.
> >>
> >> Due to the above and in order to provide some level of testing, a new QEMU
> >> configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
> >> as qemu_arm64_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
> >> Tests are added to test/py/tests/test_net.py for that configuration.
> >>
> >
> > Hi Jermone,
> >
> > I've given this a spin on an imx8mm-venice-gw73xx-0x via
> > imx8mm_venice_defconfig and I can't get DHCP to work (didn't work in
> > v3 either):
> >
> > $ diff defconfig configs/imx8mm_venice_defconfig
> > 68,69c68,71
> > < CONFIG_CMD_DNS_LWIP=y
> > < CONFIG_CMD_WGET_LWIP=y
> > ---
> >> CONFIG_CMD_DHCP6=y
> >> CONFIG_CMD_TFTPPUT=y
> >> CONFIG_SYS_DISABLE_AUTOLOAD=y
> >> CONFIG_CMD_WGET=y
> > 88,90c90,94
> > < CONFIG_NET_LWIP=y
> > < CONFIG_LWIP_DEBUG=y
> > < CONFIG_LWIP_ASSERT=y
> > ---
> >> CONFIG_NET_RANDOM_ETHADDR=y
> >> CONFIG_IP_DEFRAG=y
> >> CONFIG_TFTP_BLOCKSIZE=4096
> >> CONFIG_PROT_TCP_SACK=y
> >> CONFIG_IPV6=y
> >
> > Target:
> > u-boot=> net list
> > eth0 : ethernet@30be0000 00:d0:12:b5:f8:41 active
> > u-boot=> dhcp || echo fail
> > eth0: ethernet@30be0000 00:d0:12:b5:f8:41 active
> > netif_set_ipaddr: netif address being changed
> > netif: added interface 0 addr 192.168.1.1 netmask 0.0.0.0 gw 0.0.0.0
> > etharp_request: sending ARP request.
> > etharp_raw: sending raw ARP packet.
> > ethernet_output: sending packet 000000007df00bf0
> > dhcp_start(netif=000000007df2af40) 0dhcp_start(): mallocing new DHCP client
> > dhcp_start(): allocated dhcp
> > dhcp_start(): starting DHCP configuration
> > dhcp_discover()
> > transaction id xid(42021)
> > dhcp_discover: making request
> > dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
> > ip4_output_if: 0IP header:
> > +-------------------------------+
> > | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
> > +-------------------------------+
> > | 0 |000| 0 | (id, flags, offset)
> > +-------------------------------+
> > | 255 | 17 | 0xba9d | (ttl, proto, chksum)
> > +-------------------------------+
> > | 0 | 0 | 0 | 0 | (src)
> > +-------------------------------+
> > | 255 | 255 | 255 | 255 | (dest)
> > +-------------------------------+
> > ip4_output_if: call netif->output()
> > ethernet_output: sending packet 000000007df2c010
> > dhcp_discover: deleting()
> > dhcp_discover: SELECTING
> > dhcp_discover(): set request timeout 2000 msecs
> > ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:28:28:5d:bb:16:9f, type:8899
> > ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:00:27:0e:0d:74:ba, type:806
> > etharp_update_arp_entry: 172.24.20.24 - 00:27:0e:0d:74:ba
> > etharp_find_entry: found empty entry 0
> > etharp_find_entry: no empty entry found and not allowed to recycle
> > etharp_input: incoming ARP request
> > etharp_input: ARP request was not for us.
> > ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:98:90:96:ac:d7:63, type:806
> > etharp_update_arp_entry: 172.24.20.3 - 98:90:96:ac:d7:63
> > etharp_find_entry: found empty entry 0
> > etharp_find_entry: no empty entry found and not allowed to recycle
> > etharp_input: incoming ARP request
> > etharp_input: ARP request was not for us.
> > ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:84:2b:2b:4e:5a:9a, type:806
> > etharp_update_arp_entry: 172.24.0.1 - 84:2b:2b:4e:5a:9a
> > etharp_find_entry: found empty entry 0
> > etharp_find_entry: no empty entry found and not allowed to recycle
> > etharp_input: incoming ARP request
> > etharp_input: ARP request was not for us.
> > ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:cc:96:e5:1e:a0:7b, type:800
> > ip_input: iphdr->dest 0xffff1fac netif->ip_addr 0x101a8c0 (0x0, 0x0, 0xffff1fac)
> > ip4_input: UDP packet to DHCP client port 138
> > ip4_input: packet not for us.
>
> That's weird. I think what could happen is the interface already has
> a static IP assigned when it is registered to the lwIP stack and thus
> DHCP never receives the packed because it is dropped before.
> I have reworked the initialization code in v5, lwIP will get to know
> only one interface at a time and I make sure that interface is registered
> without an IP address when doing DHCP. Hopefully that should fix the issue.
>
> Thanks for testing!
>
I tried your to-upstream/v5-wip branch
(042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
you have something else to try/test?
Best Regards,
Tim
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-21 16:08 ` Tim Harvey
@ 2024-06-21 17:56 ` Jerome Forissier
2024-06-21 18:42 ` Fabio Estevam
1 sibling, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-21 17:56 UTC (permalink / raw)
To: Tim Harvey; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
On 6/21/24 18:08, Tim Harvey wrote:
> On Fri, Jun 21, 2024 at 5:59 AM Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>>
>>
>> On 6/20/24 19:10, Tim Harvey wrote:
>>> On Mon, Jun 17, 2024 at 8:33 AM Jerome Forissier
>>> <jerome.forissier@linaro.org> wrote:
>>>>
>>>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>>>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>>>> stack [2] [3] as an alternative to the current implementation in net/,
>>>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>>>> reasons for doing so are:
>>>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>>>> has some additional lwIP and Mbed TLS patches to do so. With that it
>>>> becomes possible to fetch and launch a distro installer such as Debian
>>>> etc. using a secure, authenticated connection directly from the U-Boot
>>>> shell. Several use cases:
>>>> * Authentication: prevent MITM attack (third party replacing the
>>>> binary with a different one)
>>>> * Confidentiality: prevent third parties from grabbing a copy of the
>>>> image as it is being downloaded
>>>> * Allow connection to servers that do not support plain HTTP anymore
>>>> (this is becoming more and more common on the Internet these days)
>>>> - Possibly benefit from additional features implemented in lwIP
>>>> - Less code to maintain in U-Boot
>>>>
>>>> Prior to applying this series, the lwIP stack needs to be added as a
>>>> Git subtree with the following command:
>>>>
>>>> $ git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE
>>>>
>>>> The first patch renames some enums in order to avoid a conflict when a
>>>> later patch enables the lwIP library.
>>>>
>>>> The second patch introduces a new Kconfig symbol: NET_LWIP, which selects
>>>> the lwIP implementation instead of the current one (NET). Contrary to the
>>>> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
>>>> simultaneously. The rationale is we want to start from a clean state and
>>>> not pull potentially duplicated functionality from both stacks. Note
>>>> however that a few files are still built in net/, they are the ones
>>>> related to ethernet device management and the ethernet bootflow.
>>>>
>>>> The third patch splits the net.h header into net-legacy.h, net-common.h,
>>>> net-lwip.h, leaving net.h as a simple wrapper.
>>>>
>>>> The fourth patch introduces the Makefile to build lwIP when NET_LWIP is
>>>> enabled.
>>>>
>>>> The subsequent patches implement various network-oriented commands and
>>>> features: dhcp, dns, ping, tftpboot, wget.
>>>>
>>>> A number of features are currently incompatible with NET_LWIP: SANDBOX,
>>>> DFU_TFTP, FASTBOOT, SPL_NET. All make assumptions on how the network
>>>> stack is implemented and/or pull sybols that are not trivially exported
>>>> from lwIP. Some interface rework may be needed.
>>>>
>>>> Due to the above and in order to provide some level of testing, a new QEMU
>>>> configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
>>>> as qemu_arm64_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
>>>> Tests are added to test/py/tests/test_net.py for that configuration.
>>>>
>>>
>>> Hi Jermone,
>>>
>>> I've given this a spin on an imx8mm-venice-gw73xx-0x via
>>> imx8mm_venice_defconfig and I can't get DHCP to work (didn't work in
>>> v3 either):
>>>
>>> $ diff defconfig configs/imx8mm_venice_defconfig
>>> 68,69c68,71
>>> < CONFIG_CMD_DNS_LWIP=y
>>> < CONFIG_CMD_WGET_LWIP=y
>>> ---
>>>> CONFIG_CMD_DHCP6=y
>>>> CONFIG_CMD_TFTPPUT=y
>>>> CONFIG_SYS_DISABLE_AUTOLOAD=y
>>>> CONFIG_CMD_WGET=y
>>> 88,90c90,94
>>> < CONFIG_NET_LWIP=y
>>> < CONFIG_LWIP_DEBUG=y
>>> < CONFIG_LWIP_ASSERT=y
>>> ---
>>>> CONFIG_NET_RANDOM_ETHADDR=y
>>>> CONFIG_IP_DEFRAG=y
>>>> CONFIG_TFTP_BLOCKSIZE=4096
>>>> CONFIG_PROT_TCP_SACK=y
>>>> CONFIG_IPV6=y
>>>
>>> Target:
>>> u-boot=> net list
>>> eth0 : ethernet@30be0000 00:d0:12:b5:f8:41 active
>>> u-boot=> dhcp || echo fail
>>> eth0: ethernet@30be0000 00:d0:12:b5:f8:41 active
>>> netif_set_ipaddr: netif address being changed
>>> netif: added interface 0 addr 192.168.1.1 netmask 0.0.0.0 gw 0.0.0.0
>>> etharp_request: sending ARP request.
>>> etharp_raw: sending raw ARP packet.
>>> ethernet_output: sending packet 000000007df00bf0
>>> dhcp_start(netif=000000007df2af40) 0dhcp_start(): mallocing new DHCP client
>>> dhcp_start(): allocated dhcp
>>> dhcp_start(): starting DHCP configuration
>>> dhcp_discover()
>>> transaction id xid(42021)
>>> dhcp_discover: making request
>>> dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
>>> ip4_output_if: 0IP header:
>>> +-------------------------------+
>>> | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
>>> +-------------------------------+
>>> | 0 |000| 0 | (id, flags, offset)
>>> +-------------------------------+
>>> | 255 | 17 | 0xba9d | (ttl, proto, chksum)
>>> +-------------------------------+
>>> | 0 | 0 | 0 | 0 | (src)
>>> +-------------------------------+
>>> | 255 | 255 | 255 | 255 | (dest)
>>> +-------------------------------+
>>> ip4_output_if: call netif->output()
>>> ethernet_output: sending packet 000000007df2c010
>>> dhcp_discover: deleting()
>>> dhcp_discover: SELECTING
>>> dhcp_discover(): set request timeout 2000 msecs
>>> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:28:28:5d:bb:16:9f, type:8899
>>> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:00:27:0e:0d:74:ba, type:806
>>> etharp_update_arp_entry: 172.24.20.24 - 00:27:0e:0d:74:ba
>>> etharp_find_entry: found empty entry 0
>>> etharp_find_entry: no empty entry found and not allowed to recycle
>>> etharp_input: incoming ARP request
>>> etharp_input: ARP request was not for us.
>>> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:98:90:96:ac:d7:63, type:806
>>> etharp_update_arp_entry: 172.24.20.3 - 98:90:96:ac:d7:63
>>> etharp_find_entry: found empty entry 0
>>> etharp_find_entry: no empty entry found and not allowed to recycle
>>> etharp_input: incoming ARP request
>>> etharp_input: ARP request was not for us.
>>> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:84:2b:2b:4e:5a:9a, type:806
>>> etharp_update_arp_entry: 172.24.0.1 - 84:2b:2b:4e:5a:9a
>>> etharp_find_entry: found empty entry 0
>>> etharp_find_entry: no empty entry found and not allowed to recycle
>>> etharp_input: incoming ARP request
>>> etharp_input: ARP request was not for us.
>>> ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:cc:96:e5:1e:a0:7b, type:800
>>> ip_input: iphdr->dest 0xffff1fac netif->ip_addr 0x101a8c0 (0x0, 0x0, 0xffff1fac)
>>> ip4_input: UDP packet to DHCP client port 138
>>> ip4_input: packet not for us.
>>
>> That's weird. I think what could happen is the interface already has
>> a static IP assigned when it is registered to the lwIP stack and thus
>> DHCP never receives the packed because it is dropped before.
>> I have reworked the initialization code in v5, lwIP will get to know
>> only one interface at a time and I make sure that interface is registered
>> without an IP address when doing DHCP. Hopefully that should fix the issue.
>>
>> Thanks for testing!
>>
>
> I tried your to-upstream/v5-wip branch
> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> you have something else to try/test?
Not at the moment, unfortunately. I'll take a closer look at what this
message "packet not for us" means on Monday.
Thanks,
--
Jerome
>
> Best Regards,
>
> Tim
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-21 16:08 ` Tim Harvey
2024-06-21 17:56 ` Jerome Forissier
@ 2024-06-21 18:42 ` Fabio Estevam
2024-06-22 8:08 ` Maxim Uvarov
1 sibling, 1 reply; 53+ messages in thread
From: Fabio Estevam @ 2024-06-21 18:42 UTC (permalink / raw)
To: Tim Harvey
Cc: Jerome Forissier, u-boot, Ilias Apalodimas, Javier Tia,
Maxim Uvarov
Hi Tim and Jerome,
On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
> I tried your to-upstream/v5-wip branch
> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> you have something else to try/test?
Yes, when I tested older versions from Maxim I could never get lwIP to
work with i.MX.
Jerome,
Please try to run the lwIP series on any i.MX board, if possible.
Thanks
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-21 18:42 ` Fabio Estevam
@ 2024-06-22 8:08 ` Maxim Uvarov
2024-06-24 22:28 ` Tim Harvey
0 siblings, 1 reply; 53+ messages in thread
From: Maxim Uvarov @ 2024-06-22 8:08 UTC (permalink / raw)
To: Fabio Estevam
Cc: Tim Harvey, Jerome Forissier, u-boot, Ilias Apalodimas,
Javier Tia
пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
>
> Hi Tim and Jerome,
>
> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
>
> > I tried your to-upstream/v5-wip branch
> > (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> > you have something else to try/test?
>
> Yes, when I tested older versions from Maxim I could never get lwIP to
> work with i.MX.
>
> Jerome,
>
> Please try to run the lwIP series on any i.MX board, if possible.
>
> Thanks
Packet not for us means that incoming packet DST MAC does not match to
the MAC address inside lwip. I.e. to MAC address set into lwip when
lwip_init was done. Original U-Boot network stack does not compare
MACs but lwip does. There is something specific on this board, in
general lwip with debug should print out
MAC used during initialization. This MAC should match to the MAC from
the incoming packet.
--
Best regards,
Maxim Uvarov
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-22 8:08 ` Maxim Uvarov
@ 2024-06-24 22:28 ` Tim Harvey
2024-06-25 8:02 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Tim Harvey @ 2024-06-24 22:28 UTC (permalink / raw)
To: Maxim Uvarov, Jerome Forissier
Cc: Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia
On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
>
> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
> >
> > Hi Tim and Jerome,
> >
> > On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
> >
> > > I tried your to-upstream/v5-wip branch
> > > (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> > > you have something else to try/test?
> >
> > Yes, when I tested older versions from Maxim I could never get lwIP to
> > work with i.MX.
> >
> > Jerome,
> >
> > Please try to run the lwIP series on any i.MX board, if possible.
> >
> > Thanks
>
> Packet not for us means that incoming packet DST MAC does not match to
> the MAC address inside lwip. I.e. to MAC address set into lwip when
> lwip_init was done. Original U-Boot network stack does not compare
> MACs but lwip does. There is something specific on this board, in
> general lwip with debug should print out
> MAC used during initialization. This MAC should match to the MAC from
> the incoming packet.
>
It seems 'packet not for us' can mean a lot of things.
I added a bit of debugging around 'DHCP packet accepted' and found I'm
not receiving any packets from my DHCP server. So I connected directly
to another board (isolated network) where I ran my own server and
tcpdump and I don't see packets coming from lwip:
without lwip my server shows:
# tcpdump -i eth1
tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
length 262144 bytes
tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
length 262144 bytes
22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
proto UDP (17), length 328)
22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
proto UDP (17), length 328)
22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
proto UDP (17), length 328)
22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
proto UDP (17), length 328)
# tcpdump -i eth1
tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
length 262144 bytes
22:22:41.602178 [|llc]
22:22:41.709978 [|llc]
22:22:41.867947 [|llc]
22:22:42.105202 [|llc]
22:22:42.502091 [|llc]
22:22:43.219079 [|llc]
22:22:44.497979 [|llc]
22:22:45.776884 [|llc]
22:22:47.054773 [|llc]
22:22:48.333667 [|llc]
22:22:49.611559 [|llc]
22:22:50.890469 [|llc]
What actual hardware has this been tested with? I think Tom mentioned
he tested with an rpi of some sort.
I don't know what the meaning of the llc msg is above but you can see
there is no DHCP request.
Best Regards,
Tim
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-24 22:28 ` Tim Harvey
@ 2024-06-25 8:02 ` Jerome Forissier
2024-06-26 16:00 ` Tim Harvey
0 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-25 8:02 UTC (permalink / raw)
To: Tim Harvey, Maxim Uvarov
Cc: Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia
On 6/25/24 00:28, Tim Harvey wrote:
> On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
>>
>> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
>>>
>>> Hi Tim and Jerome,
>>>
>>> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
>>>
>>>> I tried your to-upstream/v5-wip branch
>>>> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
>>>> you have something else to try/test?
>>>
>>> Yes, when I tested older versions from Maxim I could never get lwIP to
>>> work with i.MX.
>>>
>>> Jerome,
>>>
>>> Please try to run the lwIP series on any i.MX board, if possible.
>>>
>>> Thanks
>>
>> Packet not for us means that incoming packet DST MAC does not match to
>> the MAC address inside lwip. I.e. to MAC address set into lwip when
>> lwip_init was done. Original U-Boot network stack does not compare
>> MACs but lwip does. There is something specific on this board, in
>> general lwip with debug should print out
>> MAC used during initialization. This MAC should match to the MAC from
>> the incoming packet.
>>
>
> It seems 'packet not for us' can mean a lot of things.
Yeah :-/ in this case I believe the traces are caused by unrelated traffic
(UDP port 138 is used by NetBIOS).
> I added a bit of debugging around 'DHCP packet accepted' and found I'm
> not receiving any packets from my DHCP server. So I connected directly
> to another board (isolated network) where I ran my own server and
> tcpdump and I don't see packets coming from lwip:
Ha! That's interesting.
> without lwip my server shows:
> # tcpdump -i eth1
> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> length 262144 bytes
> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> length 262144 bytes
> 22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
> proto UDP (17), length 328)
> 22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> proto UDP (17), length 328)
> 22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
> proto UDP (17), length 328)
> 22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> proto UDP (17), length 328)
>
> # tcpdump -i eth1
> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> length 262144 bytes
> 22:22:41.602178 [|llc]
> 22:22:41.709978 [|llc]
> 22:22:41.867947 [|llc]
> 22:22:42.105202 [|llc]
> 22:22:42.502091 [|llc]
> 22:22:43.219079 [|llc]
> 22:22:44.497979 [|llc]
> 22:22:45.776884 [|llc]
> 22:22:47.054773 [|llc]
> 22:22:48.333667 [|llc]
> 22:22:49.611559 [|llc]
> 22:22:50.890469 [|llc]
>
> What actual hardware has this been tested with? I think Tom mentioned
> he tested with an rpi of some sort.
Yes, I believe he tested on RPi 3B and me too. Ilias has tested on NVIDIA
Jetson Nano.
> I don't know what the meaning of the llc msg is above but you can see
> there is no DHCP request.
Some more tracing is needed. Can you try enabling all traces in
lib/lwip/u-boot/lwipopts.h? i.e., replace all LWIP_DBG_OFF with
LWIP_DBG_ON in the #if defined(CONFIG_LWIP_DEBUG) section. And of course
enabled CONFIG_LWIP_DEBUG.
I do have a i.MX8M Plus EVK board but will not be able to use it before
tomorrow.
Thanks,
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-25 8:02 ` Jerome Forissier
@ 2024-06-26 16:00 ` Tim Harvey
2024-06-28 9:50 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Tim Harvey @ 2024-06-26 16:00 UTC (permalink / raw)
To: Jerome Forissier
Cc: Maxim Uvarov, Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia
On Tue, Jun 25, 2024 at 1:02 AM Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> On 6/25/24 00:28, Tim Harvey wrote:
> > On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
> >>
> >> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
> >>>
> >>> Hi Tim and Jerome,
> >>>
> >>> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
> >>>
> >>>> I tried your to-upstream/v5-wip branch
> >>>> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> >>>> you have something else to try/test?
> >>>
> >>> Yes, when I tested older versions from Maxim I could never get lwIP to
> >>> work with i.MX.
> >>>
> >>> Jerome,
> >>>
> >>> Please try to run the lwIP series on any i.MX board, if possible.
> >>>
> >>> Thanks
> >>
> >> Packet not for us means that incoming packet DST MAC does not match to
> >> the MAC address inside lwip. I.e. to MAC address set into lwip when
> >> lwip_init was done. Original U-Boot network stack does not compare
> >> MACs but lwip does. There is something specific on this board, in
> >> general lwip with debug should print out
> >> MAC used during initialization. This MAC should match to the MAC from
> >> the incoming packet.
> >>
> >
> > It seems 'packet not for us' can mean a lot of things.
>
> Yeah :-/ in this case I believe the traces are caused by unrelated traffic
> (UDP port 138 is used by NetBIOS).
>
>
> > I added a bit of debugging around 'DHCP packet accepted' and found I'm
> > not receiving any packets from my DHCP server. So I connected directly
> > to another board (isolated network) where I ran my own server and
> > tcpdump and I don't see packets coming from lwip:
>
> Ha! That's interesting.
>
> > without lwip my server shows:
> > # tcpdump -i eth1
> > tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> > length 262144 bytes
> > tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> > length 262144 bytes
> > 22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
> > proto UDP (17), length 328)
> > 22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> > proto UDP (17), length 328)
> > 22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
> > proto UDP (17), length 328)
> > 22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> > proto UDP (17), length 328)
> >
> > # tcpdump -i eth1
> > tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> > length 262144 bytes
> > 22:22:41.602178 [|llc]
> > 22:22:41.709978 [|llc]
> > 22:22:41.867947 [|llc]
> > 22:22:42.105202 [|llc]
> > 22:22:42.502091 [|llc]
> > 22:22:43.219079 [|llc]
> > 22:22:44.497979 [|llc]
> > 22:22:45.776884 [|llc]
> > 22:22:47.054773 [|llc]
> > 22:22:48.333667 [|llc]
> > 22:22:49.611559 [|llc]
> > 22:22:50.890469 [|llc]
> >
> > What actual hardware has this been tested with? I think Tom mentioned
> > he tested with an rpi of some sort.
>
> Yes, I believe he tested on RPi 3B and me too. Ilias has tested on NVIDIA
> Jetson Nano.
>
> > I don't know what the meaning of the llc msg is above but you can see
> > there is no DHCP request.
>
> Some more tracing is needed. Can you try enabling all traces in
> lib/lwip/u-boot/lwipopts.h? i.e., replace all LWIP_DBG_OFF with
> LWIP_DBG_ON in the #if defined(CONFIG_LWIP_DEBUG) section. And of course
> enabled CONFIG_LWIP_DEBUG.
Here's what I see with all those enabled on an imx8mm-venice-gw73xx-0x:
Net: eth0: ethernet@30be0000 [PRIME]
GSC : boot watchdog disabled
Thermal protection:enabled at 96C
Hit any key to stop autoboot: 0
u-boot=> dhcp || echo fail
netif: added interface et IP addr 0.0.0.0 netmask 0.0.0.0 gw 0.0.0.0
netif: setting default interface et
dhcp_start(netif=00000000fdf23bb0) et0
dhcp_start(): mallocing new DHCP client
dhcp_start(): allocated dhcp
dhcp_start(): starting DHCP configuration
udp_bind(ipaddr = 0.0.0.0, port = 68)
udp_bind: bound to 0.0.0.0, port 68)
udp_connect: connected to 0.0.0.0, port 67)
dhcp_discover()
pbuf_alloc(length=308)
pbuf_alloc(length=308) == 00000000fdf23d10
transaction id xid(42021)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
pbuf_add_header: old 00000000fdf23d5e new 00000000fdf23d56 (8)
udp_send: added header in given pbuf 00000000fdf23d10
udp_send: sending datagram of length 316
udp_send: UDP packet length 316
inet_chksum_pseudo(): checksumming pbuf 00000000fdf23d10 (has next
0000000000000000)
inet_chksum_pseudo(): pbuf chain lwip_chksum()=807
udp_send: UDP checksum 0xf7f8
udp_send: ip_output_if (,,,,0x11,)
pbuf_add_header: old 00000000fdf23d56 new 00000000fdf23d42 (20)
ip4_output_if: et0
IP header:
+-------------------------------+
| 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
+-------------------------------+
| 0 |000| 0 | (id, flags, offset)
+-------------------------------+
| 255 | 17 | 0xba9d | (ttl, proto, chksum)
+-------------------------------+
| 0 | 0 | 0 | 0 | (src)
+-------------------------------+
| 255 | 255 | 255 | 255 | (dest)
+-------------------------------+
ip4_output_if: call netif->output()
pbuf_add_header: old 00000000fdf23d42 new 00000000fdf23d34 (14)
ethernet_output: sending packet 00000000fdf23d10
^^^ at this point a 350 byte packet gets sent to fecmxc_send for the
NIC which looks like this via print_hex_dump_bytes():
00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
00000010: 01 50 00 00 00 00 ff 11 ba 9d 00 00 00 00 ff ff .P..............
00000020: ff ff 00 44 00 43 01 3c f8 f7 01 01 06 00 00 04 ...D.C.<........
00000030: 20 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !..............
00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 05 ......c.Sc5..9..
00000120: dc 37 03 01 03 1c ff 00 00 00 00 00 00 00 00 00 .7..............
00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
on my dhcp server 'tcpdump -i eth1 -X -vvv' shows:
tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
length 262144 bytes
15:34:25.341167 [|llc]
0x0000: 0000 0000 0000 0000 0000 343d f2fd 0000 ..........4=....
0x0010: 0000 5e01 5e01 8000 0100 0000 0000 0000 ..^.^...........
0x0020: 0000 0000 0000 ffff ffff ffff 00d0 12ba ................
0x0030: f8cc 0800 4500 0150 001e 0000 ff11 ba7f ....E..P........
0x0040: 0000 0000 ffff ffff 0044 0043 013c 6d78 .........D.C.<mx
0x0050: 0101 0600 1255 994f 0000 0000 0000 0000 .....U.O........
0x0060: 0000 0000 0000 0000 0000 0000 00d0 12ba ................
0x0070: f8cc 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0130: 0000 0000 0000 0000 0000 0000 6382 5363 ............c.Sc
0x0140: 3501 0139 0205 dc37 0301 031c ff00 0000 5..9...7........
Comparing to w/o LWIP:
u-boot=> dhcp || echo fail
BOOTP broadcast 1
fecmxc_send ethernet@30be0000 342
00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
00000010: 01 48 00 00 40 00 ff 11 7a a5 00 00 00 00 ff ff .H..@...z.......
00000020: ff ff 00 44 00 43 01 34 00 00 01 01 06 00 12 bb ...D.C.4........
00000030: 82 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .d..............
00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 02 ......c.Sc5..9..
00000120: 40 5d 02 00 16 5e 03 01 00 00 3c 0c 55 2d 42 6f @]...^....<.U-Bo
00000130: 6f 74 2e 61 72 6d 76 38 37 05 01 03 06 0c 11 ff ot.armv87.......
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150: 00 00 00 00 00 00 ......
^^^ Note the packet is 8 bytes shorter
and on the dhcp server:
tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
length 262144 bytes
15:45:12.548077 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF],
proto UDP (17), length 328)
0.0.0.0.bootpc > 255.255.255.255.bootps: [no cksum] BOOTP/DHCP,
Request from 00:d0:12:ba:f8:cc (oui Unknown), length 300, xid
0x12bb8264, Flags [none] (0x0000)
Client-Ethernet-Address 00:d0:12:ba:f8:cc (oui Unknown)
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message (53), length 1: Discover
MSZ (57), length 2: 576
ARCH (93), length 2: 22
NDI (94), length 3: 1.0.0
Vendor-Class (60), length 12: "U-Boot.armv8"
Parameter-Request (55), length 5:
Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6),
Hostname (12)
RP (17)
END (255), length 0
PAD (0), length 0, occurs 22
0x0000: 4500 0148 0000 4000 ff11 7aa5 0000 0000 E..H..@...z.....
0x0010: ffff ffff 0044 0043 0134 0000 0101 0600 .....D.C.4......
0x0020: 12bb 8264 0000 0000 0000 0000 0000 0000 ...d............
0x0030: 0000 0000 0000 0000 00d0 12ba f8cc 0000 ................
0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0100: 0000 0000 0000 0000 6382 5363 3501 0139 ........c.Sc5..9
0x0110: 0202 405d 0200 165e 0301 0000 3c0c 552d ..@]...^....<.U-
0x0120: 426f 6f74 2e61 726d 7638 3705 0103 060c Boot.armv87.....
0x0130: 11ff 0000 0000 0000 0000 0000 0000 0000 ................
0x0140: 0000 0000 0000 0000 ........
> I do have a i.MX8M Plus EVK board but will not be able to use it before
> tomorrow.
Please let me know your findings. I can test imx8mp as well but would
have to reconfigure everything.
Best Regards,
Tim
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-26 16:00 ` Tim Harvey
@ 2024-06-28 9:50 ` Jerome Forissier
2024-06-28 15:48 ` Tim Harvey
0 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-06-28 9:50 UTC (permalink / raw)
To: Tim Harvey
Cc: Maxim Uvarov, Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia
Hi Tim,
On 6/26/24 18:00, Tim Harvey wrote:
> On Tue, Jun 25, 2024 at 1:02 AM Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>> On 6/25/24 00:28, Tim Harvey wrote:
>>> On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
>>>>
>>>> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
>>>>>
>>>>> Hi Tim and Jerome,
>>>>>
>>>>> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
>>>>>
>>>>>> I tried your to-upstream/v5-wip branch
>>>>>> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
>>>>>> you have something else to try/test?
>>>>>
>>>>> Yes, when I tested older versions from Maxim I could never get lwIP to
>>>>> work with i.MX.
>>>>>
>>>>> Jerome,
>>>>>
>>>>> Please try to run the lwIP series on any i.MX board, if possible.
>>>>>
>>>>> Thanks
>>>>
>>>> Packet not for us means that incoming packet DST MAC does not match to
>>>> the MAC address inside lwip. I.e. to MAC address set into lwip when
>>>> lwip_init was done. Original U-Boot network stack does not compare
>>>> MACs but lwip does. There is something specific on this board, in
>>>> general lwip with debug should print out
>>>> MAC used during initialization. This MAC should match to the MAC from
>>>> the incoming packet.
>>>>
>>>
>>> It seems 'packet not for us' can mean a lot of things.
>>
>> Yeah :-/ in this case I believe the traces are caused by unrelated traffic
>> (UDP port 138 is used by NetBIOS).
>>
>>
>>> I added a bit of debugging around 'DHCP packet accepted' and found I'm
>>> not receiving any packets from my DHCP server. So I connected directly
>>> to another board (isolated network) where I ran my own server and
>>> tcpdump and I don't see packets coming from lwip:
>>
>> Ha! That's interesting.
>>
>>> without lwip my server shows:
>>> # tcpdump -i eth1
>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>> length 262144 bytes
>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>> length 262144 bytes
>>> 22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
>>> proto UDP (17), length 328)
>>> 22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
>>> proto UDP (17), length 328)
>>> 22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
>>> proto UDP (17), length 328)
>>> 22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
>>> proto UDP (17), length 328)
>>>
>>> # tcpdump -i eth1
>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>> length 262144 bytes
>>> 22:22:41.602178 [|llc]
>>> 22:22:41.709978 [|llc]
>>> 22:22:41.867947 [|llc]
>>> 22:22:42.105202 [|llc]
>>> 22:22:42.502091 [|llc]
>>> 22:22:43.219079 [|llc]
>>> 22:22:44.497979 [|llc]
>>> 22:22:45.776884 [|llc]
>>> 22:22:47.054773 [|llc]
>>> 22:22:48.333667 [|llc]
>>> 22:22:49.611559 [|llc]
>>> 22:22:50.890469 [|llc]
>>>
>>> What actual hardware has this been tested with? I think Tom mentioned
>>> he tested with an rpi of some sort.
>>
>> Yes, I believe he tested on RPi 3B and me too. Ilias has tested on NVIDIA
>> Jetson Nano.
>>
>>> I don't know what the meaning of the llc msg is above but you can see
>>> there is no DHCP request.
>>
>> Some more tracing is needed. Can you try enabling all traces in
>> lib/lwip/u-boot/lwipopts.h? i.e., replace all LWIP_DBG_OFF with
>> LWIP_DBG_ON in the #if defined(CONFIG_LWIP_DEBUG) section. And of course
>> enabled CONFIG_LWIP_DEBUG.
>
> Here's what I see with all those enabled on an imx8mm-venice-gw73xx-0x:
> Net: eth0: ethernet@30be0000 [PRIME]
> GSC : boot watchdog disabled
> Thermal protection:enabled at 96C
> Hit any key to stop autoboot: 0
> u-boot=> dhcp || echo fail
> netif: added interface et IP addr 0.0.0.0 netmask 0.0.0.0 gw 0.0.0.0
> netif: setting default interface et
> dhcp_start(netif=00000000fdf23bb0) et0
> dhcp_start(): mallocing new DHCP client
> dhcp_start(): allocated dhcp
> dhcp_start(): starting DHCP configuration
> udp_bind(ipaddr = 0.0.0.0, port = 68)
> udp_bind: bound to 0.0.0.0, port 68)
> udp_connect: connected to 0.0.0.0, port 67)
> dhcp_discover()
> pbuf_alloc(length=308)
> pbuf_alloc(length=308) == 00000000fdf23d10
> transaction id xid(42021)
> dhcp_discover: making request
> dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
> pbuf_add_header: old 00000000fdf23d5e new 00000000fdf23d56 (8)
> udp_send: added header in given pbuf 00000000fdf23d10
> udp_send: sending datagram of length 316
> udp_send: UDP packet length 316
> inet_chksum_pseudo(): checksumming pbuf 00000000fdf23d10 (has next
> 0000000000000000)
> inet_chksum_pseudo(): pbuf chain lwip_chksum()=807
> udp_send: UDP checksum 0xf7f8
> udp_send: ip_output_if (,,,,0x11,)
> pbuf_add_header: old 00000000fdf23d56 new 00000000fdf23d42 (20)
> ip4_output_if: et0
> IP header:
> +-------------------------------+
> | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
> +-------------------------------+
> | 0 |000| 0 | (id, flags, offset)
> +-------------------------------+
> | 255 | 17 | 0xba9d | (ttl, proto, chksum)
> +-------------------------------+
> | 0 | 0 | 0 | 0 | (src)
> +-------------------------------+
> | 255 | 255 | 255 | 255 | (dest)
> +-------------------------------+
> ip4_output_if: call netif->output()
> pbuf_add_header: old 00000000fdf23d42 new 00000000fdf23d34 (14)
> ethernet_output: sending packet 00000000fdf23d10
> ^^^ at this point a 350 byte packet gets sent to fecmxc_send for the
> NIC which looks like this via print_hex_dump_bytes():
> 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
> 00000010: 01 50 00 00 00 00 ff 11 ba 9d 00 00 00 00 ff ff .P..............
> 00000020: ff ff 00 44 00 43 01 3c f8 f7 01 01 06 00 00 04 ...D.C.<........
> 00000030: 20 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !..............
> 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
> 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 05 ......c.Sc5..9..
> 00000120: dc 37 03 01 03 1c ff 00 00 00 00 00 00 00 00 00 .7..............
> 00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
Up to this point everything *seems* OK
> on my dhcp server 'tcpdump -i eth1 -X -vvv' shows:
> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> length 262144 bytes
> 15:34:25.341167 [|llc]
> 0x0000: 0000 0000 0000 0000 0000 343d f2fd 0000 ..........4=....
> 0x0010: 0000 5e01 5e01 8000 0100 0000 0000 0000 ..^.^...........
> 0x0020: 0000 0000 0000 ffff ffff ffff 00d0 12ba ................
> 0x0030: f8cc 0800 4500 0150 001e 0000 ff11 ba7f ....E..P........
> 0x0040: 0000 0000 ffff ffff 0044 0043 013c 6d78 .........D.C.<mx
> 0x0050: 0101 0600 1255 994f 0000 0000 0000 0000 .....U.O........
> 0x0060: 0000 0000 0000 0000 0000 0000 00d0 12ba ................
> 0x0070: f8cc 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0130: 0000 0000 0000 0000 0000 0000 6382 5363 ............c.Sc
> 0x0140: 3501 0139 0205 dc37 0301 031c ff00 0000 5..9...7........
But here it shows the DHCP packet is not received.
> Comparing to w/o LWIP:
> u-boot=> dhcp || echo fail
> BOOTP broadcast 1
> fecmxc_send ethernet@30be0000 342
> 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
> 00000010: 01 48 00 00 40 00 ff 11 7a a5 00 00 00 00 ff ff .H..@...z.......
> 00000020: ff ff 00 44 00 43 01 34 00 00 01 01 06 00 12 bb ...D.C.4........
> 00000030: 82 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .d..............
> 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
> 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 02 ......c.Sc5..9..
> 00000120: 40 5d 02 00 16 5e 03 01 00 00 3c 0c 55 2d 42 6f @]...^....<.U-Bo
> 00000130: 6f 74 2e 61 72 6d 76 38 37 05 01 03 06 0c 11 ff ot.armv87.......
> 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> 00000150: 00 00 00 00 00 00 ......
> ^^^ Note the packet is 8 bytes shorter
Yes but that's just padding IIUC.
> and on the dhcp server:
> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> length 262144 bytes
> 15:45:12.548077 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF],
> proto UDP (17), length 328)
> 0.0.0.0.bootpc > 255.255.255.255.bootps: [no cksum] BOOTP/DHCP,
> Request from 00:d0:12:ba:f8:cc (oui Unknown), length 300, xid
> 0x12bb8264, Flags [none] (0x0000)
> Client-Ethernet-Address 00:d0:12:ba:f8:cc (oui Unknown)
> Vendor-rfc1048 Extensions
> Magic Cookie 0x63825363
> DHCP-Message (53), length 1: Discover
> MSZ (57), length 2: 576
> ARCH (93), length 2: 22
> NDI (94), length 3: 1.0.0
> Vendor-Class (60), length 12: "U-Boot.armv8"
> Parameter-Request (55), length 5:
> Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6),
> Hostname (12)
> RP (17)
> END (255), length 0
> PAD (0), length 0, occurs 22
> 0x0000: 4500 0148 0000 4000 ff11 7aa5 0000 0000 E..H..@...z.....
> 0x0010: ffff ffff 0044 0043 0134 0000 0101 0600 .....D.C.4......
> 0x0020: 12bb 8264 0000 0000 0000 0000 0000 0000 ...d............
> 0x0030: 0000 0000 0000 0000 00d0 12ba f8cc 0000 ................
> 0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0100: 0000 0000 0000 0000 6382 5363 3501 0139 ........c.Sc5..9
> 0x0110: 0202 405d 0200 165e 0301 0000 3c0c 552d ..@]...^....<.U-
> 0x0120: 426f 6f74 2e61 726d 7638 3705 0103 060c Boot.armv87.....
> 0x0130: 11ff 0000 0000 0000 0000 0000 0000 0000 ................
> 0x0140: 0000 0000 0000 0000 ........
All good there, as expected.
>> I do have a i.MX8M Plus EVK board but will not be able to use it before
>> tomorrow.
>
> Please let me know your findings. I can test imx8mp as well but would
> have to reconfigure everything.
So I did some tests on my imx8mp and I got DHCP to work on the second
ethernet port (ENET2) but *not* on the first one (ENET1). They appear to
be using different drivers (drivers/net/fec_mxc.c for ENET1 and
drivers/net/dwc_eth_qos.c for ENET2). No matter what I do, there is no
packet going out of ENET1.
With a network cable plugged into ENET2 (ethernet@30bf0000):
...
Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
Hit any key to stop autoboot: 0
u-boot=>
u-boot=> dhcp
ethernet@30bf0000 Waiting for PHY auto negotiation to complete....... done
DHCP client bound to address 192.168.0.39 (2066 ms)
u-boot=>
Now moving the cable to ENET1 (ethernet@30be0000) and resetting the board:
...
Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
Hit any key to stop autoboot: 0
u-boot=>
u-boot=> setenv ethact ethernet@30be0000
u-boot=> dhcp
u-boot=> echo $?
1
I enabled the debug traces in fecmxc_send() but I see nothing wrong,
the function is called with a packet and it returns success yet nothing
is sent out on the wire. Any idea what could be wrong?
My plan is to add more traces to the driver and compare NET vs. NET_LWIP.
Regards,
--
Jerome
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-28 9:50 ` Jerome Forissier
@ 2024-06-28 15:48 ` Tim Harvey
2024-07-01 9:58 ` Jerome Forissier
0 siblings, 1 reply; 53+ messages in thread
From: Tim Harvey @ 2024-06-28 15:48 UTC (permalink / raw)
To: Jerome Forissier
Cc: Maxim Uvarov, Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia,
Joe Hershberger, Ramon Fried
On Fri, Jun 28, 2024 at 2:50 AM Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> Hi Tim,
>
> On 6/26/24 18:00, Tim Harvey wrote:
> > On Tue, Jun 25, 2024 at 1:02 AM Jerome Forissier
> > <jerome.forissier@linaro.org> wrote:
> >>
> >> On 6/25/24 00:28, Tim Harvey wrote:
> >>> On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
> >>>>
> >>>> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
> >>>>>
> >>>>> Hi Tim and Jerome,
> >>>>>
> >>>>> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
> >>>>>
> >>>>>> I tried your to-upstream/v5-wip branch
> >>>>>> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> >>>>>> you have something else to try/test?
> >>>>>
> >>>>> Yes, when I tested older versions from Maxim I could never get lwIP to
> >>>>> work with i.MX.
> >>>>>
> >>>>> Jerome,
> >>>>>
> >>>>> Please try to run the lwIP series on any i.MX board, if possible.
> >>>>>
> >>>>> Thanks
> >>>>
> >>>> Packet not for us means that incoming packet DST MAC does not match to
> >>>> the MAC address inside lwip. I.e. to MAC address set into lwip when
> >>>> lwip_init was done. Original U-Boot network stack does not compare
> >>>> MACs but lwip does. There is something specific on this board, in
> >>>> general lwip with debug should print out
> >>>> MAC used during initialization. This MAC should match to the MAC from
> >>>> the incoming packet.
> >>>>
> >>>
> >>> It seems 'packet not for us' can mean a lot of things.
> >>
> >> Yeah :-/ in this case I believe the traces are caused by unrelated traffic
> >> (UDP port 138 is used by NetBIOS).
> >>
> >>
> >>> I added a bit of debugging around 'DHCP packet accepted' and found I'm
> >>> not receiving any packets from my DHCP server. So I connected directly
> >>> to another board (isolated network) where I ran my own server and
> >>> tcpdump and I don't see packets coming from lwip:
> >>
> >> Ha! That's interesting.
> >>
> >>> without lwip my server shows:
> >>> # tcpdump -i eth1
> >>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>> length 262144 bytes
> >>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>> length 262144 bytes
> >>> 22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
> >>> proto UDP (17), length 328)
> >>> 22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> >>> proto UDP (17), length 328)
> >>> 22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
> >>> proto UDP (17), length 328)
> >>> 22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> >>> proto UDP (17), length 328)
> >>>
> >>> # tcpdump -i eth1
> >>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>> length 262144 bytes
> >>> 22:22:41.602178 [|llc]
> >>> 22:22:41.709978 [|llc]
> >>> 22:22:41.867947 [|llc]
> >>> 22:22:42.105202 [|llc]
> >>> 22:22:42.502091 [|llc]
> >>> 22:22:43.219079 [|llc]
> >>> 22:22:44.497979 [|llc]
> >>> 22:22:45.776884 [|llc]
> >>> 22:22:47.054773 [|llc]
> >>> 22:22:48.333667 [|llc]
> >>> 22:22:49.611559 [|llc]
> >>> 22:22:50.890469 [|llc]
> >>>
> >>> What actual hardware has this been tested with? I think Tom mentioned
> >>> he tested with an rpi of some sort.
> >>
> >> Yes, I believe he tested on RPi 3B and me too. Ilias has tested on NVIDIA
> >> Jetson Nano.
> >>
> >>> I don't know what the meaning of the llc msg is above but you can see
> >>> there is no DHCP request.
> >>
> >> Some more tracing is needed. Can you try enabling all traces in
> >> lib/lwip/u-boot/lwipopts.h? i.e., replace all LWIP_DBG_OFF with
> >> LWIP_DBG_ON in the #if defined(CONFIG_LWIP_DEBUG) section. And of course
> >> enabled CONFIG_LWIP_DEBUG.
> >
> > Here's what I see with all those enabled on an imx8mm-venice-gw73xx-0x:
> > Net: eth0: ethernet@30be0000 [PRIME]
> > GSC : boot watchdog disabled
> > Thermal protection:enabled at 96C
> > Hit any key to stop autoboot: 0
> > u-boot=> dhcp || echo fail
> > netif: added interface et IP addr 0.0.0.0 netmask 0.0.0.0 gw 0.0.0.0
> > netif: setting default interface et
> > dhcp_start(netif=00000000fdf23bb0) et0
> > dhcp_start(): mallocing new DHCP client
> > dhcp_start(): allocated dhcp
> > dhcp_start(): starting DHCP configuration
> > udp_bind(ipaddr = 0.0.0.0, port = 68)
> > udp_bind: bound to 0.0.0.0, port 68)
> > udp_connect: connected to 0.0.0.0, port 67)
> > dhcp_discover()
> > pbuf_alloc(length=308)
> > pbuf_alloc(length=308) == 00000000fdf23d10
> > transaction id xid(42021)
> > dhcp_discover: making request
> > dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
> > pbuf_add_header: old 00000000fdf23d5e new 00000000fdf23d56 (8)
> > udp_send: added header in given pbuf 00000000fdf23d10
> > udp_send: sending datagram of length 316
> > udp_send: UDP packet length 316
> > inet_chksum_pseudo(): checksumming pbuf 00000000fdf23d10 (has next
> > 0000000000000000)
> > inet_chksum_pseudo(): pbuf chain lwip_chksum()=807
> > udp_send: UDP checksum 0xf7f8
> > udp_send: ip_output_if (,,,,0x11,)
> > pbuf_add_header: old 00000000fdf23d56 new 00000000fdf23d42 (20)
> > ip4_output_if: et0
> > IP header:
> > +-------------------------------+
> > | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
> > +-------------------------------+
> > | 0 |000| 0 | (id, flags, offset)
> > +-------------------------------+
> > | 255 | 17 | 0xba9d | (ttl, proto, chksum)
> > +-------------------------------+
> > | 0 | 0 | 0 | 0 | (src)
> > +-------------------------------+
> > | 255 | 255 | 255 | 255 | (dest)
> > +-------------------------------+
> > ip4_output_if: call netif->output()
> > pbuf_add_header: old 00000000fdf23d42 new 00000000fdf23d34 (14)
> > ethernet_output: sending packet 00000000fdf23d10
> > ^^^ at this point a 350 byte packet gets sent to fecmxc_send for the
> > NIC which looks like this via print_hex_dump_bytes():
> > 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
> > 00000010: 01 50 00 00 00 00 ff 11 ba 9d 00 00 00 00 ff ff .P..............
> > 00000020: ff ff 00 44 00 43 01 3c f8 f7 01 01 06 00 00 04 ...D.C.<........
> > 00000030: 20 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !..............
> > 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
> > 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 05 ......c.Sc5..9..
> > 00000120: dc 37 03 01 03 1c ff 00 00 00 00 00 00 00 00 00 .7..............
> > 00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
>
> Up to this point everything *seems* OK
>
> > on my dhcp server 'tcpdump -i eth1 -X -vvv' shows:
> > tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> > length 262144 bytes
> > 15:34:25.341167 [|llc]
> > 0x0000: 0000 0000 0000 0000 0000 343d f2fd 0000 ..........4=....
> > 0x0010: 0000 5e01 5e01 8000 0100 0000 0000 0000 ..^.^...........
> > 0x0020: 0000 0000 0000 ffff ffff ffff 00d0 12ba ................
> > 0x0030: f8cc 0800 4500 0150 001e 0000 ff11 ba7f ....E..P........
> > 0x0040: 0000 0000 ffff ffff 0044 0043 013c 6d78 .........D.C.<mx
> > 0x0050: 0101 0600 1255 994f 0000 0000 0000 0000 .....U.O........
> > 0x0060: 0000 0000 0000 0000 0000 0000 00d0 12ba ................
> > 0x0070: f8cc 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0130: 0000 0000 0000 0000 0000 0000 6382 5363 ............c.Sc
> > 0x0140: 3501 0139 0205 dc37 0301 031c ff00 0000 5..9...7........
>
> But here it shows the DHCP packet is not received.
>
> > Comparing to w/o LWIP:
> > u-boot=> dhcp || echo fail
> > BOOTP broadcast 1
> > fecmxc_send ethernet@30be0000 342
> > 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
> > 00000010: 01 48 00 00 40 00 ff 11 7a a5 00 00 00 00 ff ff .H..@...z.......
> > 00000020: ff ff 00 44 00 43 01 34 00 00 01 01 06 00 12 bb ...D.C.4........
> > 00000030: 82 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .d..............
> > 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
> > 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 02 ......c.Sc5..9..
> > 00000120: 40 5d 02 00 16 5e 03 01 00 00 3c 0c 55 2d 42 6f @]...^....<.U-Bo
> > 00000130: 6f 74 2e 61 72 6d 76 38 37 05 01 03 06 0c 11 ff ot.armv87.......
> > 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > 00000150: 00 00 00 00 00 00 ......
> > ^^^ Note the packet is 8 bytes shorter
>
> Yes but that's just padding IIUC.
>
> > and on the dhcp server:
> > tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> > length 262144 bytes
> > 15:45:12.548077 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF],
> > proto UDP (17), length 328)
> > 0.0.0.0.bootpc > 255.255.255.255.bootps: [no cksum] BOOTP/DHCP,
> > Request from 00:d0:12:ba:f8:cc (oui Unknown), length 300, xid
> > 0x12bb8264, Flags [none] (0x0000)
> > Client-Ethernet-Address 00:d0:12:ba:f8:cc (oui Unknown)
> > Vendor-rfc1048 Extensions
> > Magic Cookie 0x63825363
> > DHCP-Message (53), length 1: Discover
> > MSZ (57), length 2: 576
> > ARCH (93), length 2: 22
> > NDI (94), length 3: 1.0.0
> > Vendor-Class (60), length 12: "U-Boot.armv8"
> > Parameter-Request (55), length 5:
> > Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6),
> > Hostname (12)
> > RP (17)
> > END (255), length 0
> > PAD (0), length 0, occurs 22
> > 0x0000: 4500 0148 0000 4000 ff11 7aa5 0000 0000 E..H..@...z.....
> > 0x0010: ffff ffff 0044 0043 0134 0000 0101 0600 .....D.C.4......
> > 0x0020: 12bb 8264 0000 0000 0000 0000 0000 0000 ...d............
> > 0x0030: 0000 0000 0000 0000 00d0 12ba f8cc 0000 ................
> > 0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0100: 0000 0000 0000 0000 6382 5363 3501 0139 ........c.Sc5..9
> > 0x0110: 0202 405d 0200 165e 0301 0000 3c0c 552d ..@]...^....<.U-
> > 0x0120: 426f 6f74 2e61 726d 7638 3705 0103 060c Boot.armv87.....
> > 0x0130: 11ff 0000 0000 0000 0000 0000 0000 0000 ................
> > 0x0140: 0000 0000 0000 0000 ........
>
> All good there, as expected.
>
> >> I do have a i.MX8M Plus EVK board but will not be able to use it before
> >> tomorrow.
> >
> > Please let me know your findings. I can test imx8mp as well but would
> > have to reconfigure everything.
>
> So I did some tests on my imx8mp and I got DHCP to work on the second
> ethernet port (ENET2) but *not* on the first one (ENET1). They appear to
> be using different drivers (drivers/net/fec_mxc.c for ENET1 and
> drivers/net/dwc_eth_qos.c for ENET2). No matter what I do, there is no
> packet going out of ENET1.
>
> With a network cable plugged into ENET2 (ethernet@30bf0000):
>
> ...
> Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
> Hit any key to stop autoboot: 0
> u-boot=>
> u-boot=> dhcp
> ethernet@30bf0000 Waiting for PHY auto negotiation to complete....... done
> DHCP client bound to address 192.168.0.39 (2066 ms)
> u-boot=>
>
> Now moving the cable to ENET1 (ethernet@30be0000) and resetting the board:
>
> ...
> Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
> Hit any key to stop autoboot: 0
> u-boot=>
> u-boot=> setenv ethact ethernet@30be0000
> u-boot=> dhcp
> u-boot=> echo $?
> 1
>
> I enabled the debug traces in fecmxc_send() but I see nothing wrong,
> the function is called with a packet and it returns success yet nothing
> is sent out on the wire. Any idea what could be wrong?
> My plan is to add more traces to the driver and compare NET vs. NET_LWIP.
>
Jerome,
That is consistent with what I see then. The imx8mm (and all imx all
the way back to imx28) use the FEC ethernet MAC so I would assume you
see the issue on all of those SOC's. The imx8mp introduced a 2nd
different MAC, the eqos which you are showing working.
If you look at my results above a packet 'is' received by the DHCP
server but its missing something where tcpdump shows an '[|llc]' and I
don't know what that means - something wrong with the link layer?
I feel like something is wrong in the header or packet alignment.
Maybe the key is to understand what the tcpdump output of '[llc]'
means:
- lwip fec mac destination tcpdump shows '15:34:25.341167 [|llc]'
- no-lwip fec mac destination tcptdump shows '15:45:12.548077 IP (tos
0x0, ttl 255, id 0, offset 0, flags [DF], proto UDP (17), length 328)
(Adding Joe and Ramon, the network maintainers to cc)
Regards,
Tim
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-28 15:48 ` Tim Harvey
@ 2024-07-01 9:58 ` Jerome Forissier
2024-07-01 16:06 ` Tim Harvey
0 siblings, 1 reply; 53+ messages in thread
From: Jerome Forissier @ 2024-07-01 9:58 UTC (permalink / raw)
To: Tim Harvey
Cc: Maxim Uvarov, Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia,
Joe Hershberger, Ramon Fried
On 6/28/24 17:48, Tim Harvey wrote:
> On Fri, Jun 28, 2024 at 2:50 AM Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>> Hi Tim,
>>
>> On 6/26/24 18:00, Tim Harvey wrote:
>>> On Tue, Jun 25, 2024 at 1:02 AM Jerome Forissier
>>> <jerome.forissier@linaro.org> wrote:
>>>>
>>>> On 6/25/24 00:28, Tim Harvey wrote:
>>>>> On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
>>>>>>
>>>>>> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
>>>>>>>
>>>>>>> Hi Tim and Jerome,
>>>>>>>
>>>>>>> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
>>>>>>>
>>>>>>>> I tried your to-upstream/v5-wip branch
>>>>>>>> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
>>>>>>>> you have something else to try/test?
>>>>>>>
>>>>>>> Yes, when I tested older versions from Maxim I could never get lwIP to
>>>>>>> work with i.MX.
>>>>>>>
>>>>>>> Jerome,
>>>>>>>
>>>>>>> Please try to run the lwIP series on any i.MX board, if possible.
>>>>>>>
>>>>>>> Thanks
>>>>>>
>>>>>> Packet not for us means that incoming packet DST MAC does not match to
>>>>>> the MAC address inside lwip. I.e. to MAC address set into lwip when
>>>>>> lwip_init was done. Original U-Boot network stack does not compare
>>>>>> MACs but lwip does. There is something specific on this board, in
>>>>>> general lwip with debug should print out
>>>>>> MAC used during initialization. This MAC should match to the MAC from
>>>>>> the incoming packet.
>>>>>>
>>>>>
>>>>> It seems 'packet not for us' can mean a lot of things.
>>>>
>>>> Yeah :-/ in this case I believe the traces are caused by unrelated traffic
>>>> (UDP port 138 is used by NetBIOS).
>>>>
>>>>
>>>>> I added a bit of debugging around 'DHCP packet accepted' and found I'm
>>>>> not receiving any packets from my DHCP server. So I connected directly
>>>>> to another board (isolated network) where I ran my own server and
>>>>> tcpdump and I don't see packets coming from lwip:
>>>>
>>>> Ha! That's interesting.
>>>>
>>>>> without lwip my server shows:
>>>>> # tcpdump -i eth1
>>>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>>>> length 262144 bytes
>>>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>>>> length 262144 bytes
>>>>> 22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
>>>>> proto UDP (17), length 328)
>>>>> 22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
>>>>> proto UDP (17), length 328)
>>>>> 22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
>>>>> proto UDP (17), length 328)
>>>>> 22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
>>>>> proto UDP (17), length 328)
>>>>>
>>>>> # tcpdump -i eth1
>>>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>>>> length 262144 bytes
>>>>> 22:22:41.602178 [|llc]
>>>>> 22:22:41.709978 [|llc]
>>>>> 22:22:41.867947 [|llc]
>>>>> 22:22:42.105202 [|llc]
>>>>> 22:22:42.502091 [|llc]
>>>>> 22:22:43.219079 [|llc]
>>>>> 22:22:44.497979 [|llc]
>>>>> 22:22:45.776884 [|llc]
>>>>> 22:22:47.054773 [|llc]
>>>>> 22:22:48.333667 [|llc]
>>>>> 22:22:49.611559 [|llc]
>>>>> 22:22:50.890469 [|llc]
>>>>>
>>>>> What actual hardware has this been tested with? I think Tom mentioned
>>>>> he tested with an rpi of some sort.
>>>>
>>>> Yes, I believe he tested on RPi 3B and me too. Ilias has tested on NVIDIA
>>>> Jetson Nano.
>>>>
>>>>> I don't know what the meaning of the llc msg is above but you can see
>>>>> there is no DHCP request.
>>>>
>>>> Some more tracing is needed. Can you try enabling all traces in
>>>> lib/lwip/u-boot/lwipopts.h? i.e., replace all LWIP_DBG_OFF with
>>>> LWIP_DBG_ON in the #if defined(CONFIG_LWIP_DEBUG) section. And of course
>>>> enabled CONFIG_LWIP_DEBUG.
>>>
>>> Here's what I see with all those enabled on an imx8mm-venice-gw73xx-0x:
>>> Net: eth0: ethernet@30be0000 [PRIME]
>>> GSC : boot watchdog disabled
>>> Thermal protection:enabled at 96C
>>> Hit any key to stop autoboot: 0
>>> u-boot=> dhcp || echo fail
>>> netif: added interface et IP addr 0.0.0.0 netmask 0.0.0.0 gw 0.0.0.0
>>> netif: setting default interface et
>>> dhcp_start(netif=00000000fdf23bb0) et0
>>> dhcp_start(): mallocing new DHCP client
>>> dhcp_start(): allocated dhcp
>>> dhcp_start(): starting DHCP configuration
>>> udp_bind(ipaddr = 0.0.0.0, port = 68)
>>> udp_bind: bound to 0.0.0.0, port 68)
>>> udp_connect: connected to 0.0.0.0, port 67)
>>> dhcp_discover()
>>> pbuf_alloc(length=308)
>>> pbuf_alloc(length=308) == 00000000fdf23d10
>>> transaction id xid(42021)
>>> dhcp_discover: making request
>>> dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
>>> pbuf_add_header: old 00000000fdf23d5e new 00000000fdf23d56 (8)
>>> udp_send: added header in given pbuf 00000000fdf23d10
>>> udp_send: sending datagram of length 316
>>> udp_send: UDP packet length 316
>>> inet_chksum_pseudo(): checksumming pbuf 00000000fdf23d10 (has next
>>> 0000000000000000)
>>> inet_chksum_pseudo(): pbuf chain lwip_chksum()=807
>>> udp_send: UDP checksum 0xf7f8
>>> udp_send: ip_output_if (,,,,0x11,)
>>> pbuf_add_header: old 00000000fdf23d56 new 00000000fdf23d42 (20)
>>> ip4_output_if: et0
>>> IP header:
>>> +-------------------------------+
>>> | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
>>> +-------------------------------+
>>> | 0 |000| 0 | (id, flags, offset)
>>> +-------------------------------+
>>> | 255 | 17 | 0xba9d | (ttl, proto, chksum)
>>> +-------------------------------+
>>> | 0 | 0 | 0 | 0 | (src)
>>> +-------------------------------+
>>> | 255 | 255 | 255 | 255 | (dest)
>>> +-------------------------------+
>>> ip4_output_if: call netif->output()
>>> pbuf_add_header: old 00000000fdf23d42 new 00000000fdf23d34 (14)
>>> ethernet_output: sending packet 00000000fdf23d10
>>> ^^^ at this point a 350 byte packet gets sent to fecmxc_send for the
>>> NIC which looks like this via print_hex_dump_bytes():
>>> 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
>>> 00000010: 01 50 00 00 00 00 ff 11 ba 9d 00 00 00 00 ff ff .P..............
>>> 00000020: ff ff 00 44 00 43 01 3c f8 f7 01 01 06 00 00 04 ...D.C.<........
>>> 00000030: 20 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !..............
>>> 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
>>> 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 05 ......c.Sc5..9..
>>> 00000120: dc 37 03 01 03 1c ff 00 00 00 00 00 00 00 00 00 .7..............
>>> 00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
>>
>> Up to this point everything *seems* OK
>>
>>> on my dhcp server 'tcpdump -i eth1 -X -vvv' shows:
>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>> length 262144 bytes
>>> 15:34:25.341167 [|llc]
>>> 0x0000: 0000 0000 0000 0000 0000 343d f2fd 0000 ..........4=....
>>> 0x0010: 0000 5e01 5e01 8000 0100 0000 0000 0000 ..^.^...........
>>> 0x0020: 0000 0000 0000 ffff ffff ffff 00d0 12ba ................
>>> 0x0030: f8cc 0800 4500 0150 001e 0000 ff11 ba7f ....E..P........
>>> 0x0040: 0000 0000 ffff ffff 0044 0043 013c 6d78 .........D.C.<mx
>>> 0x0050: 0101 0600 1255 994f 0000 0000 0000 0000 .....U.O........
>>> 0x0060: 0000 0000 0000 0000 0000 0000 00d0 12ba ................
>>> 0x0070: f8cc 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0130: 0000 0000 0000 0000 0000 0000 6382 5363 ............c.Sc
>>> 0x0140: 3501 0139 0205 dc37 0301 031c ff00 0000 5..9...7........
>>
>> But here it shows the DHCP packet is not received.
>>
>>> Comparing to w/o LWIP:
>>> u-boot=> dhcp || echo fail
>>> BOOTP broadcast 1
>>> fecmxc_send ethernet@30be0000 342
>>> 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
>>> 00000010: 01 48 00 00 40 00 ff 11 7a a5 00 00 00 00 ff ff .H..@...z.......
>>> 00000020: ff ff 00 44 00 43 01 34 00 00 01 01 06 00 12 bb ...D.C.4........
>>> 00000030: 82 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .d..............
>>> 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
>>> 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 02 ......c.Sc5..9..
>>> 00000120: 40 5d 02 00 16 5e 03 01 00 00 3c 0c 55 2d 42 6f @]...^....<.U-Bo
>>> 00000130: 6f 74 2e 61 72 6d 76 38 37 05 01 03 06 0c 11 ff ot.armv87.......
>>> 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>>> 00000150: 00 00 00 00 00 00 ......
>>> ^^^ Note the packet is 8 bytes shorter
>>
>> Yes but that's just padding IIUC.
>>
>>> and on the dhcp server:
>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
>>> length 262144 bytes
>>> 15:45:12.548077 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF],
>>> proto UDP (17), length 328)
>>> 0.0.0.0.bootpc > 255.255.255.255.bootps: [no cksum] BOOTP/DHCP,
>>> Request from 00:d0:12:ba:f8:cc (oui Unknown), length 300, xid
>>> 0x12bb8264, Flags [none] (0x0000)
>>> Client-Ethernet-Address 00:d0:12:ba:f8:cc (oui Unknown)
>>> Vendor-rfc1048 Extensions
>>> Magic Cookie 0x63825363
>>> DHCP-Message (53), length 1: Discover
>>> MSZ (57), length 2: 576
>>> ARCH (93), length 2: 22
>>> NDI (94), length 3: 1.0.0
>>> Vendor-Class (60), length 12: "U-Boot.armv8"
>>> Parameter-Request (55), length 5:
>>> Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6),
>>> Hostname (12)
>>> RP (17)
>>> END (255), length 0
>>> PAD (0), length 0, occurs 22
>>> 0x0000: 4500 0148 0000 4000 ff11 7aa5 0000 0000 E..H..@...z.....
>>> 0x0010: ffff ffff 0044 0043 0134 0000 0101 0600 .....D.C.4......
>>> 0x0020: 12bb 8264 0000 0000 0000 0000 0000 0000 ...d............
>>> 0x0030: 0000 0000 0000 0000 00d0 12ba f8cc 0000 ................
>>> 0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0100: 0000 0000 0000 0000 6382 5363 3501 0139 ........c.Sc5..9
>>> 0x0110: 0202 405d 0200 165e 0301 0000 3c0c 552d ..@]...^....<.U-
>>> 0x0120: 426f 6f74 2e61 726d 7638 3705 0103 060c Boot.armv87.....
>>> 0x0130: 11ff 0000 0000 0000 0000 0000 0000 0000 ................
>>> 0x0140: 0000 0000 0000 0000 ........
>>
>> All good there, as expected.
>>
>>>> I do have a i.MX8M Plus EVK board but will not be able to use it before
>>>> tomorrow.
>>>
>>> Please let me know your findings. I can test imx8mp as well but would
>>> have to reconfigure everything.
>>
>> So I did some tests on my imx8mp and I got DHCP to work on the second
>> ethernet port (ENET2) but *not* on the first one (ENET1). They appear to
>> be using different drivers (drivers/net/fec_mxc.c for ENET1 and
>> drivers/net/dwc_eth_qos.c for ENET2). No matter what I do, there is no
>> packet going out of ENET1.
>>
>> With a network cable plugged into ENET2 (ethernet@30bf0000):
>>
>> ...
>> Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
>> Hit any key to stop autoboot: 0
>> u-boot=>
>> u-boot=> dhcp
>> ethernet@30bf0000 Waiting for PHY auto negotiation to complete....... done
>> DHCP client bound to address 192.168.0.39 (2066 ms)
>> u-boot=>
>>
>> Now moving the cable to ENET1 (ethernet@30be0000) and resetting the board:
>>
>> ...
>> Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
>> Hit any key to stop autoboot: 0
>> u-boot=>
>> u-boot=> setenv ethact ethernet@30be0000
>> u-boot=> dhcp
>> u-boot=> echo $?
>> 1
>>
>> I enabled the debug traces in fecmxc_send() but I see nothing wrong,
>> the function is called with a packet and it returns success yet nothing
>> is sent out on the wire. Any idea what could be wrong?
>> My plan is to add more traces to the driver and compare NET vs. NET_LWIP.
>>
>
> Jerome,
>
> That is consistent with what I see then. The imx8mm (and all imx all
> the way back to imx28) use the FEC ethernet MAC so I would assume you
> see the issue on all of those SOC's. The imx8mp introduced a 2nd
> different MAC, the eqos which you are showing working.
>
> If you look at my results above a packet 'is' received by the DHCP
> server but its missing something where tcpdump shows an '[|llc]' and I
> don't know what that means - something wrong with the link layer?
>
> I feel like something is wrong in the header or packet alignment.
Good catch :) Here is a quick workaroud that works for me:
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 2dc1364beec..85bf1a2b52e 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -658,7 +658,7 @@ static void fecmxc_halt(struct udevice *dev)
* @param[in] length Data count in bytes
* Return: 0 on success
*/
-static int fecmxc_send(struct udevice *dev, void *packet, int length)
+static int fecmxc_send_(struct udevice *dev, void *packet, int length)
{
unsigned int status;
u32 size;
@@ -796,6 +796,21 @@ out:
return ret;
}
+static int fecmxc_send(struct udevice *dev, void *packet, int length)
+{
+ void *pp;
+ int ret;
+
+ pp = memalign(64, length);
+ if (!pp)
+ return -ENOMEM;
+ memcpy(pp, packet, length);
+ ret = fecmxc_send_(dev, pp, length);
+ free(pp);
+
+ return ret;
+}
+
/**
* Pull one frame from the card
* @param[in] dev Our ethernet device to handle
I believe the root of the problem is that lwIP uses malloc() to allocate
the outgoing packets and doesn't enforce any alignement. I need to
revisit that wrt. PKTALIGN.
Thanks,
--
Jerome
> Maybe the key is to understand what the tcpdump output of '[llc]'
> means:
> - lwip fec mac destination tcpdump shows '15:34:25.341167 [|llc]'
> - no-lwip fec mac destination tcptdump shows '15:45:12.548077 IP (tos
> 0x0, ttl 255, id 0, offset 0, flags [DF], proto UDP (17), length 328)
>
> (Adding Joe and Ramon, the network maintainers to cc)
>
> Regards,
>
> Tim
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-07-01 9:58 ` Jerome Forissier
@ 2024-07-01 16:06 ` Tim Harvey
0 siblings, 0 replies; 53+ messages in thread
From: Tim Harvey @ 2024-07-01 16:06 UTC (permalink / raw)
To: Jerome Forissier
Cc: Maxim Uvarov, Fabio Estevam, u-boot, Ilias Apalodimas, Javier Tia,
Joe Hershberger, Ramon Fried
On Mon, Jul 1, 2024 at 2:58 AM Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
>
>
> On 6/28/24 17:48, Tim Harvey wrote:
> > On Fri, Jun 28, 2024 at 2:50 AM Jerome Forissier
> > <jerome.forissier@linaro.org> wrote:
> >>
> >> Hi Tim,
> >>
> >> On 6/26/24 18:00, Tim Harvey wrote:
> >>> On Tue, Jun 25, 2024 at 1:02 AM Jerome Forissier
> >>> <jerome.forissier@linaro.org> wrote:
> >>>>
> >>>> On 6/25/24 00:28, Tim Harvey wrote:
> >>>>> On Sat, Jun 22, 2024 at 1:09 AM Maxim Uvarov <muvarov@gmail.com> wrote:
> >>>>>>
> >>>>>> пт, 21 июн. 2024 г. в 21:42, Fabio Estevam <festevam@gmail.com>:
> >>>>>>>
> >>>>>>> Hi Tim and Jerome,
> >>>>>>>
> >>>>>>> On Fri, Jun 21, 2024 at 1:08 PM Tim Harvey <tharvey@gateworks.com> wrote:
> >>>>>>>
> >>>>>>>> I tried your to-upstream/v5-wip branch
> >>>>>>>> (042bea36eb9731079a3d7afffe3774d79e06ac5d) and it behaves the same. Do
> >>>>>>>> you have something else to try/test?
> >>>>>>>
> >>>>>>> Yes, when I tested older versions from Maxim I could never get lwIP to
> >>>>>>> work with i.MX.
> >>>>>>>
> >>>>>>> Jerome,
> >>>>>>>
> >>>>>>> Please try to run the lwIP series on any i.MX board, if possible.
> >>>>>>>
> >>>>>>> Thanks
> >>>>>>
> >>>>>> Packet not for us means that incoming packet DST MAC does not match to
> >>>>>> the MAC address inside lwip. I.e. to MAC address set into lwip when
> >>>>>> lwip_init was done. Original U-Boot network stack does not compare
> >>>>>> MACs but lwip does. There is something specific on this board, in
> >>>>>> general lwip with debug should print out
> >>>>>> MAC used during initialization. This MAC should match to the MAC from
> >>>>>> the incoming packet.
> >>>>>>
> >>>>>
> >>>>> It seems 'packet not for us' can mean a lot of things.
> >>>>
> >>>> Yeah :-/ in this case I believe the traces are caused by unrelated traffic
> >>>> (UDP port 138 is used by NetBIOS).
> >>>>
> >>>>
> >>>>> I added a bit of debugging around 'DHCP packet accepted' and found I'm
> >>>>> not receiving any packets from my DHCP server. So I connected directly
> >>>>> to another board (isolated network) where I ran my own server and
> >>>>> tcpdump and I don't see packets coming from lwip:
> >>>>
> >>>> Ha! That's interesting.
> >>>>
> >>>>> without lwip my server shows:
> >>>>> # tcpdump -i eth1
> >>>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>>>> length 262144 bytes
> >>>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>>>> length 262144 bytes
> >>>>> 22:18:01.043992 IP (tos 0x0, ttl 255, id 23, offset 0, flags [DF],
> >>>>> proto UDP (17), length 328)
> >>>>> 22:18:01.044391 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> >>>>> proto UDP (17), length 328)
> >>>>> 22:18:01.044454 IP (tos 0x0, ttl 255, id 24, offset 0, flags [DF],
> >>>>> proto UDP (17), length 328)
> >>>>> 22:18:01.044752 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none],
> >>>>> proto UDP (17), length 328)
> >>>>>
> >>>>> # tcpdump -i eth1
> >>>>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>>>> length 262144 bytes
> >>>>> 22:22:41.602178 [|llc]
> >>>>> 22:22:41.709978 [|llc]
> >>>>> 22:22:41.867947 [|llc]
> >>>>> 22:22:42.105202 [|llc]
> >>>>> 22:22:42.502091 [|llc]
> >>>>> 22:22:43.219079 [|llc]
> >>>>> 22:22:44.497979 [|llc]
> >>>>> 22:22:45.776884 [|llc]
> >>>>> 22:22:47.054773 [|llc]
> >>>>> 22:22:48.333667 [|llc]
> >>>>> 22:22:49.611559 [|llc]
> >>>>> 22:22:50.890469 [|llc]
> >>>>>
> >>>>> What actual hardware has this been tested with? I think Tom mentioned
> >>>>> he tested with an rpi of some sort.
> >>>>
> >>>> Yes, I believe he tested on RPi 3B and me too. Ilias has tested on NVIDIA
> >>>> Jetson Nano.
> >>>>
> >>>>> I don't know what the meaning of the llc msg is above but you can see
> >>>>> there is no DHCP request.
> >>>>
> >>>> Some more tracing is needed. Can you try enabling all traces in
> >>>> lib/lwip/u-boot/lwipopts.h? i.e., replace all LWIP_DBG_OFF with
> >>>> LWIP_DBG_ON in the #if defined(CONFIG_LWIP_DEBUG) section. And of course
> >>>> enabled CONFIG_LWIP_DEBUG.
> >>>
> >>> Here's what I see with all those enabled on an imx8mm-venice-gw73xx-0x:
> >>> Net: eth0: ethernet@30be0000 [PRIME]
> >>> GSC : boot watchdog disabled
> >>> Thermal protection:enabled at 96C
> >>> Hit any key to stop autoboot: 0
> >>> u-boot=> dhcp || echo fail
> >>> netif: added interface et IP addr 0.0.0.0 netmask 0.0.0.0 gw 0.0.0.0
> >>> netif: setting default interface et
> >>> dhcp_start(netif=00000000fdf23bb0) et0
> >>> dhcp_start(): mallocing new DHCP client
> >>> dhcp_start(): allocated dhcp
> >>> dhcp_start(): starting DHCP configuration
> >>> udp_bind(ipaddr = 0.0.0.0, port = 68)
> >>> udp_bind: bound to 0.0.0.0, port 68)
> >>> udp_connect: connected to 0.0.0.0, port 67)
> >>> dhcp_discover()
> >>> pbuf_alloc(length=308)
> >>> pbuf_alloc(length=308) == 00000000fdf23d10
> >>> transaction id xid(42021)
> >>> dhcp_discover: making request
> >>> dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
> >>> pbuf_add_header: old 00000000fdf23d5e new 00000000fdf23d56 (8)
> >>> udp_send: added header in given pbuf 00000000fdf23d10
> >>> udp_send: sending datagram of length 316
> >>> udp_send: UDP packet length 316
> >>> inet_chksum_pseudo(): checksumming pbuf 00000000fdf23d10 (has next
> >>> 0000000000000000)
> >>> inet_chksum_pseudo(): pbuf chain lwip_chksum()=807
> >>> udp_send: UDP checksum 0xf7f8
> >>> udp_send: ip_output_if (,,,,0x11,)
> >>> pbuf_add_header: old 00000000fdf23d56 new 00000000fdf23d42 (20)
> >>> ip4_output_if: et0
> >>> IP header:
> >>> +-------------------------------+
> >>> | 4 | 5 | 0x00 | 336 | (v, hl, tos, len)
> >>> +-------------------------------+
> >>> | 0 |000| 0 | (id, flags, offset)
> >>> +-------------------------------+
> >>> | 255 | 17 | 0xba9d | (ttl, proto, chksum)
> >>> +-------------------------------+
> >>> | 0 | 0 | 0 | 0 | (src)
> >>> +-------------------------------+
> >>> | 255 | 255 | 255 | 255 | (dest)
> >>> +-------------------------------+
> >>> ip4_output_if: call netif->output()
> >>> pbuf_add_header: old 00000000fdf23d42 new 00000000fdf23d34 (14)
> >>> ethernet_output: sending packet 00000000fdf23d10
> >>> ^^^ at this point a 350 byte packet gets sent to fecmxc_send for the
> >>> NIC which looks like this via print_hex_dump_bytes():
> >>> 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
> >>> 00000010: 01 50 00 00 00 00 ff 11 ba 9d 00 00 00 00 ff ff .P..............
> >>> 00000020: ff ff 00 44 00 43 01 3c f8 f7 01 01 06 00 00 04 ...D.C.<........
> >>> 00000030: 20 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !..............
> >>> 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
> >>> 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 05 ......c.Sc5..9..
> >>> 00000120: dc 37 03 01 03 1c ff 00 00 00 00 00 00 00 00 00 .7..............
> >>> 00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
> >>
> >> Up to this point everything *seems* OK
> >>
> >>> on my dhcp server 'tcpdump -i eth1 -X -vvv' shows:
> >>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>> length 262144 bytes
> >>> 15:34:25.341167 [|llc]
> >>> 0x0000: 0000 0000 0000 0000 0000 343d f2fd 0000 ..........4=....
> >>> 0x0010: 0000 5e01 5e01 8000 0100 0000 0000 0000 ..^.^...........
> >>> 0x0020: 0000 0000 0000 ffff ffff ffff 00d0 12ba ................
> >>> 0x0030: f8cc 0800 4500 0150 001e 0000 ff11 ba7f ....E..P........
> >>> 0x0040: 0000 0000 ffff ffff 0044 0043 013c 6d78 .........D.C.<mx
> >>> 0x0050: 0101 0600 1255 994f 0000 0000 0000 0000 .....U.O........
> >>> 0x0060: 0000 0000 0000 0000 0000 0000 00d0 12ba ................
> >>> 0x0070: f8cc 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0110: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0120: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0130: 0000 0000 0000 0000 0000 0000 6382 5363 ............c.Sc
> >>> 0x0140: 3501 0139 0205 dc37 0301 031c ff00 0000 5..9...7........
> >>
> >> But here it shows the DHCP packet is not received.
> >>
> >>> Comparing to w/o LWIP:
> >>> u-boot=> dhcp || echo fail
> >>> BOOTP broadcast 1
> >>> fecmxc_send ethernet@30be0000 342
> >>> 00000000: ff ff ff ff ff ff 00 d0 12 ba f8 cc 08 00 45 00 ..............E.
> >>> 00000010: 01 48 00 00 40 00 ff 11 7a a5 00 00 00 00 ff ff .H..@...z.......
> >>> 00000020: ff ff 00 44 00 43 01 34 00 00 01 01 06 00 12 bb ...D.C.4........
> >>> 00000030: 82 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .d..............
> >>> 00000040: 00 00 00 00 00 00 00 d0 12 ba f8 cc 00 00 00 00 ................
> >>> 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000110: 00 00 00 00 00 00 63 82 53 63 35 01 01 39 02 02 ......c.Sc5..9..
> >>> 00000120: 40 5d 02 00 16 5e 03 01 00 00 3c 0c 55 2d 42 6f @]...^....<.U-Bo
> >>> 00000130: 6f 74 2e 61 72 6d 76 38 37 05 01 03 06 0c 11 ff ot.armv87.......
> >>> 00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> >>> 00000150: 00 00 00 00 00 00 ......
> >>> ^^^ Note the packet is 8 bytes shorter
> >>
> >> Yes but that's just padding IIUC.
> >>
> >>> and on the dhcp server:
> >>> tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot
> >>> length 262144 bytes
> >>> 15:45:12.548077 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF],
> >>> proto UDP (17), length 328)
> >>> 0.0.0.0.bootpc > 255.255.255.255.bootps: [no cksum] BOOTP/DHCP,
> >>> Request from 00:d0:12:ba:f8:cc (oui Unknown), length 300, xid
> >>> 0x12bb8264, Flags [none] (0x0000)
> >>> Client-Ethernet-Address 00:d0:12:ba:f8:cc (oui Unknown)
> >>> Vendor-rfc1048 Extensions
> >>> Magic Cookie 0x63825363
> >>> DHCP-Message (53), length 1: Discover
> >>> MSZ (57), length 2: 576
> >>> ARCH (93), length 2: 22
> >>> NDI (94), length 3: 1.0.0
> >>> Vendor-Class (60), length 12: "U-Boot.armv8"
> >>> Parameter-Request (55), length 5:
> >>> Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6),
> >>> Hostname (12)
> >>> RP (17)
> >>> END (255), length 0
> >>> PAD (0), length 0, occurs 22
> >>> 0x0000: 4500 0148 0000 4000 ff11 7aa5 0000 0000 E..H..@...z.....
> >>> 0x0010: ffff ffff 0044 0043 0134 0000 0101 0600 .....D.C.4......
> >>> 0x0020: 12bb 8264 0000 0000 0000 0000 0000 0000 ...d............
> >>> 0x0030: 0000 0000 0000 0000 00d0 12ba f8cc 0000 ................
> >>> 0x0040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x00f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0100: 0000 0000 0000 0000 6382 5363 3501 0139 ........c.Sc5..9
> >>> 0x0110: 0202 405d 0200 165e 0301 0000 3c0c 552d ..@]...^....<.U-
> >>> 0x0120: 426f 6f74 2e61 726d 7638 3705 0103 060c Boot.armv87.....
> >>> 0x0130: 11ff 0000 0000 0000 0000 0000 0000 0000 ................
> >>> 0x0140: 0000 0000 0000 0000 ........
> >>
> >> All good there, as expected.
> >>
> >>>> I do have a i.MX8M Plus EVK board but will not be able to use it before
> >>>> tomorrow.
> >>>
> >>> Please let me know your findings. I can test imx8mp as well but would
> >>> have to reconfigure everything.
> >>
> >> So I did some tests on my imx8mp and I got DHCP to work on the second
> >> ethernet port (ENET2) but *not* on the first one (ENET1). They appear to
> >> be using different drivers (drivers/net/fec_mxc.c for ENET1 and
> >> drivers/net/dwc_eth_qos.c for ENET2). No matter what I do, there is no
> >> packet going out of ENET1.
> >>
> >> With a network cable plugged into ENET2 (ethernet@30bf0000):
> >>
> >> ...
> >> Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
> >> Hit any key to stop autoboot: 0
> >> u-boot=>
> >> u-boot=> dhcp
> >> ethernet@30bf0000 Waiting for PHY auto negotiation to complete....... done
> >> DHCP client bound to address 192.168.0.39 (2066 ms)
> >> u-boot=>
> >>
> >> Now moving the cable to ENET1 (ethernet@30be0000) and resetting the board:
> >>
> >> ...
> >> Net: eth0: ethernet@30be0000, eth1: ethernet@30bf0000 [PRIME]
> >> Hit any key to stop autoboot: 0
> >> u-boot=>
> >> u-boot=> setenv ethact ethernet@30be0000
> >> u-boot=> dhcp
> >> u-boot=> echo $?
> >> 1
> >>
> >> I enabled the debug traces in fecmxc_send() but I see nothing wrong,
> >> the function is called with a packet and it returns success yet nothing
> >> is sent out on the wire. Any idea what could be wrong?
> >> My plan is to add more traces to the driver and compare NET vs. NET_LWIP.
> >>
> >
> > Jerome,
> >
> > That is consistent with what I see then. The imx8mm (and all imx all
> > the way back to imx28) use the FEC ethernet MAC so I would assume you
> > see the issue on all of those SOC's. The imx8mp introduced a 2nd
> > different MAC, the eqos which you are showing working.
> >
> > If you look at my results above a packet 'is' received by the DHCP
> > server but its missing something where tcpdump shows an '[|llc]' and I
> > don't know what that means - something wrong with the link layer?
> >
> > I feel like something is wrong in the header or packet alignment.
>
> Good catch :) Here is a quick workaroud that works for me:
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index 2dc1364beec..85bf1a2b52e 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -658,7 +658,7 @@ static void fecmxc_halt(struct udevice *dev)
> * @param[in] length Data count in bytes
> * Return: 0 on success
> */
> -static int fecmxc_send(struct udevice *dev, void *packet, int length)
> +static int fecmxc_send_(struct udevice *dev, void *packet, int length)
> {
> unsigned int status;
> u32 size;
> @@ -796,6 +796,21 @@ out:
> return ret;
> }
>
> +static int fecmxc_send(struct udevice *dev, void *packet, int length)
> +{
> + void *pp;
> + int ret;
> +
> + pp = memalign(64, length);
> + if (!pp)
> + return -ENOMEM;
> + memcpy(pp, packet, length);
> + ret = fecmxc_send_(dev, pp, length);
> + free(pp);
> +
> + return ret;
> +}
> +
> /**
> * Pull one frame from the card
> * @param[in] dev Our ethernet device to handle
>
>
> I believe the root of the problem is that lwIP uses malloc() to allocate
> the outgoing packets and doesn't enforce any alignement. I need to
> revisit that wrt. PKTALIGN.
>
Yes, this makes sense. This driver uses DMA.
Glad we got to the bottom of it!
This hack does resolve the issue.
Best Regards,
Tim
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-17 15:32 [PATCH v4 00/14] Introduce the lwIP network stack Jerome Forissier
` (15 preceding siblings ...)
2024-06-20 17:10 ` Tim Harvey
@ 2024-06-21 14:57 ` Simon Glass
2024-06-21 17:55 ` Jerome Forissier
16 siblings, 1 reply; 53+ messages in thread
From: Simon Glass @ 2024-06-21 14:57 UTC (permalink / raw)
To: Jerome Forissier; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
Hi Jerome,
On Mon, 17 Jun 2024 at 09:33, Jerome Forissier
<jerome.forissier@linaro.org> wrote:
>
> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
> stack [2] [3] as an alternative to the current implementation in net/,
> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
> reasons for doing so are:
> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
> has some additional lwIP and Mbed TLS patches to do so. With that it
> becomes possible to fetch and launch a distro installer such as Debian
> etc. using a secure, authenticated connection directly from the U-Boot
> shell. Several use cases:
> * Authentication: prevent MITM attack (third party replacing the
> binary with a different one)
> * Confidentiality: prevent third parties from grabbing a copy of the
> image as it is being downloaded
> * Allow connection to servers that do not support plain HTTP anymore
> (this is becoming more and more common on the Internet these days)
> - Possibly benefit from additional features implemented in lwIP
> - Less code to maintain in U-Boot
>
> Prior to applying this series, the lwIP stack needs to be added as a
> Git subtree with the following command:
>
> $ git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE
>
> The first patch renames some enums in order to avoid a conflict when a
> later patch enables the lwIP library.
>
> The second patch introduces a new Kconfig symbol: NET_LWIP, which selects
> the lwIP implementation instead of the current one (NET). Contrary to the
> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
> simultaneously. The rationale is we want to start from a clean state and
> not pull potentially duplicated functionality from both stacks. Note
> however that a few files are still built in net/, they are the ones
> related to ethernet device management and the ethernet bootflow.
>
> The third patch splits the net.h header into net-legacy.h, net-common.h,
> net-lwip.h, leaving net.h as a simple wrapper.
>
> The fourth patch introduces the Makefile to build lwIP when NET_LWIP is
> enabled.
>
> The subsequent patches implement various network-oriented commands and
> features: dhcp, dns, ping, tftpboot, wget.
>
> A number of features are currently incompatible with NET_LWIP: SANDBOX,
> DFU_TFTP, FASTBOOT, SPL_NET. All make assumptions on how the network
> stack is implemented and/or pull sybols that are not trivially exported
> from lwIP. Some interface rework may be needed.
>
> Due to the above and in order to provide some level of testing, a new QEMU
> configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
> as qemu_arm64_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
> Tests are added to test/py/tests/test_net.py for that configuration.
>
> Changes in v4:
>
> - Fixed the DHCP algorithm which was missing a sys_timeout() call in
> the "fine timer" callback. This should close the issue that Tom R.
> reported with his Raspberry Pi 3 (it does fix it on mine).
> - The DHCP exchange timeout is increased from 2 to 10 seconds
> - The DHCP exchange can be interrupted with Ctrl-C.
> - "net: introduce alternative implementation as net-lwip/": rework
> dependencies. A few symbols have 'depends on !NET_LWIP' and in addition
> 'NET_LWIP depends on !SANDBOX'. Sandbox, DSA and fastboot are
> unsupported, because they are deeply welded to the current stack.
> - All network commands (dns, ping, tftp and wget):
> * Get rid of global variables (Ilias A.)
> * Use printf() rather than log_info()
> - "net-lwip: add ping command": use packet count instead of
> timeout, fix code style (Ilias A.)
> - Add "net: split cmd/net.c into cmd/net.c and cmd/net-common.c"
> extracted from the wget patch (Ilias A.).
> - Add "net: split include/net.h into net{,-common,-legacy,-lwip}.h"
> (Ilias A.)
> - Add "flash: prefix error codes with FL_" which is required to
> avoid name clashes when splitting net.h
> - Reworked the initialization of the lwIP stack. One and only
> one network interface (struct netif) is added for the duration
> of the command that uses that interface. That's commit "net-lwip:
> add DHCP support and dhcp commmand".
> - Drop "test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y",
> not needed now that NET_LWIP depend on !SANDBOX.
> - qemu_arm64_lwip_defconfig now enables CMD_DNS and CMD_WGET (so
> that all the supported network commands are available).
>
> Changes in v3:
>
> - Make NET_LWIP a Kconfig choice in patch "net: introduce alternative
> implementation as net-lwip/" (Tom R.)
> - Drop the patch introducing lwIP as a Git subtree and document the git
> command in the cover letter instead (Tom R.)
> - "net-lwip: add TFTP support and tftpboot command": use the same
> "Bytes transferred =" message as in the legacy implementation (Tom R.,
> Maxim U.)
> - Drop "test/py: net: add _lwip variants of dhcp, ping and tftpboot
> tests" which is not needed anymore.
> - Add missing kfree() calls in cmd/net-common.c and fix the parsing of
> decimal address in net-lwip/wget.c (patch "net-lwip: add wget command")
> (Maxim U.)
> - "net-lwip: add ping command": drop the ICMP payload (Ilias A.). Set
> the sequence number to zero when entering ping_loop().
>
> Changes in v2:
>
> ** Address comments from Ilias A.
>
> - "net-lwip: add wget command"
> Implement the wget_with_dns() function to do most of the wget work and
> call it from do_wget(). This allows to simplify patch "net-lwip: add
> support for EFI_HTTP_BOOT".
>
> - "net-lwip: import net command from cmd/net.c"
> Move a few functions from cmd/net.c to a new file cmd/net-common.c
> rather than duplicating then in cmd/net-lwip.c.
>
> - "net-lwip: add support for EFI_HTTP_BOOT"
> Since wget_with_dns() is now implemented in "net-lwip: add wget command",
> just enable the wget command when the lwIP stack is enabled and
> EFI_HTTP_BOOT is requested.
>
> ** Address comments from Tom R.
>
> - "net-lwip: add DHCP support and dhcp commmand",
> "net-lwip: add TFTP support and tftpboot command",
> "net-lwip: add ping command",
> "net-lwip: add dns command",
> "net-lwip: add wget command"
> Do not introduce new CMD_XXX_LWIP symbols and use existing CMD_XXX
> instead.
>
> - "configs: add qemu_arm64_lwip_defconfig"
> Use #include <configs/qemu_arm64_defconfig>.
>
> - "net-lwip: import lwIP library under lib/lwip"
> Patch removed and replaced by the introduction of a Git subtree:
> "Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c3".
>
> Note that I have not yet addressed your comments on "test: dm: dsa,
> eth: disable tests when CONFIG_NET_LWIP=y"). I need some more time
> for that and I think running CI on this v2 will help better understand
> what is needed for v3.
>
> ** Miscellaneous improvements
>
> - "net: introduce alternative implementation as net-lwip/":
>
> * Make DFU_OVER_TFTP not DFU_TFTP incompatible with NET_LWIP. It seems
> quite natural to supplement "depends on NET" with "&& !NET_LWIP".
> * Make PROT_*_LWIP not visible by removing the Kconfig prompt.
>
> [1] https://lore.kernel.org/all/20231127125726.3735-1-maxim.uvarov@linaro.org/
> [2] https://www.nongnu.org/lwip/
> [3] https://en.wikipedia.org/wiki/LwIP
>
> CC: Javier Tia <javier.tia@linaro.org>
>
> Jerome Forissier (14):
> flash: prefix error codes with FL_
> net: introduce alternative implementation as net-lwip/
> net: split include/net.h into net{,-common,-legacy,-lwip}.h
> net-lwip: build lwIP
> net-lwip: add DHCP support and dhcp commmand
> net-lwip: add TFTP support and tftpboot command
> net-lwip: add ping command
> net-lwip: add dns command
> net: split cmd/net.c into cmd/net.c and cmd/net-common.c
> net-lwip: add wget command
> cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
> configs: add qemu_arm64_lwip_defconfig
> MAINTAINERS: net-lwip: add myself as a maintainer
> CI: add qemu_arm64_lwip to the test matrix
>
> .azure-pipelines.yml | 7 +
> Kconfig | 41 ++
> MAINTAINERS | 11 +
> Makefile | 12 +-
> board/cobra5272/flash.c | 26 +-
> board/freescale/m5253demo/flash.c | 6 +-
> boot/Kconfig | 5 +-
> cmd/Kconfig | 44 ++
> cmd/Makefile | 7 +
> cmd/bdinfo.c | 5 +-
> cmd/net-common.c | 109 ++++
> cmd/net-lwip.c | 45 ++
> cmd/net.c | 115 ----
> common/Kconfig | 2 +-
> common/board_r.c | 4 +-
> common/flash.c | 44 +-
> common/spl/Kconfig | 1 +
> configs/qemu_arm64_lwip_defconfig | 4 +
> drivers/dfu/Kconfig | 1 +
> drivers/fastboot/Kconfig | 1 +
> drivers/mtd/cfi_flash.c | 36 +-
> drivers/net/Kconfig | 3 +-
> drivers/net/phy/Kconfig | 2 +-
> drivers/usb/gadget/Kconfig | 2 +-
> include/flash.h | 20 +-
> include/net-common.h | 408 +++++++++++++
> include/net-legacy.h | 649 ++++++++++++++++++++
> include/net-lwip.h | 36 ++
> include/net.h | 944 +-----------------------------
> lib/Makefile | 2 +
> lib/lwip/Makefile | 55 ++
> lib/lwip/u-boot/arch/cc.h | 43 ++
> lib/lwip/u-boot/arch/sys_arch.h | 0
> lib/lwip/u-boot/limits.h | 0
> lib/lwip/u-boot/lwipopts.h | 197 +++++++
> net-lwip/Kconfig | 37 ++
> net-lwip/Makefile | 18 +
> net-lwip/dhcp.c | 108 ++++
> net-lwip/dns.c | 117 ++++
> net-lwip/eth_internal.h | 35 ++
> net-lwip/net-lwip.c | 270 +++++++++
> net-lwip/ping.c | 174 ++++++
> net-lwip/tftp.c | 226 +++++++
> net-lwip/wget.c | 269 +++++++++
> net/Kconfig | 14 -
> 45 files changed, 3008 insertions(+), 1147 deletions(-)
> create mode 100644 cmd/net-common.c
> create mode 100644 cmd/net-lwip.c
> create mode 100644 configs/qemu_arm64_lwip_defconfig
> create mode 100644 include/net-common.h
> create mode 100644 include/net-legacy.h
> create mode 100644 include/net-lwip.h
> create mode 100644 lib/lwip/Makefile
> create mode 100644 lib/lwip/u-boot/arch/cc.h
> create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
> create mode 100644 lib/lwip/u-boot/limits.h
> create mode 100644 lib/lwip/u-boot/lwipopts.h
> create mode 100644 net-lwip/Kconfig
> create mode 100644 net-lwip/Makefile
> create mode 100644 net-lwip/dhcp.c
> create mode 100644 net-lwip/dns.c
> create mode 100644 net-lwip/eth_internal.h
> create mode 100644 net-lwip/net-lwip.c
> create mode 100644 net-lwip/ping.c
> create mode 100644 net-lwip/tftp.c
> create mode 100644 net-lwip/wget.c
Would it be possible to put net-lwip in net/lwip? We should try to
keep the directory structure clean / minimal.
Regards,
Simon
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH v4 00/14] Introduce the lwIP network stack
2024-06-21 14:57 ` Simon Glass
@ 2024-06-21 17:55 ` Jerome Forissier
0 siblings, 0 replies; 53+ messages in thread
From: Jerome Forissier @ 2024-06-21 17:55 UTC (permalink / raw)
To: Simon Glass; +Cc: u-boot, Ilias Apalodimas, Javier Tia, Maxim Uvarov
Hi Simon,
On 6/21/24 16:57, Simon Glass wrote:
> Hi Jerome,
>
> On Mon, 17 Jun 2024 at 09:33, Jerome Forissier
> <jerome.forissier@linaro.org> wrote:
>>
>> This is a rework of a patch series by Maxim Uvarov: "net/lwip: add lwip
>> library for the network stack" [1]. The goal is to introduce the lwIP TCP/IP
>> stack [2] [3] as an alternative to the current implementation in net/,
>> selectable with Kconfig, and ultimately keep only lwIP if possible. Some
>> reasons for doing so are:
>> - Make the support of HTTPS in the wget command easier. Javier T. (CC'd)
>> has some additional lwIP and Mbed TLS patches to do so. With that it
>> becomes possible to fetch and launch a distro installer such as Debian
>> etc. using a secure, authenticated connection directly from the U-Boot
>> shell. Several use cases:
>> * Authentication: prevent MITM attack (third party replacing the
>> binary with a different one)
>> * Confidentiality: prevent third parties from grabbing a copy of the
>> image as it is being downloaded
>> * Allow connection to servers that do not support plain HTTP anymore
>> (this is becoming more and more common on the Internet these days)
>> - Possibly benefit from additional features implemented in lwIP
>> - Less code to maintain in U-Boot
>>
>> Prior to applying this series, the lwIP stack needs to be added as a
>> Git subtree with the following command:
>>
>> $ git subtree add --squash --prefix lib/lwip/lwip https://git.savannah.gnu.org/git/lwip.git STABLE-2_2_0_RELEASE
>>
>> The first patch renames some enums in order to avoid a conflict when a
>> later patch enables the lwIP library.
>>
>> The second patch introduces a new Kconfig symbol: NET_LWIP, which selects
>> the lwIP implementation instead of the current one (NET). Contrary to the
>> approach chosen by Maxim in [1], NET_LWIP and NET cannot be enabled
>> simultaneously. The rationale is we want to start from a clean state and
>> not pull potentially duplicated functionality from both stacks. Note
>> however that a few files are still built in net/, they are the ones
>> related to ethernet device management and the ethernet bootflow.
>>
>> The third patch splits the net.h header into net-legacy.h, net-common.h,
>> net-lwip.h, leaving net.h as a simple wrapper.
>>
>> The fourth patch introduces the Makefile to build lwIP when NET_LWIP is
>> enabled.
>>
>> The subsequent patches implement various network-oriented commands and
>> features: dhcp, dns, ping, tftpboot, wget.
>>
>> A number of features are currently incompatible with NET_LWIP: SANDBOX,
>> DFU_TFTP, FASTBOOT, SPL_NET. All make assumptions on how the network
>> stack is implemented and/or pull sybols that are not trivially exported
>> from lwIP. Some interface rework may be needed.
>>
>> Due to the above and in order to provide some level of testing, a new QEMU
>> configuration is introduced (qemu_arm64_lwip_defconfig) which is the same
>> as qemu_arm64_defconfig but with NET_LWIP and CMD_*_LWIP enabled.
>> Tests are added to test/py/tests/test_net.py for that configuration.
>>
>> Changes in v4:
>>
>> - Fixed the DHCP algorithm which was missing a sys_timeout() call in
>> the "fine timer" callback. This should close the issue that Tom R.
>> reported with his Raspberry Pi 3 (it does fix it on mine).
>> - The DHCP exchange timeout is increased from 2 to 10 seconds
>> - The DHCP exchange can be interrupted with Ctrl-C.
>> - "net: introduce alternative implementation as net-lwip/": rework
>> dependencies. A few symbols have 'depends on !NET_LWIP' and in addition
>> 'NET_LWIP depends on !SANDBOX'. Sandbox, DSA and fastboot are
>> unsupported, because they are deeply welded to the current stack.
>> - All network commands (dns, ping, tftp and wget):
>> * Get rid of global variables (Ilias A.)
>> * Use printf() rather than log_info()
>> - "net-lwip: add ping command": use packet count instead of
>> timeout, fix code style (Ilias A.)
>> - Add "net: split cmd/net.c into cmd/net.c and cmd/net-common.c"
>> extracted from the wget patch (Ilias A.).
>> - Add "net: split include/net.h into net{,-common,-legacy,-lwip}.h"
>> (Ilias A.)
>> - Add "flash: prefix error codes with FL_" which is required to
>> avoid name clashes when splitting net.h
>> - Reworked the initialization of the lwIP stack. One and only
>> one network interface (struct netif) is added for the duration
>> of the command that uses that interface. That's commit "net-lwip:
>> add DHCP support and dhcp commmand".
>> - Drop "test: dm: dsa, eth: disable tests when CONFIG_NET_LWIP=y",
>> not needed now that NET_LWIP depend on !SANDBOX.
>> - qemu_arm64_lwip_defconfig now enables CMD_DNS and CMD_WGET (so
>> that all the supported network commands are available).
>>
>> Changes in v3:
>>
>> - Make NET_LWIP a Kconfig choice in patch "net: introduce alternative
>> implementation as net-lwip/" (Tom R.)
>> - Drop the patch introducing lwIP as a Git subtree and document the git
>> command in the cover letter instead (Tom R.)
>> - "net-lwip: add TFTP support and tftpboot command": use the same
>> "Bytes transferred =" message as in the legacy implementation (Tom R.,
>> Maxim U.)
>> - Drop "test/py: net: add _lwip variants of dhcp, ping and tftpboot
>> tests" which is not needed anymore.
>> - Add missing kfree() calls in cmd/net-common.c and fix the parsing of
>> decimal address in net-lwip/wget.c (patch "net-lwip: add wget command")
>> (Maxim U.)
>> - "net-lwip: add ping command": drop the ICMP payload (Ilias A.). Set
>> the sequence number to zero when entering ping_loop().
>>
>> Changes in v2:
>>
>> ** Address comments from Ilias A.
>>
>> - "net-lwip: add wget command"
>> Implement the wget_with_dns() function to do most of the wget work and
>> call it from do_wget(). This allows to simplify patch "net-lwip: add
>> support for EFI_HTTP_BOOT".
>>
>> - "net-lwip: import net command from cmd/net.c"
>> Move a few functions from cmd/net.c to a new file cmd/net-common.c
>> rather than duplicating then in cmd/net-lwip.c.
>>
>> - "net-lwip: add support for EFI_HTTP_BOOT"
>> Since wget_with_dns() is now implemented in "net-lwip: add wget command",
>> just enable the wget command when the lwIP stack is enabled and
>> EFI_HTTP_BOOT is requested.
>>
>> ** Address comments from Tom R.
>>
>> - "net-lwip: add DHCP support and dhcp commmand",
>> "net-lwip: add TFTP support and tftpboot command",
>> "net-lwip: add ping command",
>> "net-lwip: add dns command",
>> "net-lwip: add wget command"
>> Do not introduce new CMD_XXX_LWIP symbols and use existing CMD_XXX
>> instead.
>>
>> - "configs: add qemu_arm64_lwip_defconfig"
>> Use #include <configs/qemu_arm64_defconfig>.
>>
>> - "net-lwip: import lwIP library under lib/lwip"
>> Patch removed and replaced by the introduction of a Git subtree:
>> "Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c3".
>>
>> Note that I have not yet addressed your comments on "test: dm: dsa,
>> eth: disable tests when CONFIG_NET_LWIP=y"). I need some more time
>> for that and I think running CI on this v2 will help better understand
>> what is needed for v3.
>>
>> ** Miscellaneous improvements
>>
>> - "net: introduce alternative implementation as net-lwip/":
>>
>> * Make DFU_OVER_TFTP not DFU_TFTP incompatible with NET_LWIP. It seems
>> quite natural to supplement "depends on NET" with "&& !NET_LWIP".
>> * Make PROT_*_LWIP not visible by removing the Kconfig prompt.
>>
>> [1] https://lore.kernel.org/all/20231127125726.3735-1-maxim.uvarov@linaro.org/
>> [2] https://www.nongnu.org/lwip/
>> [3] https://en.wikipedia.org/wiki/LwIP
>>
>> CC: Javier Tia <javier.tia@linaro.org>
>>
>> Jerome Forissier (14):
>> flash: prefix error codes with FL_
>> net: introduce alternative implementation as net-lwip/
>> net: split include/net.h into net{,-common,-legacy,-lwip}.h
>> net-lwip: build lwIP
>> net-lwip: add DHCP support and dhcp commmand
>> net-lwip: add TFTP support and tftpboot command
>> net-lwip: add ping command
>> net-lwip: add dns command
>> net: split cmd/net.c into cmd/net.c and cmd/net-common.c
>> net-lwip: add wget command
>> cmd: bdinfo: enable -e when CONFIG_CMD_NET_LWIP=y
>> configs: add qemu_arm64_lwip_defconfig
>> MAINTAINERS: net-lwip: add myself as a maintainer
>> CI: add qemu_arm64_lwip to the test matrix
>>
>> .azure-pipelines.yml | 7 +
>> Kconfig | 41 ++
>> MAINTAINERS | 11 +
>> Makefile | 12 +-
>> board/cobra5272/flash.c | 26 +-
>> board/freescale/m5253demo/flash.c | 6 +-
>> boot/Kconfig | 5 +-
>> cmd/Kconfig | 44 ++
>> cmd/Makefile | 7 +
>> cmd/bdinfo.c | 5 +-
>> cmd/net-common.c | 109 ++++
>> cmd/net-lwip.c | 45 ++
>> cmd/net.c | 115 ----
>> common/Kconfig | 2 +-
>> common/board_r.c | 4 +-
>> common/flash.c | 44 +-
>> common/spl/Kconfig | 1 +
>> configs/qemu_arm64_lwip_defconfig | 4 +
>> drivers/dfu/Kconfig | 1 +
>> drivers/fastboot/Kconfig | 1 +
>> drivers/mtd/cfi_flash.c | 36 +-
>> drivers/net/Kconfig | 3 +-
>> drivers/net/phy/Kconfig | 2 +-
>> drivers/usb/gadget/Kconfig | 2 +-
>> include/flash.h | 20 +-
>> include/net-common.h | 408 +++++++++++++
>> include/net-legacy.h | 649 ++++++++++++++++++++
>> include/net-lwip.h | 36 ++
>> include/net.h | 944 +-----------------------------
>> lib/Makefile | 2 +
>> lib/lwip/Makefile | 55 ++
>> lib/lwip/u-boot/arch/cc.h | 43 ++
>> lib/lwip/u-boot/arch/sys_arch.h | 0
>> lib/lwip/u-boot/limits.h | 0
>> lib/lwip/u-boot/lwipopts.h | 197 +++++++
>> net-lwip/Kconfig | 37 ++
>> net-lwip/Makefile | 18 +
>> net-lwip/dhcp.c | 108 ++++
>> net-lwip/dns.c | 117 ++++
>> net-lwip/eth_internal.h | 35 ++
>> net-lwip/net-lwip.c | 270 +++++++++
>> net-lwip/ping.c | 174 ++++++
>> net-lwip/tftp.c | 226 +++++++
>> net-lwip/wget.c | 269 +++++++++
>> net/Kconfig | 14 -
>> 45 files changed, 3008 insertions(+), 1147 deletions(-)
>> create mode 100644 cmd/net-common.c
>> create mode 100644 cmd/net-lwip.c
>> create mode 100644 configs/qemu_arm64_lwip_defconfig
>> create mode 100644 include/net-common.h
>> create mode 100644 include/net-legacy.h
>> create mode 100644 include/net-lwip.h
>> create mode 100644 lib/lwip/Makefile
>> create mode 100644 lib/lwip/u-boot/arch/cc.h
>> create mode 100644 lib/lwip/u-boot/arch/sys_arch.h
>> create mode 100644 lib/lwip/u-boot/limits.h
>> create mode 100644 lib/lwip/u-boot/lwipopts.h
>> create mode 100644 net-lwip/Kconfig
>> create mode 100644 net-lwip/Makefile
>> create mode 100644 net-lwip/dhcp.c
>> create mode 100644 net-lwip/dns.c
>> create mode 100644 net-lwip/eth_internal.h
>> create mode 100644 net-lwip/net-lwip.c
>> create mode 100644 net-lwip/ping.c
>> create mode 100644 net-lwip/tftp.c
>> create mode 100644 net-lwip/wget.c
>
> Would it be possible to put net-lwip in net/lwip? We should try to
> keep the directory structure clean / minimal.
Sure.
--
Jerome
> Regards,
> Simon
^ permalink raw reply [flat|nested] 53+ messages in thread