Programmer's Guide

Version 1.1 Alpha


The MRT libraries provide a powerful platform on which engineers may build and develop new routing protocols, and routing protocol applications.

The design and ideas behind many of the MRT libraries draws heavily on the architecture pioneered in GateD.

NOTE: The MRT libraries may undergo significant changes prior to the 2.0 release of MRT. After the 2.0 public release, we expect the library API will remain stable.


Index

  1. Architecture
  2. Packet Formats
  3. Libraries
    1. MRT Library
      Basic routines required by ALL MRT programs.
    2. Timer Library
      Routines to schedule repeated and one-time events
    3. Trace Library
      Routines for logging trace information to disk
    4. Interface Library
      Routines for dealing with ipv6 and ipv6 interfaces
    5. I/O Library
      Routines for handling input and output between MRT processes
    6. Select Library
      Handle polling on a socket
    7. BGP Packet/Attribute Library
      Routines for munging and building BGP4 packets
    8. BGP Protocol Library
      Routines for speaking and listening to BGP4 updates
    9. RIP Library
      Routines for munging and building RIP packets
    10. Routing Information Base (RIB) Library
      Route database and kernel support
    11. Portmapper Interface Library
      Listen on ports

[ MRT | Merit ]


1. MRT Base Library

The MRT base library provides basic routing, interface, alarm, signal and thread routines required by ALL MRT programs.

Synopsis

cc [flag ...] file... [library...] -lmrt

#include <mrt.h>

int init_mrt(trace_t* trace);

Thread Support

mrt_thread_t* mrt_thread_create (char *name, schedule_t *schedule, void (*call_fn) (), void *arg);

schedule_t *New_Schedule (char *description, trace_t *trace);

int schedule_event (schedule_t *schedule, void (*call_fn)(), int narg, ...);

int schedule_wait_for_event (schedule_t *schedule);

void Delete_Event (event_t *event)

int clear_schedule (schedule_t *schedule);

int mrt_thread_exit (mrt_thread_t *thread);

Gateways

gateway_t *New_Gateway (prefix_t *prefix, int AS);

char *gateway_toa (char *tmp, gateway_t *gateway);

gateway_t *find_gateway (prefix_t *prefix, int AS, interface_t *interface);

Prefix

prefix_t *New_Prefix (int family, u_char *dest, int bitlen);

void Delete_Prefix (prefix_t *prefix);

prefix_t* ascii2prefix (int family, char *string);

char *prefix_toa (prefix_t *prefix);

char *prefix_toa2 (prefix_t *prefix, char *tmp);

u_char *prefix_tochar (prefix_t *prefix);

int prefix_compare (prefix_t *p1, prefix_t *p2);

User Interactive Interface (UII)

int uii_add_command (int state, char *string, int *call_fn);

int parse_line (u_char *line, char *format, ...);

set_uii (uii_t *tmp, int first, ...);

int uii_send_data (uii_connection_t *uii, ...);

int uii_destroy_connection (uii_connection_t *connection);

Description

All MRT programs must call mrt_init(). This function intilaizes memory, bookkeeping functions and lower level library routines.


2. MRT I/O Library

Because MRT is structured as a number of separate processes (BGP peers, MRS, etc.), it is necessary to provide a way for these processes to communicate. Solaris provides several different methods for programs to communicate (IPC methods), but the interface to these IPC methods is not standardized, and some amount of support code is invariably necessary to provide services which MRT requires but the Solaris IPC methods do not provide.

The I/O library provides an easy-to-use, standardized abstract interface to IPC. Several different IPC methods (file, stdin/stdout, and System V message queues) are supported. A message-queue key registry is provided, to allow processes to communicate without knowledge of each other's keys.

Synopsis

cc [flag ...] file... [library...] -lio -lstruct -lmrt

#include <mrt.h> #include <io.h>

int io_init();

int io_set(int key, int val, ...);

int io_write(long tstamp, short type, short subtype, int length, char *value);

MRT_MSG_STRUCT *io_read(void);

Description

All programs using the I/O library must call io_init and io_set before any io_write or io_read calls are performed. In addition, the key registry server (msgserver) must be running in order for the IO_INMSGQ and IO_OUTMSGQ I/O types to work.

