Bull GNU/Linux NFSv4 project

IPv6 support in NFS

Version 0.4
March 29th, 2005
Aurélien Charbon


Introduction:

The goal of our work was initially to add the support of IPv6 in NFSv4. We had to take into account the work of Chuck Lever about the implementation of a transport switch at the level of the client kernel RPC.
Our work has then been extended to the support of IPv6 for NFSv2, NFSv3 and NFSv4

A version built on a kernel 2.6.9 is now available. The support of IPv6 has been achieved as recommended in the books, i.e. NFS code is now full IPv6 and IPv6 structures are used to carry both IPv4 and IPv6 addresses (the IPv4 adresses are "mapped" into IPv6 addresses). This method requires a kernel built with IPv6 enabled (even if NFS is used only on an IPv4 network). This seems unacceptable for many people. A solution could be to keep the current processing, using #ifdef CONFIG_IPV6 paterns, for the kernels not built with IPv6 enabled; but this conplicates the maintainability and is not agreed by everybody. So, a new implementation has been proposed.

The previous versions of this document are available here.


General architecture

A pre-requisite for the support of IPv6 was to solve the problem of the current SunRPC and portmap which had been designed only for TCP and UDP over IPv4 transports. So, the first step to add the support of IPv6 in NFS has been to replace these components by a TI-RPC (Transport Independent RCP) library and a rpcbind command. Refer to TI-RPC and rpcbind support specifications.

The annexe 1 describes the evolutions of architectures for NFSv2/v3 and v4 with the integration of the transport switch and the support of IPv6.


Kernel portmapper

In the Linux kernel, only basic RPC functions (SET, UNSET, GETPORT and CALL) are used.
The registering / unregistering on the portmapper is a local operation, done using a loopback address, so it can continue to be performed using an IPv4 loopback address.
So the only constraint to support IPv6 in NFS is the support of IPv6 addresses in the RPC call and getport functions to allow the NFS client to communicate with an IPv6 remote server and to get the port on which the remote RPC program is listening.
This can be done by implementing the getaddr (v3) or getversaddr (v4) functions of the rpcbind specification.
It is not possible to know whether the remote machine supports portmap or rpcbind, so we may have to try every methods if the first ones failed. We will use the newest versions first (v4, v3, then v2).


NFS user and kernel code

Description of possible implementation

Different methods of implementations are possible:

  1. each time an address (or a socket address) is used, a specific processing is performed according to the family of the address.
  2. another way is to use the IPv4-mapping addressing: with this method, preconized 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.
  3. a third way is to use sets of functions specific to each protocols (TCP/IPv4, TCP/IPv6, ...) written to implement the parts of code dependent 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.

Chosen solution: 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 will be implemented by extending the use of this transport switch to the NFS part. The goal is to have the whole client part transport independent, i.e. allowing dynamic plugging of new transports. The mount command will use the TI-RPC library and will be extended to be made transport independent.

On the server side, no work has been done, 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 from IPv6 possibilities, without needing the kernel to be compiled with IPv6 enabled.


High level description of the implementation

The following points will be addressed:

The work will be splitted into several steps (NFSv4 client, NFSv2/v3 client, NFSv4 server and NFSv2/v3 server) and patches smallest as possible will be provided to allow easy review and test.

The work will be based on the following versions:


Annexe 1: General architecture of NFS + brief overview of each component

  - current architecture for NFSv2/v3:
                              client side      both sides      server side
    user commands :             mount                            exportfs

    user daemons:                                portmap         nfsd
                                                                 mountd
                                                                 lockd/statd

    kernel parts :                               NFSv2/3
                                                 RPC
                                                 XDR
                                                 TCP/UDP
                                                 IPv4

  - current architecture for NFSv4:
                              client side      both sides      server side
    user commands :             mount                            exportfs

    user daemons:                                portmap         nfsd
                                                 idmapd

    kernel parts :                               NFSv4
                                                 RPC
                                                 XDR
                                                 TCP 
                                                 IPv4

  - future architecture for NFSv2/v3:
                              client side      both sides      server side
    user commands :             mount                            exportfs

    user daemons:                                idmapd          rpcbind
                                                                 nfsd
                                                                 mountd
                                                                 lockd/statd

    kernel parts :                               NFSv2/3
                                                 RPC
                                                 XDR
                                                 Transport switch
                                                 TCP/UDP
                                                 IPv4/IPv6

  - future architecture for NFSv4:
                              client side      both sides      server side
    user commands :             mount                            exportfs

    user daemons:                                idmapd          [rpcbind]
                                                                 nfsd

    kernel parts :                               NFSv4
                                                 RPC
                                                 XDR
                                                 Transport switch
                                                 TCP 
                                                 IPv4/IPv6

Brief overview of each components:

  SunRPC/TI-RPC:
  In the current implementations, the user commands and daemons use the SunRPC included in the glibc.
  In the future implementations, the user commands and daemons will use the TI-RPC (Transport Independent RCP) library.

  portmap/rpcbind:
  Used for mapping RPC service numbers with ports. Portmap is the old version, and support only TCP and UDP over IPv4 protocols.
  The NFS services (nfsd, lockd, ...) register themselves to the portmap or rpcbind local daemon to be accessible from remote clients. Variable ports can be used for NFSv2/v3, but a fixed TCP port is used for NFSv4. So NFSv4 can work without portmap/rcpbind;

  lockd/statd:
  Used by NFSv2/v3 to manage locks and stats. In NFSv4, these functions are in the kernel.

  idmapd:
  idmapd is used to perform the user and group id mapping between clients and servers.

  Transport switch:
  Used to plug other transport than UDP or TCP.


Page maintained by: Aurelien Charbon
Accessed times since its creation.
 
Last update: 2005, July 05