Initial IPv6 support
Subsystems (4)
v3 cover Initial IPv6 support
From: Chris Packham <[email protected]>
Now we have something functional. With this you can do something like 'setenv ipaddr6 3ffe::2' and 'ping6 3ffe::1' should work.
I seem to have a problem that when you send a ping6 for a non-existent address that ends up stuck and the next non-ipv6 net operation tries to resolve it. I suspect this is because the pending neighbor discovery information isn't cleaned up properly.
I'm sending this out now because I'll be away at a conference next week so probably won't have any time to work on this but I did want to say "hey ping6 works". When I get back I'll start tackling tftp over ipv6.
Changes in v3:
-Fix a what should have been a glaringly obvious omission that cause
all addresses to be interpreted as 0. Made even stricter so that v6 addresses that start with numbers aren't accepted.
-return -1 with the input string is null.
Changes in v2:
- use __be16/__be32
- add ipv6_addr_v4mapped and ipv6_addr_is_isatap inline functions Changes in v3
- Add reviewed-by from Kim Phillips to "Initial net6.h"
- Add support for printing mapped and ISATAP addresses
Chris Packham (7):
Initial net6.h
lib/vsprintf.c: add IPv6 compressed format %pI6c lib/net_utils.c: make string_to_ip stricter lib/net_utils.c: add string_to_ip6 common.h: add getenv_IP6addr
tsec: enable promiscuous mode for IPv6
net: ipv6 support
common/cmd_net.c | 27 +++++ drivers/net/tsec.c | 4 + include/common.h | 6 + include/net.h | 5 +- include/net6.h | 267 ++++++++++++++++++++++++++++++++++++++++ lib/net_utils.c | 128 +++++++++++++++++++- lib/vsprintf.c | 143 +++++++++++++++++++--- net/Makefile | 6 + net/ndisc.c | 276 ++++++++++++++++++++++++++++++++++++++++++ net/ndisc.h | 29 +++++ net/net.c | 38 ++++++ net/net6.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++++ net/ping6.c | 115 ++++++++++++++++++ 13 files changed, 1366 insertions(+), 27 deletions(-) create mode 100644 include/net6.h create mode 100644 net/ndisc.c create mode 100644 net/ndisc.h create mode 100644 net/net6.c create mode 100644 net/ping6.c
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 1/7 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).
---
Changes in v3:
- add reviewed-by from Kim Phillips
Changes in v2:
- use __be16/__be32
- add ipv6_addr_v4mapped and ipv6_addr_is_isatap inline functions
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. +*/ +#ifndef __NET6_H__ +#define __NET6_H__ + +typedef union ip6addr_t { +__u8 u6_addr8[16 ]; +__be16 u6_addr16[8 ]; +__be32 u6_addr32[4 ]; +}IP6addr_t ; + +/** +* struct ipv6hdr - Internet Protocol V6 (IPv6) header. +* +* IPv6 packet header as defined in RFC 2460. +*/ +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 ]; +__be16 payload_len; +__u8 nexthdr; +__u8 hop_limit; +IP6addr_t saddr; +IP6addr_t daddr; +}; + +#endif /* __NET6_H__ */
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 2/7 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.
---
Changes in v3: None
Changes in v2:
-Add support for printing mapped and ISATAP addresses
include/net6.h | 13 ++++++ lib/vsprintf.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 20 deletions(-)
include/net6.h +13 -0
@@ -40,4 +40,17 @@ struct ip6_hdr { IP6addr_t daddr; }; +/* ::ffff:0:0/96 is reserved for v4 mapped addresses */ +static inline int ipv6_addr_v4mapped (const IP6addr_t *a) +{ +return (a->u6_addr32[0 ] | a->u6_addr32[1 ] | + (a->u6_addr32[2 ] ^htonl (0x0000ffff ))) ==0 ; +} + +/* Intra-Site Automatic Tunnel Addressing Protocol Address */ +static inline int ipv6_addr_is_isatap (const IP6addr_t *a) +{ +return (a->u6_addr32[2 ] |htonl (0x02000000 )) ==htonl (0x02005EFE ); +} +#endif /* __NET6_H__ */
lib/vsprintf.c +123 -20
189 lines not on this page · raw message
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 3/7 lib/net_utils.c: make string_to_ip stricter
In reply to Chris PackhamFrom: Chris Packham <[email protected]>
Previously values greater than 255 were implicitly truncated. Add some stricter checking to reject addresses with components >255.
With the input "1234192.168.1.1" the old behaviour would truncate the address to 192.168.1.1. New behaviour rejects the string outright and returns 0, which for the purposes of IP addresses can be considered an error.
---
Changes in v3:
-Fix a what should have been a glaringly obvious omission that cause
all addresses to be interpreted as 0. Made even stricter so that v6 addresses that start with numbers aren't accepted.
Changes in v2: None
lib/net_utils.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
lib/net_utils.c +10 -5
@@ -38,12 +38,17 @@ IPaddr_t string_to_ip(const char *s)return (0 );for (addr=0 , i=0 ; i<4 ; ++i) { -ulong val = s ?simple_strtoul (s, &e,10 ) :0 ; +ulong val =simple_strtoul (s, &e,10 ); +if (val >255 ) +return 0 ; addr <<=8 ; - addr |= (val &0xFF ); -if (s) { - s = (*e) ? e+1 : e; - } + addr |= val; +if (*e =='.' ) + s = e+1 ; +else if (*e =='\0' ) +break ; +else +return 0 ; }return (htonl (addr));
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 4/7 lib/net_utils.c: add string_to_ip6
In reply to Chris PackhamFrom: Chris Packham <[email protected]>
string_to_ip6 parses an IPv6 address from a string. Parsing v6 addresses is a bit more complicated than parsing v4 because there are a number of different formats that can be used.
---
Changes in v3:
-return -1 with the input string is null.
Changes in v2: None
include/net6.h | 3 ++ lib/net_utils.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+)
include/net6.h +3 -0
@@ -53,4 +53,7 @@ static inline int ipv6_addr_is_isatap(const IP6addr_t *a) return (a->u6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE); } +/* Convert a string to an ipv6 address */ +extern int string_to_ip6 (const char *s,IP6addr_t *addr); +#endif /* __NET6_H__ */
lib/net_utils.c +114 -0
123 lines not on this page · raw message
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 5/7 common.h: add getenv_IP6addr
In reply to Chris PackhamFrom: Chris Packham <[email protected]>
Analogous to getenv_IPaddr but for IPv6. This allows the caller to get an IP6addr_t from an environment variable.
---
Changes in v3: None
Changes in v2: None
include/common.h | 6 ++++++ lib/net_utils.c | 1 - 2 files changed, 6 insertions(+), 1 deletion(-)
include/common.h +6 -0
@@ -842,6 +842,12 @@ static inline IPaddr_t getenv_IPaddr(char *var)return string_to_ip (getenv (var)); } +#include <net6.h> +static inline int getenv_IP6addr (char *var,IP6addr_t *a) +{ +return string_to_ip6 (getenv (var), a); +} +/* * CONSOLE multiplexing. */
lib/net_utils.c +0 -1
@@ -27,7 +27,6 @@*/ #include <common.h> -#include <net6.h> #include <linux/ctype.h> IPaddr_t string_to_ip (const char *s)
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 6/7 tsec: enable promiscuous mode for IPv6
In reply to Chris PackhamFrom: Chris Packham <[email protected]>
For IPv6 neighbor discovery to operate correctly we need to register for various multicast groups (because some neighbor discovery packets are sent to various multicast addresses).
---
Currently the multicast support in the tsec driver is conditional on CONFIG_MCAST_TFTP and tsec_mcast_addr, eth_mcast_join and eth_device->mcast all disagree on what the prototype for the function to add a multicast address should be. Instead of tackling this I've taken the cowards way out and just enabled promiscuous mode which means the device sees any packet regardless of the destination address. At some point we may need to decide to properly support registering for multicast groups or just always run in promiscuous mode.
Changes in v3: None
Changes in v2: None
drivers/net/tsec.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/tsec.c +4 -0
@@ -361,6 +361,10 @@ static void startup_tsec(struct eth_device *dev)if ((SVR_MAJ (svr) ==1 ) ||IS_SVR_REV (svr,2 ,0 ))redundant_init (dev);#endif +#ifdef CONFIG_CMD_NET6 +/* Enable promiscuous mode */ +setbits_be32 (®s->rctrl,0x8 ); +#endif /* Enable Transmit and Receive */ setbits_be32 (®s->maccfg1,MACCFG1_RX_EN |MACCFG1_TX_EN );
Signature · 1 line
1.7.12.rc2.16.g034161a
RFC PATCH v3 7/7 net: ipv6 support
In reply to Chris PackhamFrom: Chris Packham <[email protected]>
Adds basic support for IPv6. Neighbor discovery and ping6 are the only things supported at the moment. Stub code exists for UDP but it is untested and unlikely to work.
---
This patch is bigger than I'd like it to be but I'm not sure how to split it up and keep the parts build able. One obvious thing would be to remove the UDP stub which I'll be updating anyway in order to support TFTP over IPv6
Changes in v3: None
Changes in v2: None
common/cmd_net.c | 27 +++++ include/net.h | 5 +- include/net6.h | 208 +++++++++++++++++++++++++++++++++ net/Makefile | 6 + net/ndisc.c | 276 +++++++++++++++++++++++++++++++++++++++++++ net/ndisc.h | 29 +++++ net/net.c | 38 ++++++ net/net6.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/ping6.c | 115 ++++++++++++++++++ 9 files changed, 1051 insertions(+), 2 deletions(-) create mode 100644 net/ndisc.c create mode 100644 net/ndisc.h create mode 100644 net/net6.c create mode 100644 net/ping6.c
common/cmd_net.c +27 -0
@@ -27,6 +27,7 @@#include <common.h> #include <command.h> #include <net.h> +#include <net6.h> static int netboot_common (enum proto_t ,cmd_tbl_t *,int ,char *const []);
@@ -298,6 +299,32 @@ U_BOOT_CMD("send ICMP ECHO_REQUEST to network host" ,"pingAddress" ); + +#ifdef CONFIG_CMD_NET6 +int do_ping6 (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]) +{ +if (argc <2 ) +return -1 ; + +if (string_to_ip6 (argv[1 ], &NetPingIP6) !=0 ) +return CMD_RET_USAGE ; + +if (NetLoop (PING6 ) <0 ) { +printf ("ping6 failed; host %pI6c is not alive\n" , &NetPingIP6); +return 1 ; + } + +printf ("host %pI6c is alive\n" , &NetPingIP6); + +return 0 ; +} + +U_BOOT_CMD ( + ping6,2 ,1 , do_ping6, +"send ICMPv6 ECHO_REQUEST to network host" , +"pingAddress" +); +#endif /* CONFIG_CMD_NET6 */ #endif #if defined(CONFIG_CMD_CDP )
include/net.h +3 -2
@@ -239,6 +239,7 @@ struct vlan_ethernet_hdr {#define VLAN_ETHER_HDR_SIZE (sizeof(struct vlan_ethernet_hdr))#define PROT_IP 0x0800/* IP protocol */ +#define PROT_IP6 0x86DD/* IPv6 protocol */ #define PROT_ARP 0x0806/* IP ARP protocol */ #define PROT_RARP 0x8035/* IP ARP protocol */ #define PROT_VLAN 0x8100/* IEEE 802.1q protocol */
@@ -436,8 +437,8 @@ extern ushort NetOurNativeVLAN; /* Our Native VLAN */extern int NetRestartWrap;/* Tried all network devices */ enum proto_t { -BOOTP ,RARP ,ARP ,TFTPGET ,DHCP ,PING ,DNS ,NFS ,CDP ,NETCONS ,SNTP , -TFTPSRV ,TFTPPUT ,LINKLOCAL +BOOTP ,RARP ,ARP ,TFTPGET ,DHCP ,PING ,PING6 ,DNS ,NFS ,CDP ,NETCONS , +SNTP ,TFTPSRV ,TFTPPUT ,TFTP6 ,LINKLOCAL };/* from net/net.c */
include/net6.h +208 -0
224 lines not on this page · raw message
net/Makefile +6 -0
@@ -39,6 +39,12 @@ COBJS-$(CONFIG_CMD_PING) += ping.o COBJS-$(CONFIG_CMD_RARP) += rarp.o COBJS-$(CONFIG_CMD_SNTP) += sntp.o COBJS-$(CONFIG_CMD_NET) += tftp.o +ifdef CONFIG_CMD_NET6 +COBJS-y += net6.o +COBJS-y += ndisc.o +COBJS-$(CONFIG_CMD_PING) += ping6.o +endif + COBJS := $(sort $(COBJS-y)) SRCS := $(COBJS:.o=.c)
net/ndisc.c new file +276 -0
276 lines not on this page · raw message
net/ndisc.h new file +29 -0
@@ -0,0 +1,29 @@ +/* +* net/ndisc.h +* +* (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. +*/ + +/* IPv6 destination address of packet waiting for ND */ +extern IP6addr_t NetNDSolPacketIP6; +/* IPv6 address we are expecting ND advert from */ +extern IP6addr_t NetNDRepPacketIP6; +/* MAC destination address of packet waiting for ND */ +extern uchar *NetNDPacketMAC; +/* pointer to packet waiting to be transmitted after ND is resolved */ +extern uchar *NetNDTxPacket; +extern uchar NetNDPacketBuf[PKTSIZE_ALIGN +PKTALIGN ]; +/* size of packet waiting to be transmitted */ +extern int NetNDTxPacketSize; +/* the timer for ND resolution */ +extern ulong NetNDTimerStart; +/* the number of requests we have sent so far */ +extern int NetNDTry; + + +void ndisc_receive (struct ethernet_hdr *et,struct ip6_hdr *ip6,int len); +void ip6_NDISC_Request (void ); +void ip6_NDISC_TimeoutCheck (void );
net/net.c +38 -0
@@ -84,6 +84,7 @@#include <command.h> #include <environment.h> #include <net.h> +#include <net6.h> #if defined(CONFIG_STATUS_LED )#include <miiphy.h> #include <status_led.h>
@@ -269,9 +270,22 @@ static void NetInitLoop(void)#if defined(CONFIG_CMD_DNS ) NetOurDNSIP =getenv_IPaddr ("dnsip" );#endif +#ifdef CONFIG_CMD_NET6 +getenv_IP6addr ("ipaddr6" , &NetOurIP6); +getenv_IP6addr ("gatewayip6" , &NetOurGatewayIP6); +if (getenv ("prefixlength6" )) + NetPrefixLength = +simple_strtoul (getenv ("prefixlength6" ), +NULL ,10 ); +else + NetPrefixLength =64 ; +#endif env_changed_id = env_id; }memcpy (NetOurEther,eth_get_dev ()->enetaddr,6 ); +#ifdef CONFIG_CMD_NET6 +ip6_make_lladdr (&NetOurLinkLocalIP6, NetOurEther); +#endif return ; }
@@ -304,6 +318,9 @@ void net_init(void) NetRxPackets[i] = NetTxPacket + (i +1 ) *PKTSIZE_ALIGN ;ArpInit (); +#ifdef CONFIG_CMD_NET6 +ip6_NDISC_init (); +#endif net_clear_handlers ();/* Only need to setup buffer pointers once. */
@@ -402,6 +419,11 @@ restart:case PING :ping_start ();break ; +#ifdef CONFIG_CMD_NET6 +case PING6 : +ping6_start (); +break ; +#endif #endif #if defined(CONFIG_CMD_NFS )case NFS :
@@ -489,6 +511,9 @@ restart: }ArpTimeoutCheck (); +#ifdef CONFIG_CMD_NET6 +ip6_NDISC_TimeoutCheck (); +#endif /* * Check for a timeout, and run the timeout handler
@@ -1053,6 +1078,11 @@ NetReceive(uchar *inpkt, int len)rarp_receive (ip, len);break ;#endif +#ifdef CONFIG_CMD_NET6 +case PROT_IP6 : +NetIP6PacketHandler (et, (struct ip6_hdr *)ip, len); +break ; +#endif case PROT_IP :debug_cond (DEBUG_NET_PKT ,"Got IP\n" );/* Before we start poking the header, make sure it is there */
@@ -1207,6 +1237,14 @@ static int net_check_prereq(enum proto_t protocol) return 1; } goto common; +#ifdef CONFIG_CMD_NET6 +case PING6 : +if (ip6_is_unspecified_addr (&NetPingIP6)) { +puts ("*** ERROR: ping address not given\n" ); +return 1 ; + } + goto common; +#endif #endif #if defined(CONFIG_CMD_SNTP )case SNTP :
net/net6.c new file +349 -0
349 lines not on this page · raw message
net/ping6.c new file +115 -0
115 lines not on this page · raw message
Signature · 1 line
1.7.12.rc2.16.g034161a