summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bootp.c73
-rw-r--r--net/bootp.h2
-rw-r--r--net/eth-uclass.c2
-rw-r--r--net/link_local.c2
-rw-r--r--net/lwip/dhcp.c1
-rw-r--r--net/lwip/dns.c1
-rw-r--r--net/lwip/net-lwip.c1
-rw-r--r--net/lwip/tftp.c1
-rw-r--r--net/lwip/wget.c1
-rw-r--r--net/pcap.c1
-rw-r--r--net/tftp.c4
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: