AutoXDR - Automated XDR Interfaces
Abstract

Main
AutoGen
Pages

Home
Announce
FAQ
docs
XML Defs
testimonials
downloads

Automated
Options

AutoOpts
Comparison
Man example
Redistribute
Licensing
local use
using getopt

GCC's
Fixincludes

fixincludes

Automated
FSM

description
example
usagefsm

Addons
addon

Project GNU
Home Page

Automated
XDR

xdr project
  definitions
  XDR

  client
  clt. head
  server
  srv. head

  enums

  debug
  test code

i

This paper describes several enhancements to rpcgen designed to facilitate the implementation of both traditional RPC programs and also RPC programs with combinable RPC calls.

This proposal is based on RFCs 1831 and 1832 (RPC and XDR).


Motivation

NFSv4 defines a new RPC interface with 38 procedure calls defined. However, one is the NULL procedure and a second is the carrier procedure for the remaining 36. That means that, as it stands, the authors of the client and server procedures that support these 36 calls must manage the marshaling and unmarshaling of their data into and out of the structures used by the carrier procedure. This proposal augments the functionality of RPCGEN such that the NFSv4 implementers, or the implementers of any other protocol so conceived, shall not deal with such bookkeeping.

This proposal maintains binary compatibility with the proposed NFSv4 standard. Any variations are bugs.

back to top


Approach

This all could have been written without modifying the NFS4 XDR and, instead, just writing libraries specific to the NFS4 and NFS4-CB programs. However, modifying RPCGEN was rejected because it would have taken a lot of work and there is already a tool that makes it relatively simple to do the text expansions. With this tool and a small amount of added work, it has been possible to generate the code to produce these additional interfaces.

Terminology

The following terms are used throughout:

carrier procedure
This is a procedure that sends multiple queued procedure calls at once. It is implemented with two calls. An "init" call that will allocate data structures, and a "send" call to send the queued calls and receive the multiple results.

queued procedure calls
These are procedure calls that are not sent immediately. They are queued and sent when its carrier procedure's "send" function is invoked.

queued procedure callback
When the carrier procedure receives its results, each of the queued procedure calls had a callback procedure registered. If the registered procedure address is not NULL, it will be called with the complete argument list, input *and* output.

AutoXDR's Major functions

  • Collects arguments. It generates the procedures that puts the remote procedure arguments into and out of the structures used by the XDR routines. They call the clnt_call procedure, and process the results for the client. For the queueing procedures, a callback procedure will be registered and the arguments will be saved into a queue for later processing. The "send" procedure will unmarshal the results and call each callback procedure registered for each result.

  • Produces a client header. This file declares the procedures to call to send the requests to the remote host. For the carrier procedures, it declares the "init" and "send" functions, plus all the queueing request ("operation") procedures, plus an enumeration for each of the queueing procedures. Additionally, any enumerations that are declared in the definitions file have three translation routines declared (a la strerror(3)). For example:
        extern const char* info_nfs4_status( nfs4_status );
        extern const char* name_nfs4_status( nfs4_status );
        extern nfs4_status nfs4_status_enum( const char* );
    
    "info_nfs4_status" is analogous to "strerror(3)".
    "name_nfs4_status" will convert the status code into its name.
    "nfs4_status_enum" will find the enum value corresponding to the string name.

  • Produces the server side queued procedure dispatcher. This routine handles the overhead of freeing previous results, allocating then new result space and calling the service routine for each of the specified operations on the queued list, also queueing their results. Additionally, if the interface specifies a NULL procedure, a NULL procedure implementation is emitted here, too.

  • Produces a server side header. It specifies the names and arguments of the service procedures that must be provided by the implementer.

  • For both sides, it generates procedures to translate enumerations from binary form to descriptions or names, and from a names into its binary form. Automatically included with these are the routines for converting queued procedure call numbers.

  • Produces the ONC IDL file that rpcgen can handle.

  • Finally, a debug version of the client code is emitted which will directly call the service routines. This will enable you to debug your protocol within a single process.

back to top


XDR Changes

The implementation requires several changes to the way the XDR data and RPC programs get defined. Principally, there are some data that must be operated on by both the XDR compiler (rpcgen) and by this new tool (AutoXDR). Rather than duplicate the information, these common data are now expressed in a way that AutoGen can understand and it will produce both the new files, and the traditional XDR file. There are also a few additional bits of information that are needed by AutoGen for the XDR templates, but not specifiable in the ONC IDL.

