diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bootp.c | 73 | ||||
-rw-r--r-- | net/bootp.h | 2 | ||||
-rw-r--r-- | net/eth-uclass.c | 2 | ||||
-rw-r--r-- | net/link_local.c | 2 | ||||
-rw-r--r-- | net/lwip/dhcp.c | 1 | ||||
-rw-r--r-- | net/lwip/dns.c | 1 | ||||
-rw-r--r-- | net/lwip/net-lwip.c | 1 | ||||
-rw-r--r-- | net/lwip/tftp.c | 1 | ||||
-rw-r--r-- | net/lwip/wget.c | 1 | ||||
-rw-r--r-- | net/pcap.c | 1 | ||||
-rw-r--r-- | net/tftp.c | 4 |
11 files changed, 69 insertions, 20 deletions
diff --git a/net/bootp.c b/net/bootp.c index afd5b48094a..f22921ed388 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -41,6 +41,22 @@ */ #define TIMEOUT_MS ((3 + (CONFIG_NET_RETRY_COUNT * 5)) * 1000) +/* + * According to rfc951 : 7.2. Client Retransmission Strategy + * "After the 'average' backoff reaches about 60 seconds, it should be + * increased no further, but still randomized." + * + * U-Boot has saturated this backoff at 2 seconds for a long time. + * To modify, set the environment variable "bootpretransmitperiodmax" + */ +#define RETRANSMIT_PERIOD_MAX_MS 60000 + +/* Retransmission timeout for the initial packet (in milliseconds). + * This timeout will double on each retry. To modify, set the + * environment variable bootpretransmitperiodinit. + */ +#define RETRANSMIT_PERIOD_INIT_MS 250 + #ifndef CFG_DHCP_MIN_EXT_LEN /* minimal length of extension list */ #define CFG_DHCP_MIN_EXT_LEN 64 #endif @@ -52,6 +68,7 @@ u32 bootp_ids[CFG_BOOTP_ID_CACHE_SIZE]; unsigned int bootp_num_ids; int bootp_try; +u32 bootp_id; ulong bootp_start; ulong bootp_timeout; char net_nis_domain[32] = {0,}; /* Our NIS domain */ @@ -59,6 +76,7 @@ char net_hostname[32] = {0,}; /* Our hostname */ char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN] = {0,}; /* Our bootpath */ static ulong time_taken_max; +static u32 retransmit_period_max_ms; #if defined(CONFIG_CMD_DHCP) static dhcp_state_t dhcp_state = INIT; @@ -395,6 +413,7 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip, static void bootp_timeout_handler(void) { ulong time_taken = get_timer(bootp_start); + int rand_minus_plus_100; if (time_taken >= time_taken_max) { #ifdef CONFIG_BOOTP_MAY_FAIL @@ -413,8 +432,17 @@ static void bootp_timeout_handler(void) } } else { bootp_timeout *= 2; - if (bootp_timeout > 2000) - bootp_timeout = 2000; + if (bootp_timeout > retransmit_period_max_ms) + bootp_timeout = retransmit_period_max_ms; + + /* Randomize by adding bootp_timeout*RAND, where RAND + * is a randomization factor between -0.1..+0.1 + */ + srand(get_ticks() + rand()); + rand_minus_plus_100 = ((rand() % 200) - 100); + bootp_timeout = bootp_timeout + + (((int)bootp_timeout * rand_minus_plus_100) / 1000); + net_set_timeout_handler(bootp_timeout, bootp_timeout_handler); bootp_request(); } @@ -602,7 +630,7 @@ static int dhcp_extended(u8 *e, int message_type, struct in_addr server_ip, *cnt += 1; #endif if (IS_ENABLED(CONFIG_BOOTP_PXE_DHCP_OPTION)) { - *e++ = 209; /* PXELINUX Config File */ + *e++ = DHCP_OPTION_PXE_CONFIG_FILE; /* PXELINUX Config File */ *cnt += 1; } /* no options, so back up to avoid sending an empty request list */ @@ -713,7 +741,8 @@ void bootp_reset(void) bootp_num_ids = 0; bootp_try = 0; bootp_start = get_timer(0); - bootp_timeout = 250; + + bootp_timeout = env_get_ulong("bootpretransmitperiodinit", 10, RETRANSMIT_PERIOD_INIT_MS); } void bootp_request(void) @@ -725,7 +754,6 @@ void bootp_request(void) #ifdef CONFIG_BOOTP_RANDOM_DELAY ulong rand_ms; #endif - u32 bootp_id; struct in_addr zero_ip; struct in_addr bcast_ip; char *ep; /* Environment pointer */ @@ -741,6 +769,9 @@ void bootp_request(void) else time_taken_max = TIMEOUT_MS; + retransmit_period_max_ms = env_get_ulong("bootpretransmitperiodmax", 10, + RETRANSMIT_PERIOD_MAX_MS); + #ifdef CONFIG_BOOTP_RANDOM_DELAY /* Random BOOTP delay */ if (bootp_try == 0) srand_mac(); @@ -800,19 +831,27 @@ void bootp_request(void) extlen = bootp_extended((u8 *)bp->bp_vend); #endif - /* - * Bootp ID is the lower 4 bytes of our ethernet address - * plus the current time in ms. - */ - bootp_id = ((u32)net_ethaddr[2] << 24) - | ((u32)net_ethaddr[3] << 16) - | ((u32)net_ethaddr[4] << 8) - | (u32)net_ethaddr[5]; - bootp_id += get_timer(0); - bootp_id = htonl(bootp_id); + /* Only generate a new transaction ID for each new BOOTP request */ + if (bootp_try == 1) { + if (IS_ENABLED(CONFIG_BOOTP_RANDOM_XID)) { + srand(get_ticks() + rand()); + bootp_id = rand(); + } else { + /* + * Bootp ID is the lower 4 bytes of our ethernet address + * plus the current time in ms. + */ + bootp_id = ((u32)net_ethaddr[2] << 24) + | ((u32)net_ethaddr[3] << 16) + | ((u32)net_ethaddr[4] << 8) + | (u32)net_ethaddr[5]; + bootp_id += get_timer(0); + bootp_id = htonl(bootp_id); + } + } + bootp_add_id(bootp_id); net_copy_u32(&bp->bp_id, &bootp_id); - /* * Calculate proper packet lengths taking into account the * variable size of the options field @@ -921,7 +960,7 @@ static void dhcp_process_options(uchar *popt, uchar *end) net_boot_file_name[size] = 0; } break; - case 209: /* PXELINUX Config File */ + case DHCP_OPTION_PXE_CONFIG_FILE: /* PXELINUX Config File */ if (IS_ENABLED(CONFIG_BOOTP_PXE_DHCP_OPTION)) { /* In case it has already been allocated when get DHCP Offer packet, * free first to avoid memory leak. diff --git a/net/bootp.h b/net/bootp.h index 521d38f3528..68320bf66cf 100644 --- a/net/bootp.h +++ b/net/bootp.h @@ -90,6 +90,8 @@ typedef enum { INIT, #define DHCP_NAK 6 #define DHCP_RELEASE 7 +#define DHCP_OPTION_PXE_CONFIG_FILE 209 /* "ConfigFile" option according to rfc5071 */ + /**********************************************************************/ #endif /* __BOOTP_H__ */ diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 5555f82f23e..a233912fd8e 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -461,6 +461,8 @@ int eth_rx(void) eth_get_ops(current)->free_pkt(current, packet, ret); if (ret <= 0) break; + if (!eth_is_active(current)) + break; } if (ret == -EAGAIN) ret = 0; diff --git a/net/link_local.c b/net/link_local.c index 179721333ff..f6425ff3df2 100644 --- a/net/link_local.c +++ b/net/link_local.c @@ -106,7 +106,7 @@ static void configure_wait(void) void link_local_start(void) { - ip = env_get_ip("llipaddr"); + ip = string_to_ip(env_get("llipaddr")); if (ip.s_addr != 0 && (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR) { puts("invalid link address"); diff --git a/net/lwip/dhcp.c b/net/lwip/dhcp.c index 92bd7067a7f..043d2ab6e94 100644 --- a/net/lwip/dhcp.c +++ b/net/lwip/dhcp.c @@ -3,6 +3,7 @@ #include <command.h> #include <console.h> +#include <env.h> #include <log.h> #include <dm/device.h> #include <linux/delay.h> diff --git a/net/lwip/dns.c b/net/lwip/dns.c index 19172ac959a..6862869d9e3 100644 --- a/net/lwip/dns.c +++ b/net/lwip/dns.c @@ -3,6 +3,7 @@ #include <command.h> #include <console.h> +#include <env.h> #include <lwip/dns.h> #include <lwip/timeouts.h> #include <net.h> diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c index f05c4cd3f64..abc52b32049 100644 --- a/net/lwip/net-lwip.c +++ b/net/lwip/net-lwip.c @@ -3,6 +3,7 @@ /* Copyright (C) 2024 Linaro Ltd. */ #include <command.h> +#include <env.h> #include <dm/device.h> #include <dm/uclass.h> #include <hexdump.h> diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index fae701bad2e..b7eb486ef77 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -6,6 +6,7 @@ #include <display_options.h> #include <dm/device.h> #include <efi_loader.h> +#include <env.h> #include <image.h> #include <linux/delay.h> #include <linux/kconfig.h> diff --git a/net/lwip/wget.c b/net/lwip/wget.c index ea1113e18b1..f4fd9718285 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -5,6 +5,7 @@ #include <console.h> #include <display_options.h> #include <efi_loader.h> +#include <env.h> #include <image.h> #include <linux/kconfig.h> #include <lwip/apps/http_client.h> diff --git a/net/pcap.c b/net/pcap.c index c959e3e4e51..d1d6f705cda 100644 --- a/net/pcap.c +++ b/net/pcap.c @@ -3,6 +3,7 @@ * Copyright 2019 Ramon Fried <rfried.dev@gmail.com> */ +#include <env.h> #include <net.h> #include <net/pcap.h> #include <time.h> diff --git a/net/tftp.c b/net/tftp.c index fd9c9492929..1ca9a5ea7cf 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -655,7 +655,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, net_set_timeout_handler(timeout_ms, tftp_timeout_handler); if (store_block(tftp_cur_block, pkt + 2, len)) { - eth_halt(); + eth_halt_state_only(); net_set_state(NETLOOP_FAIL); break; } @@ -685,7 +685,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, case TFTP_ERR_FILE_NOT_FOUND: case TFTP_ERR_ACCESS_DENIED: puts("Not retrying...\n"); - eth_halt(); + eth_halt_state_only(); net_set_state(NETLOOP_FAIL); break; case TFTP_ERR_UNDEFINED: |