Table of Contents

Table of Chapters

10 Build issues

This section summarizes the additions and changes made to the InterNiche code to support IPv6. It should be noted that to a large extent these changes allow IPv6 to replace IPv4, as well as to supplement it.

10.1 Adding IPv6 to legacy IPv4 builds

Great care has been taken to ease the process of adding InterNiche IPv6 to legacy IPv4 builds. The use of "makefiles", automated build tools, and the global "ipport.h_h" file (compiler flags) are identical. Most aspects of adding IPv6 are no different than adding another IPv4 feature. This manual is designed to address those areas where there are (or may be) issues the porting engineer should be aware of.

This does not mean you should continue to use your old IPv4 InterNiche code. Networking code in directories such as "net" and "tcp", "misclib" need numerous "ifdefs" to support IPv6. So all the directories in your original InterNiche build should be updated to the code in the newer IPv6 build.

Older IPv4 applications will continue to run on the IPv4 portion of dual-mode builds without modification, however support for native IPv6 will have to be added to the application manually.

Legacy MAC drivers may work with IPv6 "as is", however because of the scatter/gather buffer design, performance of the MAC driver may be somewhat slower than when performing similar IPv4 tasks. Optimizations to get around this are discussed in the Chapter 15. Keep in mind that MAC drivers must be able to both send and receive multicast packets to support IPv6.

It's also possible that some of the default IPv4 options/features used in legacy systems can't be used for IPv6 builds. There are two known examples of this: IP multicast and binary tree routine. Each of these issues is discussed later in this document.

IP multicast was an option on IPv4 systems. IPv6 requires it. Since IP multicast was historically an extra-cost option (and not a popular one), most InterNiche stacks were shipped without the IP multicast code; and without the support for multicast in the ipport.h file. Details for using IP multicast are in the standard NicheStack documentation.

10.2 #defines

Several #defines are introduced to support IPv6. The #defines are designed to allow the build to be IPv6 only, IPv4 only, or both (the "dual mode" stack). Note that although some marketing literature describes three products (v4, v6, and "dual mode"), there are technically only two code bases involved (v4 and v6). Including both creates "Dual mode".

The # defines related to IPv6 are:

