summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README18
-rw-r--r--net/bootp.c48
2 files changed, 58 insertions, 8 deletions
diff --git a/README b/README
index 1d713596ec..d1b4eed020 100644
--- a/README
+++ b/README
@@ -2036,6 +2036,24 @@ CBFS (Coreboot Filesystem) support
4th and following
BOOTP requests: delay 0 ... 8 sec
+ CONFIG_BOOTP_ID_CACHE_SIZE
+
+ BOOTP packets are uniquely identified using a 32-bit ID. The
+ server will copy the ID from client requests to responses and
+ U-Boot will use this to determine if it is the destination of
+ an incoming response. Some servers will check that addresses
+ aren't in use before handing them out (usually using an ARP
+ ping) and therefore take up to a few hundred milliseconds to
+ respond. Network congestion may also influence the time it
+ takes for a response to make it back to the client. If that
+ time is too long, U-Boot will retransmit requests. In order
+ to allow earlier responses to still be accepted after these
+ retransmissions, U-Boot's BOOTP client keeps a small cache of
+ IDs. The CONFIG_BOOTP_ID_CACHE_SIZE controls the size of this
+ cache. The default is to keep IDs for up to four outstanding
+ requests. Increasing this will allow U-Boot to accept offers
+ from a BOOTP client in networks with unusually high latency.
+
- DHCP Advanced Options:
You can fine tune the DHCP functionality by defining
CONFIG_BOOTP_* symbols:
diff --git a/net/bootp.c b/net/bootp.c
index a4f6db570c..d4c86cf179 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -47,7 +47,12 @@
#define CONFIG_DHCP_MIN_EXT_LEN 64
#endif
-ulong BootpID;
+#ifndef CONFIG_BOOTP_ID_CACHE_SIZE
+#define CONFIG_BOOTP_ID_CACHE_SIZE 4
+#endif
+
+ulong bootp_ids[CONFIG_BOOTP_ID_CACHE_SIZE];
+unsigned int bootp_num_ids;
int BootpTry;
ulong bootp_start;
ulong bootp_timeout;
@@ -77,6 +82,30 @@ static char *dhcpmsg2str(int type)
#endif
#endif
+static void bootp_add_id(ulong id)
+{
+ if (bootp_num_ids >= ARRAY_SIZE(bootp_ids)) {
+ size_t size = sizeof(bootp_ids) - sizeof(id);
+
+ memmove(bootp_ids, &bootp_ids[1], size);
+ bootp_ids[bootp_num_ids - 1] = id;
+ } else {
+ bootp_ids[bootp_num_ids] = id;
+ bootp_num_ids++;
+ }
+}
+
+static bool bootp_match_id(ulong id)
+{
+ unsigned int i;
+
+ for (i = 0; i < bootp_num_ids; i++)
+ if (bootp_ids[i] == id)
+ return true;
+
+ return false;
+}
+
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
{
struct Bootp_t *bp = (struct Bootp_t *) pkt;
@@ -96,7 +125,7 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
retval = -4;
else if (bp->bp_hlen != HWL_ETHER)
retval = -5;
- else if (NetReadLong((ulong *)&bp->bp_id) != BootpID)
+ else if (!bootp_match_id(NetReadLong((ulong *)&bp->bp_id)))
retval = -6;
debug("Filtering pkt = %d\n", retval);
@@ -351,8 +380,8 @@ BootpTimeout(void)
#endif
} else {
bootp_timeout *= 2;
- if (bootp_timeout > 1000)
- bootp_timeout = 1000;
+ if (bootp_timeout > 2000)
+ bootp_timeout = 2000;
NetSetTimeout(bootp_timeout, BootpTimeout);
BootpRequest();
}
@@ -616,9 +645,10 @@ static int BootpExtended(u8 *e)
void BootpReset(void)
{
+ bootp_num_ids = 0;
BootpTry = 0;
bootp_start = get_timer(0);
- bootp_timeout = 10;
+ bootp_timeout = 250;
}
void
@@ -631,6 +661,7 @@ BootpRequest(void)
#ifdef CONFIG_BOOTP_RANDOM_DELAY
ulong rand_ms;
#endif
+ ulong BootpID;
bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start");
#if defined(CONFIG_CMD_DHCP)
@@ -699,7 +730,8 @@ BootpRequest(void)
| ((ulong)NetOurEther[4] << 8)
| (ulong)NetOurEther[5];
BootpID += get_timer(0);
- BootpID = htonl(BootpID);
+ BootpID = htonl(BootpID);
+ bootp_add_id(BootpID);
NetCopyLong(&bp->bp_id, &BootpID);
/*
@@ -960,8 +992,8 @@ DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
/* Store net params from reply */
BootpCopyNetParams(bp);
dhcp_state = BOUND;
- printf("DHCP client bound to address %pI4\n",
- &NetOurIP);
+ printf("DHCP client bound to address %pI4 (%lu ms)\n",
+ &NetOurIP, get_timer(bootp_start));
bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP,
"bootp_stop");
OpenPOWER on IntegriCloud