io_set is used to set up the input and output channels for the I/O library. The arguments to io_set are a sequence of key-value pairs, with the key being an I/O attribute, and the value being attribute-specific. Available keys are specified in table 1.

Table 1: io_set Attributes
Attribute Value
IO_INNONE (char *) NULL
IO_OUTNONE (char *) NULL
IO_OUTFILE filename (string)
IO_OUTAPPEND filename (string)
IO_INFILE filename (string)
IO_INMSGQ client-ID (string)
IO_OUTMSGQ client-ID (string)

After io_set has been used to configure the I/O channels, io_read and io_write can be used to read and write data, respectively.

Examples

See the src/progams/msgserver/testio.c program for an example of a program that does I/O with message queues.

Bugs


3. MRT Timer Library

SunOS associates a single timer per process. Unfortunately, a single timer is usually insufficient for most routing protocols. Protocols like RIP, BGP and IDRP require multiple timers to schedule events like sending KeepAlive packets, timing out dead peers, and retrying the opening of peering sessions. The MRT timer library provides an easy-to-use programming interface to multiplex Unix alarm signals.

The MRT Timer libary provides easy programming interfaces to create, destrory, set nad manuipulate timers.

SYNOPSIS

  cc [flag...] file... -ltimer -lutil -lstruct [library...]
  #include <timer.h>

  void init_timer_master();

  Timer *New_Timer (void (*call_fn)(), int interval, char *name, void *arg);

  void Timer_Turn_ON (Timer *timer);

  void Timer_Turn_OFF (Timer *timer);

  void Timer_Reset_Time (Timer *timer);

All programs making use of the MRT timer library MUST call init_timer_master() before calling any timer routines. Failure to call init_timer_master will result in unitialized timer structures and lead to segment faults

After initializing the master timer information, individual timers are created by calling New_Timer (). The New_Timer () function intitializes a new timer that calls the user-defined call_fn function after the timer fires every interval number of seconds. After the call_fn is executed, the timer automatically resets to expire interval seconds in the future. The name argument is a descriptive string used in logging timer events. New_Timer returns a pointer to a Timer data structure. The call_fn is called with two arguments, a pointer to the Timer data structure that fired, and a pointer to the user-defined data pointer arg. The user-defined call function has the form:

void my_call_fn (Timer *timer, void *my_data);
New_Timer returns a NULL pointer upon failure.

All timers are intially created in the OFF state. In this state, the timer is not scheduled, and the call_fn will not execute. To turn a timer ON, you must call the function Timer_Turn_ON ().

Similarly, if a timer is no longer needed, Timer_Turn_OFF () will remove timer from the timer queue and prevent the timer from firing in the future.

The Timer_Reset_Time function resets the timer to fire after the timer's original interval number of seconds expires. This function is used by protocols like BGP which need to reset KeepAlive timers after receiving a KeepAlive from a peer. If a timer is OFF, the Timer_Reset_Time call will turn the timer on. Timer_Set_Time changes the interval value of an initialized timer. After calling Timer_Set_Time, timer will fire after every interval seconds. If a timer is OFF, the Timer_Set_Time call will turn the timer on.

Finally, a protocol that no longer has need of any timer may clear all memory associated with timers by calling Destroy_Timer_Master. Most protocols will not make use of this function. Protocols MUST not call other timer library routines after invoking Destroy_Timer_Master.

Code Examples:

#include <stdio.h> 
#include <timer.h>

void my_timer_fire1() {  printf("10 I have fired\n"); }
void my_timer_fire2() {  printf("60 I have fired\n"); }


main () {
  Timer *timer1, *timer2;

  init_timer_master();

  timer1 = New_Timer (my_timer_fire1, 60, "timer1");   
  timer2 = New_Timer (my_timer_fire2, 10, "timer2");

  Timer_Turn_ON (timer1);   
  Timer_Turn_ON (timer2);

  /* loop forever */   while (1); 
}

Makefile Example:

  INCDIR=-I$(HOME)/mrt/include
  LIBDIR=-L$(HOME)/mrt/lib
  LIBS=-lstruct -lutil -ltimer 

  all: my_file

  my_file: my_file.o
      $(CC) -o my_file $(LIBDIR) $(LIBS)

  my_file.0: my_file.c
      $(CC) $(INCDIR) -c my_file.c 