This is a summary of the changes. Greater detail on the requirements for the AutoGen definitions file can be found in the example definitions file.

  1. Only one program may be defined at a time. If two different programs have a lot of common data structures, then the common data can be specified in a common definition file that is included by both of the programs' AutoXDR definition files.

    If you compile code that references both of these programs, you will need to be careful and protect the data structures with something like:

    #if defined( RPC_HDR )
    %#ifndef HAVE_XDR_DATA_
    %#define HAVE_XDR_DATA_
    
    #elif defined( RPC_XDR )
    %#ifndef HAVE_XDR_PROCS_
    %#define HAVE_XDR_PROCS_
    #endif
    
  2. The program specification must not be supplied. Instead, you must use AutoGen definition syntax to provide values for program, prog_id and one or more copies of prog_version. You will find these definitions very similar to the original definitions.

  3. The program must define the name of the status enumeration. This is done by providing a definition for status_enum, such as:
    status_enum = "nfs4_status";
    
  4. As with ONC's IDL, the procedures are defined as part of the compound version (prog_version) definitions. Each defined procedure must have a p_name defined, and may have zero, one or more arguments (p_arg) defined.

  5. Each argument must have an object type (def_type), a name (def_name) and a usage (in, out or i_o attribute) defined. If the argument is normally passed by value (a scalar), no passing type is specified. If the argument is a fixed-length array, then it must have the array attribute. Otherwise, the argument should be a structure that is passed by reference and must have the ref attribute.

  6. Queued procedures are members of carrier procedure definitions. They are defined as a p_op attribute(s) to the carrier procedure. The arguments to a queueing procedure are specified exactly the same way as the arguments to normal procedures, except they are each named op_arg.

  7. Special enumerations (especially the error status enumeration) can be specified in a way that will cause translation routines to be emitted. Here is a trivial examle from NFSv4:
    /*
     * Error status
     */
    enum = {
      en_name = status;
      en_ent[    0] = { ename = OK;
                        etype = "successful completion"; };
      en_ent[    1] = { ename = PERM;
         etype = "caller is either not privileged or not owner"; };
      en_ent[    2] = { ename = NOENT;
                        etype = "No such file or directory"; };
      en_ent[  256] = { ename = OMITTED;
                        etype = "operation omitted"; };
    };
    
    The enumeration for zero (0) is omitted.

  8. All other XDR data are passed through the AutoGen definitions by setting one or more copies of xdr_data to the text to be passed through.

back to top


Example definitions and output

Below are brief descriptions of the AutoXDR relevant files and links to longer descriptions with brief examples. The examples are based on a tiny fragment of the NFSv4 specification.

Definitions
A description of the AutoGen definitions that are used by AutoXDR. This and the example test program below are the only files that are hand edited. The remainder are generated for you.

Client code
This is the generated code that collects the arguments for the queued procedures and marshals the arguments into and out of structures for the clnt_call routine.

Client header
This is a generated file that declares the enumeration procedures and, for queued procedures, the types of the queued procedure callbacks and the procedure prototypes for the queueing procedures.

Server code
This is the generated code that handles the NULL procedure and the servicing of the queued procedures. It will process the calls until a threshold result code is exceeded. The default threshold is 0. This file is not produced if there are no carrier procedures.

Server header
This is a generated file that declares the queued service routines that the server side code will call. This file is not produced if there are no carrier procedures.

Enum translator
This is the generated code that translates enumerations into strings and back. It can be used on either the client or server side, but the interface is declared in the client header.

XDR IDL
This is the ONC IDL or XDR file.

Debug & Startup Code
There are several debug and start up files that get generated. The referenced page shows an example of the debug code only.

*-debug.c
This is a debug version substitution for the normal client code (*-client.c). It will directly call the server code so that you can debug the protocol in a single process. With this module, the XDR routines from rpcgen and the server code, you have all the glue you need to debug your RPC program inside of a single process.

*-clmain.c
This is a template file that can be used to start development of the client. It includes code that will call every procedure once and, if there are queued procedure calls, the callback procedures are generated and thecarrier procedure's init and send procedures are called at the right time. You should rename the file, if you choose to edit it. Otherwise, it will be overwritten whenever these files are regenerated.

*-svstub.c
This file contains stub procedures for the server side. They will all ignore their input arguments, print a message to stderr and return success. Similar to the *-clmain.c file, you should rename this file before editing it.


Example Test
If you compile this module and link it with the Debug Procedures, the Server code and the rpcgen-ed XDR module, you will have a fully functional program that tests out this example interface. e.g.:
  $(CC) -o rpctest rpctest.o nfsv4-debug.o nfsv4-server.o nfsv4_xdr.o

top  Viewable With Any Browser  Valid XHTML 1.0!


AutoGen, AutoOpts, columns, getdefs, AutoFSM, AutoXDR and these web pages copyright (c) 1999-2002 Bruce Korb, all rights reserved.

AutoXDR copyright (c) 2000-2001 Bruce Korb, all rights reserved.
Return to GNU's home page.

Please send FSF & GNU inquiries & questions to gnu@gnu.org. There are also other ways to contact the FSF.

Please send comments on these web pages to webmasters@www.gnu.org, send other questions to gnu@gnu.org.

This article, Copyright © 2000-2002 by Bruce Korb

Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. Last modified: Sun Oct 1 12:59:23 PDT 2006