X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=net%2Fbootp.c;h=81066015f1c2ed28a4fb0ea1ec4bbeecec08047f;hb=f94a1bed07e2af1c46ddcf2046cddd979ebfd994;hp=c9b8349b3650b873351dd44b86eb4386a495e285;hpb=d978780b2e676c005460cd561f4f15b5220bdf49;p=oweals%2Fu-boot.git diff --git a/net/bootp.c b/net/bootp.c index c9b8349b36..81066015f1 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -23,12 +23,22 @@ #define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */ -#define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */ +/* + * The timeout for the initial BOOTP/DHCP request used to be described by a + * counter of fixed-length timeout periods. TIMEOUT_COUNT represents + * that counter + * + * Now that the timeout periods are variable (exponential backoff and retry) + * we convert the timeout count to the absolute time it would have take to + * execute that many retries, and keep sending retry packets until that time + * is reached. + */ #ifndef CONFIG_NET_RETRY_COUNT # define TIMEOUT_COUNT 5 /* # of timeouts before giving up */ #else # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) #endif +#define TIMEOUT_MS ((3 + (TIMEOUT_COUNT * 5)) * 1000) #define PORT_BOOTPS 67 /* BOOTP server UDP port */ #define PORT_BOOTPC 68 /* BOOTP client UDP port */ @@ -37,13 +47,20 @@ #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; #if defined(CONFIG_CMD_DHCP) -dhcp_state_t dhcp_state = INIT; -unsigned long dhcp_leasetime; -IPaddr_t NetDHCPServerIP; +static dhcp_state_t dhcp_state = INIT; +static unsigned long dhcp_leasetime; +static IPaddr_t NetDHCPServerIP; static void DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len); @@ -65,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; @@ -84,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); @@ -104,8 +145,6 @@ static void BootpCopyNetParams(struct Bootp_t *bp) if (tmp_ip != 0) NetCopyIP(&NetServerIP, &bp->bp_siaddr); memcpy(NetServerEther, ((struct ethernet_hdr *)NetRxPacket)->et_src, 6); -#endif - NetCopyIP(&NetOurIP, &bp->bp_yiaddr); if (strlen(bp->bp_file) > 0) copy_filename(BootFile, bp->bp_file, sizeof(BootFile)); @@ -117,6 +156,8 @@ static void BootpCopyNetParams(struct Bootp_t *bp) */ if (*BootFile) setenv("bootfile", BootFile); +#endif + NetCopyIP(&NetOurIP, &bp->bp_yiaddr); } static int truncate_sz(const char *name, int maxlen, int curlen) @@ -327,20 +368,34 @@ BootpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, static void BootpTimeout(void) { - if (BootpTry >= TIMEOUT_COUNT) { + ulong time_taken = get_timer(bootp_start); + + if (time_taken >= TIMEOUT_MS) { #ifdef CONFIG_BOOTP_MAY_FAIL - puts("\nRetry count exceeded\n"); + puts("\nRetry time exceeded\n"); net_set_state(NETLOOP_FAIL); #else - puts("\nRetry count exceeded; starting again\n"); + puts("\nRetry time exceeded; starting again\n"); NetStartAgain(); #endif } else { - NetSetTimeout(TIMEOUT, BootpTimeout); + bootp_timeout *= 2; + if (bootp_timeout > 2000) + bootp_timeout = 2000; + NetSetTimeout(bootp_timeout, BootpTimeout); BootpRequest(); } } +#define put_vci(e, str) \ + do { \ + size_t vci_strlen = strlen(str); \ + *e++ = 60; /* Vendor Class Identifier */ \ + *e++ = vci_strlen; \ + memcpy(e, str, vci_strlen); \ + e += vci_strlen; \ + } while (0) + /* * Initialize BOOTP extension fields in the request. */ @@ -352,7 +407,6 @@ static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, u8 *cnt; #if defined(CONFIG_BOOTP_PXE) char *uuid; - size_t vci_strlen; u16 clientarch; #endif @@ -431,18 +485,16 @@ static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, *e++ = 17; *e++ = 0; /* type 0 - UUID */ - uuid_str_to_bin(uuid, e); + uuid_str_to_bin(uuid, e, UUID_STR_FORMAT_STD); e += 16; } else { printf("Invalid pxeuuid: %s\n", uuid); } } +#endif - *e++ = 60; /* Vendor Class Identifier */ - vci_strlen = strlen(CONFIG_BOOTP_VCI_STRING); - *e++ = vci_strlen; - memcpy(e, CONFIG_BOOTP_VCI_STRING, vci_strlen); - e += vci_strlen; +#ifdef CONFIG_BOOTP_VCI_STRING + put_vci(e, CONFIG_BOOTP_VCI_STRING); #endif #if defined(CONFIG_BOOTP_VENDOREX) @@ -529,6 +581,15 @@ static int BootpExtended(u8 *e) *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff; #endif +#if defined(CONFIG_BOOTP_VCI_STRING) || \ + (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING)) +#ifdef CONFIG_SPL_BUILD + put_vci(e, CONFIG_SPL_NET_VCI_STRING); +#else + put_vci(e, CONFIG_BOOTP_VCI_STRING); +#endif +#endif + #if defined(CONFIG_BOOTP_SUBNETMASK) *e++ = 1; /* Subnet mask request */ *e++ = 4; @@ -582,6 +643,14 @@ static int BootpExtended(u8 *e) } #endif +void BootpReset(void) +{ + bootp_num_ids = 0; + BootpTry = 0; + bootp_start = get_timer(0); + bootp_timeout = 250; +} + void BootpRequest(void) { @@ -590,8 +659,9 @@ BootpRequest(void) int extlen, pktlen, iplen; int eth_hdr_size; #ifdef CONFIG_BOOTP_RANDOM_DELAY - ulong i, rand_ms; + ulong rand_ms; #endif + ulong BootpID; bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start"); #if defined(CONFIG_CMD_DHCP) @@ -608,8 +678,7 @@ BootpRequest(void) rand_ms = rand() >> 19; printf("Random delay: %ld ms...\n", rand_ms); - for (i = 0; i < rand_ms; i++) - udelay(1000); /*Wait 1ms*/ + mdelay(rand_ms); #endif /* CONFIG_BOOTP_RANDOM_DELAY */ @@ -661,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); /* @@ -671,7 +741,7 @@ BootpRequest(void) iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen; pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen; net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen); - NetSetTimeout(SELECT_TIMEOUT, BootpTimeout); + NetSetTimeout(bootp_timeout, BootpTimeout); #if defined(CONFIG_CMD_DHCP) dhcp_state = SELECTING; @@ -728,6 +798,8 @@ static void DhcpOptionsProcess(uchar *popt, struct Bootp_t *bp) memcpy(&NetOurRootPath, popt + 2, size); NetOurRootPath[size] = 0; break; + case 28: /* Ignore Broadcast Address Option */ + break; #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER) case 42: /* NTP server IP */ NetCopyIP(&NetNtpServerIP, (popt + 2)); @@ -902,7 +974,7 @@ DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, htonl(BOOTP_VENDOR_MAGIC)) DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp); - NetSetTimeout(TIMEOUT, BootpTimeout); + NetSetTimeout(5000, BootpTimeout); DhcpSendRequestPkt(bp); #ifdef CONFIG_SYS_BOOTFILE_PREFIX } @@ -920,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");