Internal Structures

  typedef struct _Timer {    
    int time_interval;	/* seconds between firing */    
    int time_next_fire;	/* real time after which should fire */    
    void (*call_fn)();    
    u_char on;		/* timer is turned ON if this set to 1 */    
    char *name;		/* used for logging and debugging */ 
  } Timer;


  typedef struct _Timer_Master {    
    int time_interval;		/* seconds btwn firing (debugging purposes) */    
    int time_next_fire;		/* real time after which should fire */    
    LINKED_LIST *ll_timers; 
  } Timer_Master;

BUGS

None reported so far.

4. MRT Trace Library

The MRT Trace library provides simple programing interface for programs and protocols to log trace information either to disk, or to the console.

SYNOPSIS

  cc [flag...] file... -ltrace [library...]
  #include <trace.h>

  void trace (int severity, Trace_Struct *trace_struct, ...);

  Trace_Struct *New_Trace_Struct (int first, ...);

  int Set_Trace_Struct (Trace_Struct *tmp, int first, ...)

Protocols making use of the MRT Trace library must first call New_Trace_Struct to allocate memory and initalize the trace information. As argumets, New_Trace_Struct takes a null terminated list of option flag, option value pairs. Possible options, their associated type of argument, and their default value include:
  TR_LOGFILE	char*		"/tmp/mrt.log"
  TR_FLAGS	int		NORM
  TR_APPEND	boolean		TRUE
  TR_FLOCK	boolean		TRUE
TR_LOGFILE speicifes the name of the file to which trace calls will write logging information. If this flag is followed by an argument of "stdout", trace calls will write to standard out.

The TR_FLAGS argument specifies the level, or verbosity, of tracing information that will be generated. Possible arguments include:

  FATAL		/* fatal error -- die after receiving */
  TRACE		/* verbose tracing, like keepalives */
  NORM		/* normal events to trace */

  TR_PARSE	/* trace parsing of config files */
  TR_PACKET	/* trace packet comming and goings */
  TR_STATE	/* trace state changes and events */
  TR_TIMER	/* trace timer changes and events */
  TR_POLICY	/* trace policy changes and events */

  TR_ALL	/* trace everything */

TR_APPEND specifies whether the trace library should append (argument of TRUE) new tracing information onto the end of an existant file, or overwrite an existant file (argument of FALSE).

TR_FLOCK controls whether the trace library uses the flock library (see flock(2)).

The trace function writes logging information of severity to disk. The trace_struct arguments specified as a format string followed by format

Code Examples:


#include 
#include 
#include 


main () {
   Trace_Struct *protocol_trace;

   protocol_trace = New_Trace_Struct (TRACE_LOGFILE, "/tmp/my_logfile", 
                                      TRACE_FLAGS, NORM, 
                                      NULL);
   
   trace (NORM, protocol_trace, "This is a trace message");
   trace (TR_POLICY, protocol_trace, "This will not show up");

   Set_Trace_Struct (protocol_trace, 
                     TRACE_FLAGS, TR_ALL, 
                     TRACE_LOGFILE, "stdout",
                     NULL);

   trace (TR_POLICY, protocol_trace, "This will show up on the console");

   trace (FATAL, protocol_trace, "Now I will die... (this shows up in syslog)");
}

BUGS


4. Interface Library

Synopsis

cc [flag ...] file... [library...] -lnterface -lmrt

#include <mrt.h> #include <interface.h>

int init_interfaces (trace_t *ltrace);

interface_t *find_interface (prefix_t *prefix);

interface_t *find_interface_byname (char *name);

LINKED_LIST *find_network (prefix_t *prefix);

interface_t *find_interface_local (prefix_t *prefix);

int local_interface (int family, u_char *cp);

interface_t *interface_iter (interface_iter_t **iter);


5. Select Library

cc [flag ...] file... [library...] -lselect -lmrt

#include <mrt.h>
#include <select.h>

int select_enable_fd (int fd);

select_disable_fd (int fd);

int select_delete_fd (int fd);

int select_add_fd (int fd, int type_mask, void (*call_fn)(), void *arg);

int init_select ();