Initial IPv6 support
Subsystems (2)
cover Initial IPv6 support
Here's something simple to get started. IP6addr_t is added as a typedef (for consistency with IPaddr_t). I ended up borrowing and adapting the vsprintf code from Linux.
Here is an example of the printf formatting
With this code
IP6addr_t addr6 = {.u6_addr16[0] = 0x3ffe,
.u6_addr16[1] = 0x1234,
.u6_addr16[7] = 0x0001};
IPaddr_t addr4 = 0x7f000001;
printf("addr6=%pi6\n", &addr6);
printf("addr6=%pI6\n", &addr6);
printf("addr6=%pI6c\n", &addr6);
printf("addr=%pI4\n", &addr4);We get the output
addr6=3ffe1234000000000000000000000001
addr6=3ffe:1234:0000:0000:0000:0000:0000:0001
addr6=3ffe:1234::1
addr4=127.0.0.1
My work so far on this has raised a few questions:
1) Presumably the majority of the actual V6 code would be included by a config option (CONFIG_IPV6). How far should I take that? Should the vsprintf code be conditional?
2) Our current out of tree code parallels net.c and net.h. Should I continue this for the final version or integrate it into net.[ch].
3) rxhand_f currently takes an IPaddr_t. I haven't looked at the usage of this yet but to support V6 this may need to be a new union or a void *.
(note on my split personality, I use a gmail account to post to the u-boot mailing list but since this work is being done as part of my $dayjob the author and s-o-b are using my work email address)
#####################################################################################
Scanned by MailMarshal - M86 Security's comprehensive email content security solution.
#####################################################################################
RFC PATCH 1/2 Initial net6.h
From: Chris Packham <[email protected]>
Has the definition of an IPv6 address and IPv6 header. It may make sense to separate the v4 support from net.h (or to include this in net.h).
--- include/net6.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 include/net6.h
include/net6.h new file +43 -0
@@ -0,0 +1,43 @@ +/** +* Simple IPv6 network layer implementation. +* +* Based and/or adapted from the IPv4 network layer in net.[hc] +* +* (C) Copyright 2013 Allied Telesis Labs NZ +* +* This file is released under the terms of GPL v2 and any later version. +* See the file COPYING in the root directory of the source tree for details. +*/ + +typedef union ip6addr_t { +__u8 u6_addr8[16 ]; +__u16 u6_addr16[8 ]; +__u32 u6_addr32[4 ]; +}IP6addr_t ; + +/** +* struct ipv6hdr - Internet Protocol V6 (IPv6) header. +* +* IPv6 packet header as defined in RFC xxxx. +* +* BEWARE, it is incorrect. The first 4 bits of flow_lbl +* are glued to priority now, forming "class". +*/ +struct ip6_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) +__u8 priority:4 , + version:4 ; +#elif defined(__BIG_ENDIAN_BITFIELD) +__u8 version:4 , + priority:4 ; +#else +#error "Please fix <asm/byteorder.h>" +#endif +__u8 flow_lbl[3 ]; +__u16 payload_len; +__u8 nexthdr; +__u8 hop_limit; +IP6addr_t saddr; +IP6addr_t daddr; +}; +
Signature · 6 lines
1.7.12.rc2.16.g034161a ##################################################################################### Scanned by MailMarshal - M86 Security's comprehensive email content security solution. #####################################################################################
RFC PATCH 1/2 Initial net6.h
include/net6.h line 14
Quoted 3 lines · On Wed, 16 Jan 2013 23:01:26 +1300 Chris Packham <[email protected]>…
include/net6.h new file +3
-0+typedef union ip6addr_t { + __u8 u6_addr8[16]; + __u16 u6_addr16[8];
__be16, for use with sparse.
include/net6.h line 15
Quoted 1 line
include/net6.h new file +1
-0+__u32 u6_addr32[4 ];
__be32
Quoted 1 line
+}
IP6addr_t;
Kim
RFC PATCH 2/2 lib/vsprintf.c: add IPv6 compressed format %pI6c
In reply to Chris PackhamFrom: Chris Packham <[email protected]>
Add support for "human friendly" IPv6 address representations as specified in
http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
This code has been adapted from Linux kernel with minimal modification.
--- lib/vsprintf.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 128 insertions(+), 20 deletions(-)
lib/vsprintf.c +128 -20
@@ -23,6 +23,7 @@#endif #include <div64.h> +#include <net6.h> #define noinline __attribute__((noinline))/* some reluctance to put this into a new limits.h, so it is here */
@@ -276,6 +277,7 @@ static noinline char *put_dec(char *buf, u64 num)#define LEFT 16/* left justified */ #define SMALL 32/* Must be 32 == 0x20 */ #define SPECIAL 64/* 0x */ +#define COMPRESSED 128/* use compressed format */ #ifdef CONFIG_SYS_VSNPRINTF /*
@@ -430,12 +432,112 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, flags & ~SPECIAL); } -static char *ip6_addr_string (char *buf,char *end,u8 *addr,int field_width, -int precision,int flags) +static char *ip4_string (char *p,u8 *addr) +{ +char temp[3 ];/* hold each IP quad in reverse order */ +int i, digits; + +for (i =0 ; i <4 ; i++) { + digits =put_dec_trunc (temp, addr[i]) - temp; +/* reverse the digits in the quad */ +while (digits--) + *p++ = temp[digits]; +if (i !=3 ) + *p++ ='.' ; + } + *p ='\0' ; + +return p; +} + +static char *ip6_compressed_string (char *p,u8 *addr) +{ +int i, j, range; +unsigned char zerolength[8 ]; +int longest =1 ; +int colonpos =-1 ; +u16 word; +u8 hi, lo; +int needcolon =0 ; +int useIPv4; +IP6addr_t in6; + +memcpy (&in6, addr,sizeof (IP6addr_t)); + +/* TODO: v4 mapped detection. Might be overkill for a bootloader */ +#if 0 + useIPv4 =ipv6_addr_v4mapped (&in6) ||ipv6_addr_is_isatap (&in6); +#else + useIPv4 =0 ; +#endif + +memset (zerolength,0 ,sizeof (zerolength)); + +if (useIPv4) + range =6 ; +else + range =8 ; + +/* find position of longest 0 run */ +for (i =0 ; i < range; i++) { +for (j = i; j < range; j++) { +if (in6.u6_addr16[j] !=0 ) +break ; + zerolength[i]++; + } + } +for (i =0 ; i < range; i++) { +if (zerolength[i] > longest) { + longest = zerolength[i]; + colonpos = i; + } + } +if (longest ==1 )/* don't compress a single 0 */ + colonpos =-1 ; + +/* emit address */ +for (i =0 ; i < range; i++) { +if (i == colonpos) { +if (needcolon || i ==0 ) + *p++ =':' ; + *p++ =':' ; + needcolon =0 ; + i += longest -1 ; +continue ; + } +if (needcolon) { + *p++ =':' ; + needcolon =0 ; + } +/* hex u16 without leading 0s */ + word =ntohs (in6.u6_addr16[i]); + hi = word >>8 ; + lo = word &0xff ; +if (hi) { +if (hi >0x0f ) + p =pack_hex_byte (p, hi); +else + *p++ =hex_asc_lo (hi); + p =pack_hex_byte (p, lo); + }else if (lo >0x0f ) + p =pack_hex_byte (p, lo); +else + *p++ =hex_asc_lo (lo); + needcolon =1 ; + } + +if (useIPv4) { +if (needcolon) + *p++ =':' ; + p =ip4_string (p, &in6.u6_addr8[12 ]); + } + *p ='\0' ; + +return p; +} + +static char *ip6_string (char *p,u8 *addr,int flags) { -/* (8 * 4 hex digits), 7 colons and trailing zero */ -char ip6_addr[8 *5 ]; -char *p = ip6_addr;int i;for (i =0 ; i <8 ; i++) {
@@ -446,6 +548,19 @@ static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width, } *p ='\0' ; +return p; +} + +static char *ip6_addr_string (char *buf,char *end,u8 *addr,int field_width, +int precision,int flags) +{ +char ip6_addr[sizeof ("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255" )]; + +if (flags &COMPRESSED ) +ip6_compressed_string (ip6_addr, addr); +else +ip6_string (ip6_addr, addr, flags); +return string (buf, end, ip6_addr, field_width, precision, flags & ~SPECIAL ); }
@@ -453,21 +568,9 @@ static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,static char *ip4_addr_string (char *buf,char *end,u8 *addr,int field_width,int precision,int flags) { -/* (4 * 3 decimal digits), 3 dots and trailing zero */ -char ip4_addr[4 *4 ]; -char temp[3 ];/* hold each IP quad in reverse order */ -char *p = ip4_addr; -int i, digits; +char ip4_addr[sizeof ("255.255.255.255" )]; -for (i =0 ; i <4 ; i++) { - digits =put_dec_trunc (temp, addr[i]) - temp; -/* reverse the digits in the quad */ -while (digits--) - *p++ = temp[digits]; -if (i !=3 ) - *p++ ='.' ; - } - *p ='\0' ; +ip4_string (ip4_addr, addr);return string (buf, end, ip4_addr, field_width, precision, flags & ~SPECIAL );
@@ -487,6 +590,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,* decimal for v4 and colon separated network-order 16 bit hex for v6) * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is * currently the same +* - 'I6c' for IPv6 addresses printed as specified by +* http://tools.ietf.org/html/rfc5952 * * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a
@@ -517,9 +622,12 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, flags |=SPECIAL ;/* Fallthrough */ case 'I' : -if (fmt[1 ] =='6' ) +if (fmt[1 ] =='6' ) { +if (fmt[2 ] =='c' ) + flags |=COMPRESSED ;return ip6_addr_string (buf, end, ptr, field_width, precision, flags); + }if (fmt[1 ] =='4' )return ip4_addr_string (buf, end, ptr, field_width, precision, flags);
Signature · 6 lines
1.7.12.rc2.16.g034161a ##################################################################################### Scanned by MailMarshal - M86 Security's comprehensive email content security solution. #####################################################################################
cover Initial IPv6 support
In reply to Chris PackhamOn 01/16/2013 11:01 PM, Chris Packham wrote:
<snip>
Quoted 3 lines
#####################################################################################
Scanned by MailMarshal - M86 Security's comprehensive email content security solution.
#####################################################################################
Ick. Where did that come from?