public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [RFC PATCH 0/2] Initial IPv6 support
@ 2013-01-16 10:01 Chris Packham
  2013-01-16 10:01 ` [U-Boot] [RFC PATCH 1/2] Initial net6.h Chris Packham
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Chris Packham @ 2013-01-16 10:01 UTC (permalink / raw)
  To: u-boot

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. 
#####################################################################################

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [RFC PATCH 1/2] Initial net6.h
  2013-01-16 10:01 [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham
@ 2013-01-16 10:01 ` Chris Packham
  2013-01-16 22:37   ` Kim Phillips
  2013-01-16 10:01 ` [U-Boot] [RFC PATCH 2/2] lib/vsprintf.c: add IPv6 compressed format %pI6c Chris Packham
  2013-01-16 10:18 ` [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham
  2 siblings, 1 reply; 5+ messages in thread
From: Chris Packham @ 2013-01-16 10:01 UTC (permalink / raw)
  To: u-boot

From: Chris Packham <chris.packham@alliedtelesis.co.nz>

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).

Cc: Joe Hershberger <joe.hershberger@gmail.com>
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
 include/net6.h | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 include/net6.h

diff --git a/include/net6.h b/include/net6.h
new file mode 100644
index 0000000..2ef7405
--- /dev/null
+++ b/include/net6.h
@@ -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;
+};
+
-- 
1.7.12.rc2.16.g034161a


#####################################################################################
Scanned by MailMarshal - M86 Security's comprehensive email content security solution. 
#####################################################################################

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [RFC PATCH 2/2] lib/vsprintf.c: add IPv6 compressed format %pI6c
  2013-01-16 10:01 [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham
  2013-01-16 10:01 ` [U-Boot] [RFC PATCH 1/2] Initial net6.h Chris Packham
@ 2013-01-16 10:01 ` Chris Packham
  2013-01-16 10:18 ` [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham
  2 siblings, 0 replies; 5+ messages in thread
From: Chris Packham @ 2013-01-16 10:01 UTC (permalink / raw)
  To: u-boot

From: Chris Packham <chris.packham@alliedtelesis.co.nz>

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.

Cc: Joe Hershberger <joe.hershberger@gmail.com>
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
 lib/vsprintf.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 3c432f8..ae992dc 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -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);
-- 
1.7.12.rc2.16.g034161a


#####################################################################################
Scanned by MailMarshal - M86 Security's comprehensive email content security solution. 
#####################################################################################

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [RFC PATCH 0/2] Initial IPv6 support
  2013-01-16 10:01 [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham
  2013-01-16 10:01 ` [U-Boot] [RFC PATCH 1/2] Initial net6.h Chris Packham
  2013-01-16 10:01 ` [U-Boot] [RFC PATCH 2/2] lib/vsprintf.c: add IPv6 compressed format %pI6c Chris Packham
@ 2013-01-16 10:18 ` Chris Packham
  2 siblings, 0 replies; 5+ messages in thread
From: Chris Packham @ 2013-01-16 10:18 UTC (permalink / raw)
  To: u-boot

On 01/16/2013 11:01 PM, Chris Packham wrote:

<snip>

> #####################################################################################
> Scanned by MailMarshal - M86 Security's comprehensive email content security solution. 
> #####################################################################################

Ick. Where did that come from?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [RFC PATCH 1/2] Initial net6.h
  2013-01-16 10:01 ` [U-Boot] [RFC PATCH 1/2] Initial net6.h Chris Packham
@ 2013-01-16 22:37   ` Kim Phillips
  0 siblings, 0 replies; 5+ messages in thread
From: Kim Phillips @ 2013-01-16 22:37 UTC (permalink / raw)
  To: u-boot

On Wed, 16 Jan 2013 23:01:26 +1300
Chris Packham <judge.packham@gmail.com> wrote:

> +typedef union ip6addr_t {
> +	__u8	u6_addr8[16];
> +	__u16	u6_addr16[8];

__be16, for use with sparse.

> +	__u32	u6_addr32[4];

__be32

> +} IP6addr_t;

Kim

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-01-16 22:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-16 10:01 [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham
2013-01-16 10:01 ` [U-Boot] [RFC PATCH 1/2] Initial net6.h Chris Packham
2013-01-16 22:37   ` Kim Phillips
2013-01-16 10:01 ` [U-Boot] [RFC PATCH 2/2] lib/vsprintf.c: add IPv6 compressed format %pI6c Chris Packham
2013-01-16 10:18 ` [U-Boot] [RFC PATCH 0/2] Initial IPv6 support Chris Packham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox