X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=net%2Fbootp.c;h=fe143201c0f3f509b59219cc67e68e6f50dd3ec8;hb=c4baf1ac6604cb90b84bfb764f7dd484bca6d28e;hp=fdb97cb56252521237baf7b2f02c94f42724cd8d;hpb=f2c8d7f591e28d3437155c7a6eae8c8d9e3fe552;p=karo-tx-uboot.git diff --git a/net/bootp.c b/net/bootp.c index fdb97cb562..fe143201c0 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -17,18 +17,28 @@ #ifdef CONFIG_STATUS_LED #include #endif -#ifdef CONFIG_BOOTP_RANDOM_DELAY +#if defined(CONFIG_BOOTP_RANDOM_DELAY) || defined(CONFIG_BOOTP_RANDOM_ID) #include "net_rand.h" #endif #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,15 +47,22 @@ #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) 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); +static struct in_addr dhcp_server_ip; +static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, + unsigned src, unsigned len); /* For Debug */ #if 0 @@ -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); @@ -98,25 +139,26 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len) static void BootpCopyNetParams(struct Bootp_t *bp) { #if !defined(CONFIG_BOOTP_SERVERIP) - IPaddr_t tmp_ip; + struct in_addr tmp_ip; - NetCopyIP(&tmp_ip, &bp->bp_siaddr); - if (tmp_ip != 0) - NetCopyIP(&NetServerIP, &bp->bp_siaddr); + net_copy_ip(&tmp_ip, &bp->bp_siaddr); + if (tmp_ip.s_addr != 0) + net_copy_ip(&net_server_ip, &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)); + copy_filename(net_boot_file_name, bp->bp_file, + sizeof(net_boot_file_name)); - debug("Bootfile: %s\n", BootFile); + debug("net_boot_file_name: %s\n", net_boot_file_name); /* Propagate to environment: * don't delete exising entry when BOOTP / DHCP reply does * not contain a new value */ - if (*BootFile) - setenv("bootfile", BootFile); + if (*net_boot_file_name) + setenv("bootfile", net_boot_file_name); +#endif + net_copy_ip(&net_ip, &bp->bp_yiaddr); } static int truncate_sz(const char *name, int maxlen, int curlen) @@ -138,31 +180,33 @@ static void BootpVendorFieldProcess(u8 *ext) debug("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext + 1)); - NetBootFileSize = 0; + net_boot_file_expected_size_in_blocks = 0; switch (*ext) { /* Fixed length fields */ case 1: /* Subnet mask */ - if (NetOurSubnetMask == 0) - NetCopyIP(&NetOurSubnetMask, (IPaddr_t *) (ext + 2)); + if (net_netmask.s_addr == 0) + net_copy_ip(&net_netmask, (struct in_addr *)(ext + 2)); break; case 2: /* Time offset - Not yet supported */ break; /* Variable length fields */ case 3: /* Gateways list */ - if (NetOurGatewayIP == 0) - NetCopyIP(&NetOurGatewayIP, (IPaddr_t *) (ext + 2)); + if (net_gateway.s_addr == 0) + net_copy_ip(&net_gateway, (struct in_addr *)(ext + 2)); break; case 4: /* Time server - Not yet supported */ break; case 5: /* IEN-116 name server - Not yet supported */ break; case 6: - if (NetOurDNSIP == 0) - NetCopyIP(&NetOurDNSIP, (IPaddr_t *) (ext + 2)); + if (net_dns_server.s_addr == 0) + net_copy_ip(&net_dns_server, + (struct in_addr *)(ext + 2)); #if defined(CONFIG_BOOTP_DNS2) - if ((NetOurDNS2IP == 0) && (size > 4)) - NetCopyIP(&NetOurDNS2IP, (IPaddr_t *) (ext + 2 + 4)); + if ((net_dns_server2.s_addr == 0) && (size > 4)) + net_copy_ip(&net_dns_server2, + (struct in_addr *)(ext + 2 + 4)); #endif break; case 7: /* Log server - Not yet supported */ @@ -185,9 +229,11 @@ static void BootpVendorFieldProcess(u8 *ext) break; case 13: /* Boot file size */ if (size == 2) - NetBootFileSize = ntohs(*(ushort *) (ext + 2)); + net_boot_file_expected_size_in_blocks = + ntohs(*(ushort *)(ext + 2)); else if (size == 4) - NetBootFileSize = ntohl(*(ulong *) (ext + 2)); + net_boot_file_expected_size_in_blocks = + ntohl(*(ulong *)(ext + 2)); break; case 14: /* Merit dump file - Not yet supported */ break; @@ -221,7 +267,7 @@ static void BootpVendorFieldProcess(u8 *ext) break; #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER) case 42: /* NTP server IP */ - NetCopyIP(&NetNtpServerIP, (IPaddr_t *) (ext + 2)); + net_copy_ip(&net_ntp_server, (struct in_addr *)(ext + 2)); break; #endif /* Application layer fields */ @@ -254,14 +300,15 @@ static void BootpVendorProcess(u8 *ext, int size) } debug("[BOOTP] Received fields:\n"); - if (NetOurSubnetMask) - debug("NetOurSubnetMask : %pI4\n", &NetOurSubnetMask); + if (net_netmask.s_addr) + debug("net_netmask : %pI4\n", &net_netmask); - if (NetOurGatewayIP) - debug("NetOurGatewayIP : %pI4", &NetOurGatewayIP); + if (net_gateway.s_addr) + debug("net_gateway : %pI4", &net_gateway); - if (NetBootFileSize) - debug("NetBootFileSize : %d\n", NetBootFileSize); + if (net_boot_file_expected_size_in_blocks) + debug("net_boot_file_expected_size_in_blocks : %d\n", + net_boot_file_expected_size_in_blocks); if (NetOurHostName[0]) debug("NetOurHostName : %s\n", NetOurHostName); @@ -272,21 +319,17 @@ static void BootpVendorProcess(u8 *ext, int size) if (NetOurNISDomain[0]) debug("NetOurNISDomain : %s\n", NetOurNISDomain); - if (NetBootFileSize) - debug("NetBootFileSize: %d\n", NetBootFileSize); - #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER) - if (NetNtpServerIP) - debug("NetNtpServerIP : %pI4\n", &NetNtpServerIP); + if (net_ntp_server) + debug("net_ntp_server : %pI4\n", &net_ntp_server); #endif } /* * Handle a BOOTP received packet. */ -static void -BootpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, - unsigned len) +static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip, + unsigned src, unsigned len) { struct Bootp_t *bp; @@ -327,16 +370,21 @@ 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(); } } @@ -354,8 +402,8 @@ BootpTimeout(void) * Initialize BOOTP extension fields in the request. */ #if defined(CONFIG_CMD_DHCP) -static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, - IPaddr_t RequestedIP) +static int dhcp_extended(u8 *e, int message_type, struct in_addr server_ip, + struct in_addr requested_ip) { u8 *start = e; u8 *cnt; @@ -385,8 +433,8 @@ static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 8; *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff; - if (ServerID) { - int tmp = ntohl(ServerID); + if (server_ip.s_addr) { + int tmp = ntohl(server_ip.s_addr); *e++ = 54; /* ServerID */ *e++ = 4; @@ -396,8 +444,8 @@ static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, *e++ = tmp & 0xff; } - if (RequestedIP) { - int tmp = ntohl(RequestedIP); + if (requested_ip.s_addr) { + int tmp = ntohl(requested_ip.s_addr); *e++ = 50; /* Requested IP */ *e++ = 4; @@ -515,7 +563,7 @@ static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, /* * Warning: no field size check - change CONFIG_BOOTP_* at your own risk! */ -static int BootpExtended(u8 *e) +static int bootp_extended(u8 *e) { u8 *start = e; @@ -597,6 +645,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) { @@ -607,6 +663,9 @@ BootpRequest(void) #ifdef CONFIG_BOOTP_RANDOM_DELAY ulong rand_ms; #endif + ulong BootpID; + struct in_addr zero_ip; + struct in_addr bcast_ip; bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start"); #if defined(CONFIG_CMD_DHCP) @@ -652,30 +711,37 @@ BootpRequest(void) bp->bp_hlen = HWL_ETHER; bp->bp_hops = 0; bp->bp_secs = htons(get_timer(0) / 1000); - NetWriteIP(&bp->bp_ciaddr, 0); - NetWriteIP(&bp->bp_yiaddr, 0); - NetWriteIP(&bp->bp_siaddr, 0); - NetWriteIP(&bp->bp_giaddr, 0); + zero_ip.s_addr = 0; + net_write_ip(&bp->bp_ciaddr, zero_ip); + net_write_ip(&bp->bp_yiaddr, zero_ip); + net_write_ip(&bp->bp_siaddr, zero_ip); + net_write_ip(&bp->bp_giaddr, zero_ip); memcpy(bp->bp_chaddr, NetOurEther, 6); - copy_filename(bp->bp_file, BootFile, sizeof(bp->bp_file)); + copy_filename(bp->bp_file, net_boot_file_name, sizeof(bp->bp_file)); /* Request additional information from the BOOTP/DHCP server */ #if defined(CONFIG_CMD_DHCP) - extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0); + extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, zero_ip, + zero_ip); #else - extlen = BootpExtended((u8 *)bp->bp_vend); + 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. */ +#ifdef CONFIG_BOOTP_RANDOM_ID + BootpID = rand(); +#else BootpID = ((ulong)NetOurEther[2] << 24) | ((ulong)NetOurEther[3] << 16) | ((ulong)NetOurEther[4] << 8) | (ulong)NetOurEther[5]; BootpID += get_timer(0); - BootpID = htonl(BootpID); + BootpID = htonl(BootpID); + bootp_add_id(BootpID); +#endif NetCopyLong(&bp->bp_id, &BootpID); /* @@ -684,14 +750,15 @@ 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); + bcast_ip.s_addr = 0xFFFFFFFFL; + net_set_udp_header(iphdr, bcast_ip, PORT_BOOTPS, PORT_BOOTPC, iplen); + NetSetTimeout(bootp_timeout, BootpTimeout); #if defined(CONFIG_CMD_DHCP) dhcp_state = SELECTING; - net_set_udp_handler(DhcpHandler); + net_set_udp_handler(dhcp_handler); #else - net_set_udp_handler(BootpHandler); + net_set_udp_handler(bootp_handler); #endif NetSendPacket(NetTxPacket, pktlen); } @@ -709,7 +776,7 @@ static void DhcpOptionsProcess(uchar *popt, struct Bootp_t *bp) oplen = *(popt + 1); switch (*popt) { case 1: - NetCopyIP(&NetOurSubnetMask, (popt + 2)); + net_copy_ip(&net_netmask, (popt + 2)); break; #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) case 2: /* Time offset */ @@ -719,13 +786,13 @@ static void DhcpOptionsProcess(uchar *popt, struct Bootp_t *bp) break; #endif case 3: - NetCopyIP(&NetOurGatewayIP, (popt + 2)); + net_copy_ip(&net_gateway, (popt + 2)); break; case 6: - NetCopyIP(&NetOurDNSIP, (popt + 2)); + net_copy_ip(&net_dns_server, (popt + 2)); #if defined(CONFIG_BOOTP_DNS2) if (*(popt + 1) > 4) - NetCopyIP(&NetOurDNS2IP, (popt + 2 + 4)); + net_copy_ip(&net_dns_server2, (popt + 2 + 4)); #endif break; case 12: @@ -746,7 +813,7 @@ static void DhcpOptionsProcess(uchar *popt, struct Bootp_t *bp) break; #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER) case 42: /* NTP server IP */ - NetCopyIP(&NetNtpServerIP, (popt + 2)); + net_copy_ip(&net_ntp_server, (popt + 2)); break; #endif case 51: @@ -755,7 +822,7 @@ static void DhcpOptionsProcess(uchar *popt, struct Bootp_t *bp) case 53: /* Ignore Message Type Option */ break; case 54: - NetCopyIP(&NetDHCPServerIP, (popt + 2)); + net_copy_ip(&dhcp_server_ip, (popt + 2)); break; case 58: /* Ignore Renewal Time Option */ break; @@ -822,7 +889,9 @@ static void DhcpSendRequestPkt(struct Bootp_t *bp_offer) struct Bootp_t *bp; int pktlen, iplen, extlen; int eth_hdr_size; - IPaddr_t OfferedIP; + struct in_addr offered_ip; + struct in_addr zero_ip; + struct in_addr bcast_ip; debug("DhcpSendRequestPkt: Sending DHCPREQUEST\n"); pkt = NetTxPacket; @@ -847,7 +916,8 @@ static void DhcpSendRequestPkt(struct Bootp_t *bp_offer) * RFC3046 requires Relay Agents to discard packets with * nonzero and offered giaddr */ - NetWriteIP(&bp->bp_giaddr, 0); + zero_ip.s_addr = 0; + net_write_ip(&bp->bp_giaddr, zero_ip); memcpy(bp->bp_chaddr, NetOurEther, 6); @@ -862,13 +932,14 @@ static void DhcpSendRequestPkt(struct Bootp_t *bp_offer) */ /* Copy offered IP into the parameters request list */ - NetCopyIP(&OfferedIP, &bp_offer->bp_yiaddr); - extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_REQUEST, - NetDHCPServerIP, OfferedIP); + net_copy_ip(&offered_ip, &bp_offer->bp_yiaddr); + extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST, + dhcp_server_ip, offered_ip); 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); + bcast_ip.s_addr = 0xFFFFFFFFL; + net_set_udp_header(iphdr, bcast_ip, PORT_BOOTPS, PORT_BOOTPC, iplen); #ifdef CONFIG_BOOTP_DHCP_REQUEST_DELAY udelay(CONFIG_BOOTP_DHCP_REQUEST_DELAY); @@ -880,9 +951,8 @@ static void DhcpSendRequestPkt(struct Bootp_t *bp_offer) /* * Handle DHCP received packets. */ -static void -DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, - unsigned len) +static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, + unsigned src, unsigned len) { struct Bootp_t *bp = (struct Bootp_t *)pkt; @@ -918,7 +988,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 } @@ -936,8 +1006,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", + &net_ip, get_timer(bootp_start)); bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop");