On Mon, Nov 9, 2015 at 1:38 AM, Chris Packham <judge.pack...@gmail.com> wrote: > Add support for UDP/TFTP over IPv6. To support specifying an server IPv6 > address in the command square brackets must be used to separate the > address from the filename. e.g > tftpboot6 [2001:db8::1]:zImage > > Signed-off-by: Chris Packham <judge.pack...@gmail.com> > --- > > Changes in v2: None
Aren't the square brackets new? > common/Kconfig | 9 ++++++++ > common/cmd_net.c | 13 ++++++++++++ > include/net.h | 2 +- > include/net6.h | 4 ++++ > net/net.c | 3 +++ > net/net6.c | 64 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/tftp.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 7 files changed, 152 insertions(+), 1 deletion(-) > > diff --git a/common/Kconfig b/common/Kconfig > index b1effc6..5914328 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -400,6 +400,15 @@ config CMD_NET > bootp - boot image via network using BOOTP/TFTP protocol > tftpboot - boot image via network using TFTP protocol > > +config CMD_NET6 > + bool "ipv6 commands" > + select NET > + select NET6 > + default n > + help > + IPv6 network commands > + tftpboot6 - boot image via network using TFTP protocol > + Wouldn't ping6 be considered a command? Why is this not added in an earlier patch to allow for ping6? It seems like ping6 would depend on CMD_NET6. Also, it seems like tftp6 should be behind its own CMD_TFTP6 token, since it surely must be optional. Maybe we want it to be enabled by default, but it should be possible to disable. I think you'll need to update the documentation patch as a result. > config CMD_TFTPPUT > bool "tftp put" > help > diff --git a/common/cmd_net.c b/common/cmd_net.c > index 271f91d..47b56ee 100644 > --- a/common/cmd_net.c > +++ b/common/cmd_net.c > @@ -42,6 +42,19 @@ U_BOOT_CMD( > "[loadAddress] [[hostIPaddr:]bootfilename]" > ); > > +#ifdef CONFIG_CMD_NET6 > +int do_tftpb6(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + return netboot_common(TFTP6, cmdtp, argc, argv); > +} > + > +U_BOOT_CMD( > + tftpboot6, 3, 1, do_tftpb6, > + "boot image via network using TFTP protocol", > + "[loadAddress] [[hostIP6Addr]:][bootfilename]" > +); > +#endif > + > #ifdef CONFIG_CMD_TFTPPUT > int do_tftpput(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > { > diff --git a/include/net.h b/include/net.h > index 6a9832c..69e6a17 100644 > --- a/include/net.h > +++ b/include/net.h > @@ -525,7 +525,7 @@ extern int net_restart_wrap; /* Tried all > network devices */ > > enum proto_t { > BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP, NETCONS, > - SNTP, TFTPSRV, TFTPPUT, LINKLOCAL > + SNTP, TFTPSRV, TFTPPUT, TFTP6, LINKLOCAL > }; > > extern char net_boot_file_name[1024];/* Boot File name */ > diff --git a/include/net6.h b/include/net6.h > index ff97c39..7ae1777 100644 > --- a/include/net6.h > +++ b/include/net6.h > @@ -246,6 +246,10 @@ void ping6_start(void); > void ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, > int len); > > +/* Transmit UDP packet using IPv6, performing neighbour discovery if needed > */ > +int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, > + int dport, int sport, int len); > + > /* handler for incoming IPv6 echo packet */ > void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, > int len); > diff --git a/net/net.c b/net/net.c > index ca24673..2b0d17e 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -453,6 +453,9 @@ restart: > #ifdef CONFIG_CMD_TFTPPUT > case TFTPPUT: > #endif > +#ifdef CONFIG_CMD_NET6 > + case TFTP6: > +#endif > /* always use ARP to get server ethernet address */ > tftp_start(protocol); > break; > diff --git a/net/net6.c b/net/net6.c > index 8f0c721..5b8a003 100644 > --- a/net/net6.c > +++ b/net/net6.c > @@ -342,6 +342,50 @@ ip6_add_hdr(uchar *xip, struct in6_addr *src, struct > in6_addr *dest, > return sizeof(struct ip6_hdr); > } > > +int > +net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, int > sport, int len) > +{ > + uchar *pkt; > + struct udp_hdr *udp; > + > + udp = (struct udp_hdr *)((uchar *)net_tx_packet + net_eth_hdr_size() > + IP6_HDR_SIZE); > + > + udp->udp_dst = htons(dport); > + udp->udp_src = htons(sport); > + udp->udp_len = htons(len + UDP_HDR_SIZE); > + /* checksum */ > + udp->udp_xsum = 0; > + udp->udp_xsum = csum_ipv6_magic(&net_ip6, dest, len + UDP_HDR_SIZE, > + IPPROTO_UDP, csum_partial((__u8 *)udp, len + UDP_HDR_SIZE, > 0)); > + > + /* if MAC address was not discovered yet, save the packet and do > neighbour discovery */ > + if (memcmp(ether, net_null_ethaddr, 6) == 0) { > + net_copy_ip6(&net_nd_sol_packet_ip6, dest); > + net_nd_packet_mac = ether; > + > + pkt = net_nd_tx_packet; > + pkt += net_set_ether(pkt, net_nd_packet_mac, PROT_IP6); > + pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len > + UDP_HDR_SIZE); > + memcpy(pkt, (uchar *)udp, len + UDP_HDR_SIZE); > + > + /* size of the waiting packet */ > + net_nd_tx_packet_size = (pkt - net_nd_tx_packet) + > UDP_HDR_SIZE + len; > + > + /* and do the neighbor solicitation */ > + net_nd_try = 1; > + net_nd_timer_start = get_timer(0); > + ndisc_request(); > + return 1; /* waiting */ > + } > + > + pkt = (uchar *)net_tx_packet; > + pkt += net_set_ether(pkt, ether, PROT_IP6); > + pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64, len + > UDP_HDR_SIZE); > + (void) eth_send(net_tx_packet, (pkt - net_tx_packet) + UDP_HDR_SIZE + > len); > + > + return 0; /* transmitted */ > +} > + > void net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) > { > struct in_addr zero_ip = {.s_addr = 0 }; > @@ -388,6 +432,26 @@ void net_ip6_handler(struct ethernet_hdr *et, struct > ip6_hdr *ip6, int len) > } > break; > > + case IPPROTO_UDP: > + udp = (struct udp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE); > + csum = udp->udp_xsum; > + hlen = ntohs(ip6->payload_len); > + udp->udp_xsum = 0; > + /* checksum */ > + udp->udp_xsum = csum_ipv6_magic(&ip6->saddr, &ip6->daddr, > + hlen, IPPROTO_UDP, csum_partial((__u8 *)udp, > hlen, 0)); > + if (csum != udp->udp_xsum) > + return; > + > + /* IP header OK. Pass the packet to the current handler. */ > + net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE + > + UDP_HDR_SIZE, > + ntohs(udp->udp_dst), > + zero_ip, > + ntohs(udp->udp_src), > + ntohs(udp->udp_len) - 8); > + break; > + > default: > return; > break; > diff --git a/net/tftp.c b/net/tftp.c > index f2889fe..aa9e6e4 100644 > --- a/net/tftp.c > +++ b/net/tftp.c > @@ -10,6 +10,7 @@ > #include <command.h> > #include <mapmem.h> > #include <net.h> > +#include <net6.h> > #include <net/tftp.h> > #include "bootp.h" > #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP > @@ -66,6 +67,9 @@ enum { > }; > > static struct in_addr tftp_remote_ip; > +#ifdef CONFIG_CMD_NET6 > +static struct in6_addr tftp_remote_ip6; > +#endif > /* The UDP port at their end */ > static int tftp_remote_port; > /* The UDP port at our end */ > @@ -94,6 +98,10 @@ static int tftp_put_final_block_sent; > #else > #define tftp_put_active 0 > #endif > +#ifdef CONFIG_CMD_NET6 > +/* 1 if using IPv6, else 0 */ > +static int tftp6_active; > +#endif > > #define STATE_SEND_RRQ 1 > #define STATE_DATA 2 > @@ -129,6 +137,8 @@ static char tftp_filename[MAX_LEN]; > #else > #define TFTP_MTU_BLOCKSIZE 1468 > #endif > +/* IPv6 adds 20 bytes extra overhead */ > +#define TFTP_MTU_BLOCKSIZE6 (TFTP_MTU_BLOCKSIZE - 20) > > static unsigned short tftp_block_size = TFTP_BLOCK_SIZE; > static unsigned short tftp_block_size_option = TFTP_MTU_BLOCKSIZE; > @@ -341,6 +351,12 @@ static void tftp_send(void) > * We will always be sending some sort of packet, so > * cobble together the packet headers now. > */ > +#ifdef CONFIG_CMD_NET6 > + if (tftp6_active) > + pkt = net_tx_packet + net_eth_hdr_size() + > + IP6_HDR_SIZE + UDP_HDR_SIZE; > + else > +#endif > pkt = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; > > switch (tftp_state) { > @@ -440,6 +456,12 @@ static void tftp_send(void) > break; > } > > +#ifdef CONFIG_CMD_NET6 > + if (tftp6_active) > + net_send_udp_packet6(net_server_ethaddr, &tftp_remote_ip6, > + tftp_remote_port, tftp_our_port, len); > + else > +#endif > net_send_udp_packet(net_server_ethaddr, tftp_remote_ip, > tftp_remote_port, tftp_our_port, len); > } > @@ -733,6 +755,10 @@ void tftp_start(enum proto_t protocol) > debug("TFTP blocksize = %i, timeout = %ld ms\n", > tftp_block_size_option, timeout_ms); > > +#ifdef CONFIG_CMD_NET6 > + tftp6_active = (protocol == TFTP6); > + tftp_remote_ip6 = net_server_ip6; > +#endif > tftp_remote_ip = net_server_ip; > if (net_boot_file_name[0] == '\0') { > sprintf(default_filename, "%02X%02X%02X%02X.img", > @@ -746,6 +772,20 @@ void tftp_start(enum proto_t protocol) > > printf("*** Warning: no boot file name; using '%s'\n", > tftp_filename); > +#ifdef CONFIG_CMD_NET6 > + } else if (tftp6_active) { > + char *s, *e; > + s = strchr(net_boot_file_name, '['); > + e = strchr(net_boot_file_name, ']'); > + if (s && e) { > + *e++ = 0; > + string_to_ip6(s + 1, &tftp_remote_ip6); > + strncpy(tftp_filename, e + 1, MAX_LEN); > + } else { > + strncpy(tftp_filename, net_boot_file_name, MAX_LEN); > + tftp_filename[MAX_LEN - 1] = 0; > + } > +#endif > } else { > char *p = strchr(net_boot_file_name, ':'); > > @@ -760,6 +800,15 @@ void tftp_start(enum proto_t protocol) > } > > printf("Using %s device\n", eth_get_name()); > +#ifdef CONFIG_CMD_NET6 > + if (tftp6_active) { > + printf("TFTP from server %pI6c; our IP address is %pI6c", > + &tftp_remote_ip6, > + &net_ip6); > + if (tftp_block_size_option > TFTP_MTU_BLOCKSIZE6) > + tftp_block_size_option = TFTP_MTU_BLOCKSIZE6; > + } else > +#endif > printf("TFTP %s server %pI4; our IP address is %pI4", > #ifdef CONFIG_CMD_TFTPPUT > protocol == TFTPPUT ? "to" : "from", > @@ -769,6 +818,15 @@ void tftp_start(enum proto_t protocol) > &tftp_remote_ip, &net_ip); > > /* Check if we need to send across this subnet */ > +#ifdef CONFIG_CMD_NET6 > + if (tftp6_active) { > + if (!ip6_addr_in_subnet(&net_ip6, &tftp_remote_ip6, > + net_prefix_length)) { > + printf("; sending through gateway %pI6c", > + &net_gateway6); This seems like it should be a debug() message, not a printf(). > + } > + } else > +#endif > if (net_gateway.s_addr && net_netmask.s_addr) { > struct in_addr our_net; > struct in_addr remote_net; > -- > 2.5.3 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot