Server IPv6 support
From Linux NFS
NFS kernel code work for IPv6 support in NFSv4 server Description of possible implementation
Possible methods of implementation
Each time an address (or a socket address) is used, a specific processing is performed according to the family of the address.
Another way is to use the IPv4-mapping addressing: with this method, recommended to migrate to IPv6, the IPv4 addresses are mapped into IPv6 addresses and then all the processings are done on IPv6 addresses. So it is no more useful to distinguish IPv4 / IPv6 addresses and the IP layer automatically map/unmap the IPv4 addresses when needed.
A third way is to use sets of functions specific to each protocol (TCP/IPv4, TCP/IPv6, ...) written to implement the parts of code depending on the address type. When a new client or server instance is created, the set of functions corresponding to the transport protocol is stored in the associated structure to be used when needed. This method is used by the transport switch implemented by Chuck Lever to allow new transports, such as RDMA, to be plugged and used instead of TCP or UDP.
Mapped addresses are a mechanism to « encapsulate » a 32 bit IPv4 address in a 128 bit IPv6 address. The IPv4 address is stored in less significant bits of IPv6 address and the 96 most significant bits are 0:0:0:0:FFFF
So the représentaion of A.B.C.D IP address is:
The IN6_IS_ADDR_V4MAPPED() routine aims at determining if an inet6 address is a mapped address.
Solution 1 adds a lot of tests in the code which increase the complexity of the code reading and maintainability.
Solution 2 has the advantage to simplify the code (only one format of addresses is handled) and preserves the performances. Drawbacks: it requires the kernel to be compiled with IPv6, even if no IPv6 addressing is used. Other OS (*nix, Windows, ...) provide the support of IPv6 in standard. Though the default Linux kernels provided by the major distributions (RedHat, FedoraCore, Suse, Debian, Mandrake, ...) are already compiled with IPv6 enabled, the IPv6 compilation flag is not set by default on the kernel.org delivery. Several reasons could explain the unwillingness to require the kernel built with IPv6: the IPv6 code seems not to be mature and tested enough for some people, and this requirement doesn't match with the Linux concept of global modularity (i.e. the possibility to have the wanted functions and only these ones). Keeping the possibility to compile the kernel without the support of IPv6 requires to keep the current processing and to add the new one with a compilation flag (CONFIG_IPV6). This makes the bug fixing more difficult especially because different code paths can be used according to whether the kernel has been built or not with IPv6 enabled.
Solution 3 is clean, it works even if the kernel is not compiled with IPv6. But since INET addresses are used in a lot of places (in nfs, nfsd, lockd, statd, rpc, ...), the access to the structure defining the set of functions to be used may be very difficult. Moreover, according to the granularity of these functions, a lot of code may be duplicated, decreasing the maintainability.
3 for client and a mix of 1 and 2 for server On the client side, since Chuck Lever has already implemented the transport switch in the RPC kernel part, the third solution has been implemented by extending the use of this transport switch to the NFS part. Moreover, the mount command uses the TI-RPC library and has been been extended to be made transport independent. For further information see: http://nfsv4.bullopensource.org/doc/mini-howto.php
Client Ipv6 support should be integrated into Transport Switch and Trond's patchset soon. However, the Ipv6 patchset for the client is available here: http://nfsv4.bullopensource.org/patches/nfs_ipv6-5/index.php
On the server side, no work has been done yet, and is planned, to implement a framework to plug new transports. The current code allows the processing of tcp/ipv4 and udp/ipv4 transports by testing the used protocol when needed. In the same way, the tcp/ipv6 and udp/ipv6 will be added at the RPC level by using generic structures and adding tests of the used family (AF_INET or AF_INET6). INET and INET6 sockets will be used to communicate with clients. INET6 structures (sockaddr_in6 and in6_addr) are used to store both IPv4 and IPv6 addresses. The mapping mechanism is used to encapsulate IPv4 addresses in INET6 structures. In this way, we take advantage of IPv6 features, without needing the kernel to be compiled with IPv6 enabled. We will use IPv6 structure just as a container for both type of addresses. For the transmission we will use IPv6 socket only if adresses are IPv6 addresses. In case of IPv4 address, we will retrieve the IPv4 address from the INET6 structure, and then use IPv4 sockets. In this case, there is no need to have kernel IPv6 modules compiled to do IPv4 communications.