* Feature pre-dates IPv6 release
#definepurposeRequirement/note
IP_V6Includes support for IPv6Requires LINKED_PKTS, BTREE_ROUTES, and IP_MULTICAST
IP_V4Includes support for IPv4Defaults to "defined" if IP_V6 is not defined.
LINKED_PKTSIncludes code for creating linked lists of PACKET structures. (scatter/gather)Required for IPv6
IPV6_TUNNELInclude code for IPv6 tunnels.Requires IP_V6
INCLUDE_6TO4Include code for specifically for RFC3056 "6to4" tunnelsRequires IP_V6 and IPV6_TUNNEL
BTREE_ROUTES*Include binary-tree routine code (IPv6 cannot use the older "static sized table" routing.Required for IPv6
IP_MULTICAST*Include support for IP Multicast packets and IGMP.Required for IPv6

10.3 The ipv6 directory

A single new directory has been added to support IPv6 - "ipv6". This is a peer to the "net" and "ip" directories. Note that the older "ip" directory is still required in an IP_V6 build even if IP_V4 is not #defined, since some of the code is common to both v4 and v6.

10.4 File list

The following files are included in the ipv6 directory:

icmp6.cICMPv6 implementation, except for ND code
ip6.cIPv6 send ... receive routines, and support routines
ip62mac.clink layer support for Ethernet and PPP
ip6frags.cIPv6 fragmentation and reassembly
ip6menu.cdiagnostic menus for IPv6
ip6route.croutine code for IPv6
ip6tun.cIPv6 tunnel code, including 6to4
ip6_pcb.cIPv6 supplement to tcp/in_pcb.c
nd.cNeighbor Discovery (ND) code
ping6.cping client for IPv6
tcp6.cTCP conversions for IPv6
udp6.cUDP conversions for IPv6

Additionally, the following IPv6 files are added to the "h" directory:

ip6mibs.hGeneric IPv6 MIB structures
socket6.hIPv6-specific sockets definition
icmp6.hICMPv6 definitions
ip6.hIPv6 core protocol definitions

10.5 scatter/gather

The PACKET ("struct net") object has several new fields added for scatter/gather support. These fields are included when the build is compiled with LINKED_PKTS defined. The fields are:

struct netbuf * pk_prev;   /* previous pkt in chain */
struct netbuf * pk_next;   /* next ptk in chain */
int             nb_tlen;   /* total length of nb_prots in pk_next list */

The first two fields above are used to implement a bi-directional linked list. The last field, nb_tlen, is the total length of all the packets in the list. nb_tlen is only required in the first packet in the list, and should be the sum of all the nb_plen fields in the list of packet structures.

The nb_tlen field is only guaranteed to be accurate in the first PACKET of a linked list. This PACKET is can be identified by the tk_prev field being NULL.

Received packets at the IP layer are generally not stored in these lists - only packets being formed for sending. The exception is datagrams that are received in IPv6 fragments, which may be assembled into these lists by the IPv6 reassembly code. Currently the only use of this is in large ICMP and UDP packets; TCP is designed to use the TCP MSS option to avoid fragmentation and thus should not need to process received "scattered" packets.

Historically, InterNiche IPv4 code avoided the added complexity of fragmentation by requiring the transport layer to prepend space in the packet buffers for the IP and MAC layer headers. IPv6 presents multiple new motivations for using a scatter/gather approach to sending packets. First, there is the possibility of a range of IP "extension" headers being inserted between the IP and transport headers by the IP code. These include the IP fragment header, which was built into the IP header in IPv4. Another reason for scatter/gather is the (anticipated) widespread use of tunneling on IPv6, which requires additional headers inserted between the IPv6 header and the MAC layer header.

One major drawback of using scatter/gather is the added complexity required for a MAC device driver (i.e. Ethernet) to support it. This issue is examined further in Chapter 15 (MAC Drivers).

10.6 Where are the headers?

Another drawback of this system is that it can become difficult for code to reliably locate protocol headers in the packets. This problem can become especially serious on systems with a wide deviation in requirements for buffer space in front of the IP header, for example a system with one IPv4 tunneling interface and one raw Ethernet interface. The Ethernet interface will require 14 bytes (or perhaps 16 for alignment purposes), whereas the tunnel will require room for the tunnel header, the IPv6 header, and the Ethernet.

To facilitate readily finding the IPv6 header in such systems, the PACKET structure contains an #ifdef field, "ip6_hdr", that always points to the IPv6 header. This field is required in the first PACKET of any chain of packets.

The ip6_hdr field is set by the pktdemux() routine for every PACKET processed through the received queue. Transport layers preparing to send IPv6 packet should set this field prior to sending the PACKET down to the IP layer. The IP send code is required to move the ip6_hdr pointer if it moves the IP header in order to insert IP extension headers. Similarly, tunneling code should move the ip6_hdr pointer to the correct IPv6 header for "downstream" processing.

Other (non-IP) headers must be located algorithmically by starting with the IP header. Transport headers (TCP and UDP) may not directly follow the IP header in the buffer - programmers should use both the IP header's ip_nexthdr and the PACKET's nb_prot and nb_plen fields to check this. Even if ip_nexthdr indicates a certain type follows the IP header (for example 6 indicates a TCP header) if nb_prot plus nb_plen point to the end of the IP header, then the TCP header is in the next linked packet.

To facilitate rapid processing by transport layers, the InterNiche IPv6 layer sets the PACKET's nb_prot pointer to the transport header before calling the transport layer receiver code. For example tcp_rcv(pkt) is called with pkt->nb_prot pointing to the TCP header, and pkt->nb_plen indicating the amount of valid data at that pointer.

10.7 Porting macros - IP6EQ(), IP6CPY(),

IPv6 introduces two new porting macros. These macros were introduced because address copying, and comparing operations, that were very efficient on 32-bit IPv4 addresses, had the potential to be very inefficient in 128-bit IPv6 addresses. Both operations take place frequently throughout the networking code, so they are performed by the above macros, rather than using algorithms hard-coded in C code. The intention is for the porting engineer to provide implementations that are efficient on the target system and tool chain.

At their simplest, these two macros may be left to the default definitions from ip6.h file. These definitions map the macros to memcpy() and memcmp() as follows:

#define IP6EQ(addr1, addr2) (!MEMCMP(addr1, addr2, sizeof(ip6_addr)))
#define IP6CPY(addrptr1, addrptr2) MEMCPY(addrptr1, addrptr2, sizeof(ip6_addr))

Both macros may be optimized by using inline assembly, and by taking advantage of the fact that the blocks to be copied/compared are always 16 bytes long. IP6EQ() may be further optimized by comparing the data at the end of the blocks first, since that is the data most likely to differ.

CPU architectures with alignment sensitivity issues (such as ARM) may assume that the IPv6 addresses are always properly aligned in memory and dispense with alignment tests.