BIRD Programmer's Documentation: Core

Next Previous Contents

## 2. Core

## 2.1 Forwarding Information Base

FIB is a data structure designed for storage of routes indexed by their network prefixes. It supports insertion, deletion, searching by prefix, `routing' (in CIDR sense, that is searching for a longest prefix matching a given IP address) and (which makes the structure very tricky to implement) asynchronous reading, that is enumerating the contents of a FIB while other modules add, modify or remove entries.

Internally, each FIB is represented as a collection of nodes of type fib_node indexed using a sophisticated hashing mechanism. We use two-stage hashing where we calculate a 16-bit primary hash key independent on hash table size and then we just divide the primary keys modulo table size to get a real hash key used for determining the bucket containing the node. The lists of nodes in each bucket are sorted according to the primary hash key, hence if we keep the total number of buckets to be a power of two, re-hashing of the structure keeps the relative order of the nodes.

To get the asynchronous reading consistent over node deletions, we need to keep a list of readers for each node. When a node gets deleted, its readers are automatically moved to the next node in the table.

Basic FIB operations are performed by functions defined by this module, enumerating of FIB contents is accomplished by using the FIB_WALK() macro or FIB_ITERATE_START() if you want to do it asynchronously.

### Function

void fib_init (struct fib * f, pool * p, unsigned node_size, unsigned hash_order, fib_init_func init) -- initialize a new FIB

### Arguments

struct fib * f

  the FIB to be initialized (the structure itself being allocated by the caller)

pool * p

  pool to allocate the nodes in

unsigned node_size

  node size to be used (each node consists of a standard header fib_node followed by user data)

unsigned hash_order

  initial hash order (a binary logarithm of hash table size), 0 to use default order (recommended)

fib_init_func init

  pointer a function to be called to initialize a newly created node

### Description

This function initializes a newly allocated FIB and prepares it for use.

### Function

void * fib_find (struct fib * f, ip_addr * a, int len) -- search for FIB node by prefix

### Arguments

struct fib * f

  FIB to search in

ip_addr * a

  pointer to IP address of the prefix

int len

  prefix length

### Description

Search for a FIB node corresponding to the given prefix, return a pointer to it or NULL if no such node exists.

### Function

void * fib_get (struct fib * f, ip_addr * a, int len) -- find or create a FIB node

### Arguments

struct fib * f

  FIB to work with

ip_addr * a

  pointer to IP address of the prefix

int len

  prefix length

### Description

Search for a FIB node corresponding to the given prefix and return a pointer to it. If no such node exists, create it.

### Function

void * fib_route (struct fib * f, ip_addr a, int len) -- CIDR routing lookup

### Arguments

struct fib * f

  FIB to search in

ip_addr a

  pointer to IP address of the prefix

int len

  prefix length

### Description

Search for a FIB node with longest prefix matching the given network, that is a node which a CIDR router would use for routing that network.

### Function

void fib_delete (struct fib * f, void * E) -- delete a FIB node

### Arguments

struct fib * f

  FIB to delete from

void * E

  entry to delete

### Description

This function removes the given entry from the FIB, taking care of all the asynchronous readers by shifting them to the next node in the canonical reading order.

### Function

void fib_free (struct fib * f) -- delete a FIB

### Arguments

struct fib * f

  FIB to be deleted

### Description

This function deletes a FIB -- it frees all memory associated with it and all its entries.

### Function

void fib_check (struct fib * f) -- audit a FIB

### Arguments

struct fib * f

  FIB to be checked

### Description

This debugging function audits a FIB by checking its internal consistency. Use when you suspect somebody of corrupting innocent data structures.

## 2.2 Routing tables

Routing tables are probably the most important structures BIRD uses. They hold all the information about known networks, the associated routes and their attributes.

There are multiple routing tables (a primary one together with any number of secondary ones if requested by the configuration). Each table is basically a FIB containing entries describing the individual destination networks. For each network (represented by structure net), there is a one-way linked list of route entries (rte), the first entry on the list being the best one (i.e., the one we currently use for routing), the order of the other ones is undetermined.

The rte contains information specific to the route (preference, protocol metrics, time of last modification etc.) and a pointer to a rta structure (see the route attribute module for a precise explanation) holding the remaining route attributes which are expected to be shared by multiple routes in order to conserve memory.

### Function

rte * rte_find (net * net, struct proto * p) -- find a route

### Arguments

net * net

  network node

struct proto * p

  protocol

### Description

The rte_find() function returns a route for destination net which belongs has been defined by protocol p.

### Function

rte * rte_get_temp (rta * a) -- get a temporary rte

### Arguments

rta * a

  attributes to assign to the new route (a rta; in case it's un-cached, rte_update() will create a cached copy automatically)

### Description

Create a temporary rte and bind it with the attributes a. Also set route preference to the default preference set for the protocol.

### Function

void rte_announce (rtable * tab, unsigned type, net * net, rte * new, rte * old, ea_list * tmpa) -- announce a routing table change

### Arguments

rtable * tab

  table the route has been added to

unsigned type

  type of route announcement (RA_OPTIMAL or RA_ANY)

net * net

  network in question

rte * new

  the new route to be announced

rte * old

  the previous route for the same network

ea_list * tmpa

  a list of temporary attributes belonging to the new route

### Description

This function gets a routing table update and announces it to all protocols that acccepts given type of route announcement and are connected to the same table by their announcement hooks.

Route announcement of type RA_OPTIMAL si generated when optimal route (in routing table tab) changes. In that case old stores the old optimal route.

Route announcement of type RA_ANY si generated when any route (in routing table tab) changes In that case old stores the old route from the same protocol.

For each appropriate protocol, we first call its import_control() hook which performs basic checks on the route (each protocol has a right to veto or force accept of the route before any filter is asked) and adds default values of attributes specific to the new protocol (metrics, tags etc.). Then it consults the protocol's export filter and if it accepts the route, the rt_notify() hook of the protocol gets called.

### Function

void rte_free (rte * e) -- delete a rte

### Arguments

rte * e

  rte to be deleted

### Description

rte_free() deletes the given rte from the routing table it's linked to.

### Function

void rte_update (rtable * table, net * net, struct proto * p, struct proto * src, rte * new) -- enter a new update to a routing table

### Arguments

rtable * table

  table to be updated

net * net

  network node

struct proto * p

  protocol submitting the update

struct proto * src

  protocol originating the update

rte * new

  a rte representing the new route or NULL for route removal.

### Description

This function is called by the routing protocols whenever they discover a new route or wish to update/remove an existing route. The right announcement sequence is to build route attributes first (either un-cached with aflags set to zero or a cached one using rta_lookup(); in this case please note that you need to increase the use count of the attributes yourself by calling rta_clone()), call rte_get_temp() to obtain a temporary rte, fill in all the appropriate data and finally submit the new rte by calling rte_update().

src specifies the protocol that originally created the route and the meaning of protocol-dependent data of new. If new is not NULL, src have to be the same value as new->attrs->proto. p specifies the protocol that called rte_update(). In most cases it is the same protocol as src. rte_update() stores p in new->sender;

When rte_update() gets any route, it automatically validates it (checks, whether the network and next hop address are valid IP addresses and also whether a normal routing protocol doesn't try to smuggle a host or link scope route to the table), converts all protocol dependent attributes stored in the rte to temporary extended attributes, consults import filters of the protocol to see if the route should be accepted and/or its attributes modified, stores the temporary attributes back to the rte.

Now, having a "public" version of the route, we automatically find any old route defined by the protocol src for network n, replace it by the new one (or removing it if new is NULL), recalculate the optimal route for this destination and finally broadcast the change (if any) to all routing protocols by calling rte_announce().

All memory used for attribute lists and other temporary allocations is taken from a special linear pool rte_update_pool and freed when rte_update() finishes.

### Function

void rte_dump (rte * e) -- dump a route

### Arguments

rte * e

  rte to be dumped

### Description

This functions dumps contents of a rte to debug output.

### Function

void rt_dump (rtable * t) -- dump a routing table

### Arguments

rtable * t

  routing table to be dumped

### Description

This function dumps contents of a given routing table to debug output.

### Function

void rt_dump_all (void) -- dump all routing tables

### Description

This function dumps contents of all routing tables to debug output.

### Function

void rt_init (void) -- initialize routing tables

### Description

This function is called during BIRD startup. It initializes the routing table module.

### Function

void rt_prune (rtable * tab) -- prune a routing table

### Arguments

rtable * tab

  routing table to be pruned

### Description

This function is called whenever a protocol shuts down. It scans the routing table and removes all routes belonging to inactive protocols and also stale network entries.

### Function

void rt_prune_all (void) -- prune all routing tables

### Description

This function calls rt_prune() for all known routing tables.

### Function

void rt_lock_table (rtable * r) -- lock a routing table

### Arguments

rtable * r

  routing table to be locked

### Description

Lock a routing table, because it's in use by a protocol, preventing it from being freed when it gets undefined in a new configuration.

### Function

void rt_unlock_table (rtable * r) -- unlock a routing table

### Arguments

rtable * r

  routing table to be unlocked

### Description

Unlock a routing table formerly locked by rt_lock_table(), that is decrease its use count and delete it if it's scheduled for deletion by configuration changes.

### Function

void rt_commit (struct config * new, struct config * old) -- commit new routing table configuration

### Arguments

struct config * new

  new configuration

struct config * old

  original configuration or NULL if it's boot time config

### Description

Scan differences between old and new configuration and modify the routing tables according to these changes. If new defines a previously unknown table, create it, if it omits a table existing in old, schedule it for deletion (it gets deleted when all protocols disconnect from it by calling rt_unlock_table()), if it exists in both configurations, leave it unchanged.

### Function

int rt_feed_baby (struct proto * p) -- advertise routes to a new protocol

### Arguments

struct proto * p

  protocol to be fed

### Description

This function performs one pass of advertisement of routes to a newly initialized protocol. It's called by the protocol code as long as it has something to do. (We avoid transferring all the routes in single pass in order not to monopolize CPU time.)

### Function

void rt_feed_baby_abort (struct proto * p) -- abort protocol feeding

### Arguments

struct proto * p

  protocol

### Description

This function is called by the protocol code when the protocol stops or ceases to exist before the last iteration of rt_feed_baby() has finished.

### Function

net * net_find (rtable * tab, ip_addr addr, unsigned len) -- find a network entry

### Arguments

rtable * tab

  a routing table

ip_addr addr

  address of the network

unsigned len

  length of the network prefix

### Description

net_find() looks up the given network in routing table tab and returns a pointer to its net entry or NULL if no such network exists.

### Function

net * net_get (rtable * tab, ip_addr addr, unsigned len) -- obtain a network entry

### Arguments

rtable * tab

  a routing table

ip_addr addr

  address of the network

unsigned len

  length of the network prefix

### Description

net_get() looks up the given network in routing table tab and returns a pointer to its net entry. If no such entry exists, it's created.

### Function

rte * rte_cow (rte * r) -- copy a route for writing

### Arguments

rte * r

  a route entry to be copied

### Description

rte_cow() takes a rte and prepares it for modification. The exact action taken depends on the flags of the rte -- if it's a temporary entry, it's just returned unchanged, else a new temporary entry with the same contents is created.

The primary use of this function is inside the filter machinery -- when a filter wants to modify rte contents (to change the preference or to attach another set of attributes), it must ensure that the rte is not shared with anyone else (and especially that it isn't stored in any routing table).

### Result

a pointer to the new writable rte.

## 2.3 Route attribute cache

Each route entry carries a set of route attributes. Several of them vary from route to route, but most attributes are usually common for a large number of routes. To conserve memory, we've decided to store only the varying ones directly in the rte and hold the rest in a special structure called rta which is shared among all the rte's with these attributes.

Each rta contains all the static attributes of the route (i.e., those which are always present) as structure members and a list of dynamic attributes represented by a linked list of ea_list structures, each of them consisting of an array of eattr's containing the individual attributes. An attribute can be specified more than once in the ea_list chain and in such case the first occurrence overrides the others. This semantics is used especially when someone (for example a filter) wishes to alter values of several dynamic attributes, but it wants to preserve the original attribute lists maintained by another module.

Each eattr contains an attribute identifier (split to protocol ID and per-protocol attribute ID), protocol dependent flags, a type code (consisting of several bit fields describing attribute characteristics) and either an embedded 32-bit value or a pointer to a adata structure holding attribute contents.

There exist two variants of rta's -- cached and un-cached ones. Un-cached rta's can have arbitrarily complex structure of ea_list's and they can be modified by any module in the route processing chain. Cached rta's have their attribute lists normalized (that means at most one ea_list is present and its values are sorted in order to speed up searching), they are stored in a hash table to make fast lookup possible and they are provided with a use count to allow sharing.

Routing tables always contain only cached rta's.

### Function

eattr * ea_find (ea_list * e, unsigned id) -- find an extended attribute

### Arguments

ea_list * e

  attribute list to search in

unsigned id

  attribute ID to search for

### Description

Given an extended attribute list, ea_find() searches for a first occurrence of an attribute with specified ID, returning either a pointer to its eattr structure or NULL if no such attribute exists.

### Function

int ea_get_int (ea_list * e, unsigned id, int def) -- fetch an integer attribute

### Arguments

ea_list * e

  attribute list

unsigned id

  attribute ID

int def

  default value

### Description

This function is a shortcut for retrieving a value of an integer attribute by calling ea_find() to find the attribute, extracting its value or returning a provided default if no such attribute is present.

### Function

void ea_sort (ea_list * e) -- sort an attribute list

### Arguments

ea_list * e

  list to be sorted

### Description

This function takes a ea_list chain and sorts the attributes within each of its entries.

If an attribute occurs multiple times in a single ea_list, ea_sort() leaves only the first (the only significant) occurrence.

### Function

unsigned ea_scan (ea_list * e) -- estimate attribute list size

### Arguments

ea_list * e

  attribute list

### Description

This function calculates an upper bound of the size of a given ea_list after merging with ea_merge().

### Function

void ea_merge (ea_list * e, ea_list * t) -- merge segments of an attribute list

### Arguments

ea_list * e

  attribute list

ea_list * t

  buffer to store the result to

### Description

This function takes a possibly multi-segment attribute list and merges all of its segments to one.

The primary use of this function is for ea_list normalization: first call ea_scan() to determine how much memory will the result take, then allocate a buffer (usually using alloca()), merge the segments with ea_merge() and finally sort and prune the result by calling ea_sort().

### Function

int ea_same (ea_list * x, ea_list * y) -- compare two ea_list's

### Arguments

ea_list * x

  attribute list

ea_list * y

  attribute list

### Description

ea_same() compares two normalized attribute lists x and y and returns 1 if they contain the same attributes, 0 otherwise.

### Function

void ea_format (eattr * e, byte * buf) -- format an eattr for printing

### Arguments

eattr * e

  attribute to be formatted

byte * buf

  destination buffer of size EA_FORMAT_BUF_SIZE

### Description

This function takes an extended attribute represented by its eattr structure and formats it nicely for printing according to the type information.

If the protocol defining the attribute provides its own get_attr() hook, it's consulted first.

### Function

void ea_dump (ea_list * e) -- dump an extended attribute

### Arguments

ea_list * e

  attribute to be dumped

### Description

ea_dump() dumps contents of the extended attribute given to the debug output.

### Function

unsigned int ea_hash (ea_list * e) -- calculate an ea_list hash key

### Arguments

ea_list * e

  attribute list

### Description

ea_hash() takes an extended attribute list and calculated a hopefully uniformly distributed hash value from its contents.

### Function

ea_list * ea_append (ea_list * to, ea_list * what) -- concatenate ea_list's

### Arguments

ea_list * to

  destination list (can be NULL)

ea_list * what

  list to be appended (can be NULL)

### Description

This function appends the ea_list what at the end of ea_list to and returns a pointer to the resulting list.

### Function

rta * rta_lookup (rta * o) -- look up a rta in attribute cache

### Arguments

rta * o

  a un-cached rta

### Description

rta_lookup() gets an un-cached rta structure and returns its cached counterpart. It starts with examining the attribute cache to see whether there exists a matching entry. If such an entry exists, it's returned and its use count is incremented, else a new entry is created with use count set to 1.

The extended attribute lists attached to the rta are automatically converted to the normalized form.

### Function

void rta_dump (rta * a) -- dump route attributes

### Arguments

rta * a

  attribute structure to dump

### Description

This function takes a rta and dumps its contents to the debug output.

### Function

void rta_dump_all (void) -- dump attribute cache

### Description

This function dumps the whole contents of route attribute cache to the debug output.

### Function

void rta_init (void) -- initialize route attribute cache

### Description

This function is called during initialization of the routing table module to set up the internals of the attribute cache.

### Function

rta * rta_clone (rta * r) -- clone route attributes

### Arguments

rta * r

  a rta to be cloned

### Description

rta_clone() takes a cached rta and returns its identical cached copy. Currently it works by just returning the original rta with its use count incremented.

### Function

void rta_free (rta * r) -- free route attributes

### Arguments

rta * r

  a rta to be freed

### Description

If you stop using a rta (for example when deleting a route which uses it), you need to call rta_free() to notify the attribute cache the attribute is no longer in use and can be freed if you were the last user (which rta_free() tests by inspecting the use count).

## 2.4 Routing protocols

### Introduction

The routing protocols are the bird's heart and a fine amount of code is dedicated to their management and for providing support functions to them. (-: Actually, this is the reason why the directory with sources of the core code is called `nest` :-).

When talking about protocols, one need to distinguish between protocols and protocol instances. A protocol exists exactly once, not depending on whether it's configured or not and it can have an arbitrary number of instances corresponding to its "incarnations" requested by the configuration file. Each instance is completely autonomous, has its own configuration, its own status, its own set of routes and its own set of interfaces it works on.

A protocol is represented by a protocol structure containing all the basic information (protocol name, default settings and pointers to most of the protocol hooks). All these structures are linked in the protocol_list list.

Each instance has its own proto structure describing all its properties: protocol type, configuration, a resource pool where all resources belonging to the instance live, various protocol attributes (take a look at the declaration of proto in `protocol.h`), protocol states (see below for what do they mean), connections to routing tables, filters attached to the protocol and finally a set of pointers to the rest of protocol hooks (they are the same for all instances of the protocol, but in order to avoid extra indirections when calling the hooks from the fast path, they are stored directly in proto). The instance is always linked in both the global instance list (proto_list) and a per-status list (either active_proto_list for running protocols, initial_proto_list for protocols being initialized or flush_proto_list when the protocol is being shut down).

The protocol hooks are described in the next chapter, for more information about configuration of protocols, please refer to the configuration chapter and also to the description of the proto_commit function.

### Protocol states

As startup and shutdown of each protocol are complex processes which can be affected by lots of external events (user's actions, reconfigurations, behavior of neighboring routers etc.), we have decided to supervise them by a pair of simple state machines -- the protocol state machine and a core state machine.

The protocol state machine corresponds to internal state of the protocol and the protocol can alter its state whenever it wants to. There are the following states:

`PS_DOWN`

  The protocol is down and waits for being woken up by calling its start() hook.

`PS_START`

  The protocol is waiting for connection with the rest of the network. It's active, it has resources allocated, but it still doesn't want any routes since it doesn't know what to do with them.

`PS_UP`

  The protocol is up and running. It communicates with the core, delivers routes to tables and wants to hear announcement about route changes.

`PS_STOP`

  The protocol has been shut down (either by being asked by the core code to do so or due to having encountered a protocol error).

Unless the protocol is in the `PS_DOWN` state, it can decide to change its state by calling the proto_notify_state function.

At any time, the core code can ask the protocol to shut itself down by calling its stop() hook.

The core state machine takes care of the core view of protocol state. The states are traversed according to changes of the protocol state machine, but sometimes the transitions are delayed if the core needs to finish some actions (for example sending of new routes to the protocol) before proceeding to the new state. There are the following core states:

`FS_HUNGRY`

  The protocol is down, it doesn't have any routes and doesn't want them.

`FS_FEEDING`

  The protocol has reached the `PS_UP` state, but we are still busy sending the initial set of routes to it.

`FS_HAPPY`

  The protocol is up and has complete routing information.

`FS_FLUSHING`

  The protocol is shutting down (it's in either `PS_STOP` or `PS_DOWN` state) and we're flushing all of its routes from the routing tables.

### Functions of the protocol module

The protocol module provides the following functions:

### Function

void * proto_new (struct proto_config * c, unsigned size) -- create a new protocol instance

### Arguments

struct proto_config * c

  protocol configuration

unsigned size

  size of protocol data structure (each protocol instance is represented by a structure starting with generic part [struct proto] and continued with data specific to the protocol)

### Description

When a new configuration has been read in, the core code starts initializing all the protocol instances configured by calling their init() hooks with the corresponding instance configuration. The initialization code of the protocol is expected to create a new instance according to the configuration by calling this function and then modifying the default settings to values wanted by the protocol.

### Function

struct announce_hook * proto_add_announce_hook (struct proto * p, struct rtable * t) -- connect protocol to a routing table

### Arguments

struct proto * p

  protocol instance

struct rtable * t

  routing table to connect to

### Description

This function creates a connection between the protocol instance p and the routing table t, making the protocol hear all changes in the table.

Unless you want to listen to multiple routing tables (as the Pipe protocol does), you needn't to worry about this function since the connection to the protocol's primary routing table is initialized automatically by the core code.

### Function

void * proto_config_new (struct protocol * pr, unsigned size) -- create a new protocol configuration

### Arguments

struct protocol * pr

  protocol the configuration will belong to

unsigned size

  size of the structure including generic data

### Description

Whenever the configuration file says that a new instance of a routing protocol should be created, the parser calls proto_config_new() to create a configuration entry for this instance (a structure staring with the proto_config header containing all the generic items followed by protocol-specific ones). Also, the configuration entry gets added to the list of protocol instances kept in the configuration.

### Function

void protos_preconfig (struct config * c) -- pre-configuration processing

### Arguments

struct config * c

  new configuration

### Description

This function calls the preconfig() hooks of all routing protocols available to prepare them for reading of the new configuration.

### Function

void protos_postconfig (struct config * c) -- post-configuration processing

### Arguments

struct config * c

  new configuration

### Description

This function calls the postconfig() hooks of all protocol instances specified in configuration c.

### Function

void protos_commit (struct config * new, struct config * old, int force_reconfig, int type) -- commit new protocol configuration

### Arguments

struct config * new

  new configuration

struct config * old

  old configuration or NULL if it's boot time config

int force_reconfig

  force restart of all protocols (used for example when the router ID changes)

int type

  type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)

### Description

Scan differences between old and new configuration and adjust all protocol instances to conform to the new configuration.

When a protocol exists in the new configuration, but it doesn't in the original one, it's immediately started. When a collision with the other running protocol would arise, the new protocol will be temporarily stopped by the locking mechanism.

When a protocol exists in the old configuration, but it doesn't in the new one, it's shut down and deleted after the shutdown completes.

When a protocol exists in both configurations, the core decides whether it's possible to reconfigure it dynamically - it checks all the core properties of the protocol (changes in filters are ignored if type is RECONFIG_SOFT) and if they match, it asks the reconfigure() hook of the protocol to see if the protocol is able to switch to the new configuration. If it isn't possible, the protocol is shut down and a new instance is started with the new configuration after the shutdown is completed.

### Function

void protos_dump_all (void) -- dump status of all protocols

### Description

This function dumps status of all existing protocol instances to the debug output. It involves printing of general status information such as protocol states, its position on the protocol lists and also calling of a dump() hook of the protocol to print the internals.

### Function

void proto_build (struct protocol * p) -- make a single protocol available

### Arguments

struct protocol * p

  the protocol

### Description

After the platform specific initialization code uses protos_build() to add all the standard protocols, it should call proto_build() for all platform specific protocols to inform the core that they exist.

### Function

void protos_build (void) -- build a protocol list

### Description

This function is called during BIRD startup to insert all standard protocols to the global protocol list. Insertion of platform specific protocols (such as the kernel syncer) is in the domain of competence of the platform dependent startup code.

### Function

void proto_request_feeding (struct proto * p) -- request feeding routes to the protocol

### Arguments

struct proto * p

  given protocol

### Description

Sometimes it is needed to send again all routes to the protocol. This is called feeding and can be requested by this function. This would cause protocol core state transition to FS_FEEDING (during feeding) and when completed, it will switch back to FS_HAPPY. This function can be called even when feeding is already running, in that case it is restarted.

### Function

void proto_notify_state (struct proto * p, unsigned ps) -- notify core about protocol state change

### Arguments

struct proto * p

  protocol the state of which has changed

unsigned ps

  the new status

### Description

Whenever a state of a protocol changes due to some event internal to the protocol (i.e., not inside a start() or shutdown() hook), it should immediately notify the core about the change by calling proto_notify_state() which will write the new state to the proto structure and take all the actions necessary to adapt to the new state. State change to PS_DOWN immediately frees resources of protocol and might execute start callback of protocol; therefore, it should be used at tail positions of protocol callbacks.

## 2.5 Protocol hooks

Each protocol can provide a rich set of hook functions referred to by pointers in either the proto or protocol structure. They are called by the core whenever it wants the protocol to perform some action or to notify the protocol about any change of its environment. All of the hooks can be set to NULL which means to ignore the change or to take a default action.

### Function

void preconfig (struct protocol * p, struct config * c) -- protocol preconfiguration

### Arguments

struct protocol * p

  a routing protocol

struct config * c

  new configuration

### Description

The preconfig() hook is called before parsing of a new configuration.

### Function

void postconfig (struct proto_config * c) -- instance post-configuration

### Arguments

struct proto_config * c

  instance configuration

### Description

The postconfig() hook is called for each configured instance after parsing of the new configuration is finished.

### Function

struct proto * init (struct proto_config * c) -- initialize an instance

### Arguments

struct proto_config * c

  instance configuration

### Description

The init() hook is called by the core to create a protocol instance according to supplied protocol configuration.

### Result

a pointer to the instance created

### Function

int reconfigure (struct proto * p, struct proto_config * c) -- request instance reconfiguration

### Arguments

struct proto * p

  an instance

struct proto_config * c

  new configuration

### Description

The core calls the reconfigure() hook whenever it wants to ask the protocol for switching to a new configuration. If the reconfiguration is possible, the hook returns 1. Otherwise, it returns 0 and the core will shut down the instance and start a new one with the new configuration.

After the protocol confirms reconfiguration, it must no longer keep any references to the old configuration since the memory it's stored in can be re-used at any time.

### Function

void dump (struct proto * p) -- dump protocol state

### Arguments

struct proto * p

  an instance

### Description

This hook dumps the complete state of the instance to the debug output.

### Function

void dump_attrs (rte * e) -- dump protocol-dependent attributes

### Arguments

rte * e

  a route entry

### Description

This hook dumps all attributes in the rte which belong to this protocol to the debug output.

### Function

int start (struct proto * p) -- request instance startup

### Arguments

struct proto * p

  protocol instance

### Description

The start() hook is called by the core when it wishes to start the instance.

### Result

new protocol state

### Function

int shutdown (struct proto * p) -- request instance shutdown

### Arguments

struct proto * p

  protocol instance

### Description

The stop() hook is called by the core when it wishes to shut the instance down for some reason.

### Returns

new protocol state

### Function

void get_status (struct proto * p, byte * buf) -- get instance status

### Arguments

struct proto * p

  protocol instance

byte * buf

  buffer to be filled with the status string

### Description

This hook is called by the core if it wishes to obtain an brief one-line user friendly representation of the status of the instance to be printed by the <cf/show protocols/ command.

### Function

void get_route_info (rte * e, byte * buf, ea_list * attrs) -- get route information

### Arguments

rte * e

  a route entry

byte * buf

  buffer to be filled with the resulting string

ea_list * attrs

  extended attributes of the route

### Description

This hook is called to fill the buffer buf with a brief user friendly representation of metrics of a route belonging to this protocol.

### Function

int get_attr (eattr * a, byte * buf, int buflen) -- get attribute information

### Arguments

eattr * a

  an extended attribute

byte * buf

  buffer to be filled with attribute information

int buflen

  -- undescribed --

### Description

The get_attr() hook is called by the core to obtain a user friendly representation of an extended route attribute. It can either leave the whole conversion to the core (by returning GA_UNKNOWN), fill in only attribute name (and let the core format the attribute value automatically according to the type field; by returning GA_NAME) or doing the whole conversion (used in case the value requires extra care; return GA_FULL).

### Function

void if_notify (struct proto * p, unsigned flags, struct iface * i) -- notify instance about interface changes

### Arguments

struct proto * p

  protocol instance

unsigned flags

  interface change flags

struct iface * i

  the interface in question

### Description

This hook is called whenever any network interface changes its status. The change is described by a combination of status bits (IF_CHANGE_xxx) in the flags parameter.

### Function

void ifa_notify (struct proto * p, unsigned flags, struct ifa * a) -- notify instance about interface address changes

### Arguments

struct proto * p

  protocol instance

unsigned flags

  address change flags

struct ifa * a

  the interface address

### Description

This hook is called to notify the protocol instance about an interface acquiring or losing one of its addresses. The change is described by a combination of status bits (IF_CHANGE_xxx) in the flags parameter.

### Function

void rt_notify (struct proto * p, net * net, rte * new, rte * old, ea_list * attrs) -- notify instance about routing table change

### Arguments

struct proto * p

  protocol instance

net * net

  a network entry

rte * new

  new route for the network

rte * old

  old route for the network

ea_list * attrs

  extended attributes associated with the new entry

### Description

The rt_notify() hook is called to inform the protocol instance about changes in the connected routing table table, that is a route old belonging to network net being replaced by a new route new with extended attributes attrs. Either new or old or both can be NULL if the corresponding route doesn't exist.

If the type of route announcement is RA_OPTIMAL, it is an announcement of optimal route change, new stores the new optimal route and old stores the old optimal route.

If the type of route announcement is RA_ANY, it is an announcement of any route change, new stores the new route and old stores the old route from the same protocol.

p->accept_ra_types specifies which kind of route announcements protocol wants to receive.

### Function

void neigh_notify (neighbor * neigh) -- notify instance about neighbor status change

### Arguments

neighbor * neigh

  a neighbor cache entry

### Description

The neigh_notify() hook is called by the neighbor cache whenever a neighbor changes its state, that is it gets disconnected or a sticky neighbor gets connected.

### Function

ea_list * make_tmp_attrs (rte * e, struct linpool * pool) -- convert embedded attributes to temporary ones

### Arguments

rte * e

  route entry

struct linpool * pool

  linear pool to allocate attribute memory in

### Description

This hook is called by the routing table functions if they need to convert the protocol attributes embedded directly in the rte to temporary extended attributes in order to distribute them to other protocols or to filters. make_tmp_attrs() creates an ea_list in the linear pool pool, fills it with values of the temporary attributes and returns a pointer to it.

### Function

void store_tmp_attrs (rte * e, ea_list * attrs) -- convert temporary attributes to embedded ones

### Arguments

rte * e

  route entry

ea_list * attrs

  temporary attributes to be converted

### Description

This hook is an exact opposite of make_tmp_attrs() -- it takes a list of extended attributes and converts them to attributes embedded in the rte corresponding to this protocol.

You must be prepared for any of the attributes being missing from the list and use default values instead.

### Function

int import_control (struct proto * p, rte ** e, ea_list ** attrs, struct linpool * pool) -- pre-filtering decisions on route import

### Arguments

struct proto * p

  protocol instance the route is going to be imported to

rte ** e

  the route in question

ea_list ** attrs

  extended attributes of the route

struct linpool * pool

  linear pool for allocation of all temporary data

### Description

The import_control() hook is called as the first step of a exporting a route from a routing table to the protocol instance. It can modify route attributes and force acceptance or rejection of the route regardless of user-specified filters. See rte_announce() for a complete description of the route distribution process.

The standard use of this hook is to reject routes having originated from the same instance and to set default values of the protocol's metrics.

### Result

-1 if the route has to be accepted, 1 if rejected and 0 if it should be passed to the filters.

### Function

int rte_better (rte * new, rte * old) -- compare metrics of two routes

### Arguments

rte * new

  the new route

rte * old

  the original route

### Description

This hook gets called when the routing table contains two routes for the same network which have originated from different instances of a single protocol and it wants to select which one is preferred over the other one. Protocols usually decide according to route metrics.

### Result

1 if new is better (more preferred) than old, 0 otherwise.

### Function

int rte_same (rte * e1, rte * e2) -- compare two routes

### Arguments

rte * e1

  route

rte * e2

  route

### Description

The rte_same() hook tests whether the routes e1 and e2 belonging to the same protocol instance have identical contents. Contents of rta, all the extended attributes and rte preference are checked by the core code, no need to take care of them here.

### Result

1 if e1 is identical to e2, 0 otherwise.

### Function

void rte_insert (net * n, rte * e) -- notify instance about route insertion

### Arguments

net * n

  network

rte * e

  route

### Description

This hook is called whenever a rte belonging to the instance is accepted for insertion to a routing table.

Please avoid using this function in new protocols.

### Function

void rte_remove (net * n, rte * e) -- notify instance about route removal

### Arguments

net * n

  network

rte * e

  route

### Description

This hook is called whenever a rte belonging to the instance is removed from a routing table.

Please avoid using this function in new protocols.

## 2.6 Interfaces

The interface module keeps track of all network interfaces in the system and their addresses.

Each interface is represented by an iface structure which carries interface capability flags (IF_MULTIACCESS, IF_BROADCAST etc.), MTU, interface name and index and finally a linked list of network prefixes assigned to the interface, each one represented by struct ifa.

The interface module keeps a `soft-up' state for each iface which is a conjunction of link being up, the interface being of a `sane' type and at least one IP address assigned to it.

### Function

void ifa_dump (struct ifa * a) -- dump interface address

### Arguments

struct ifa * a

  interface address descriptor

### Description

This function dumps contents of an ifa to the debug output.

### Function

void if_dump (struct iface * i) -- dump interface

### Arguments

struct iface * i

  interface to dump

### Description

This function dumps all information associated with a given network interface to the debug output.

### Function

void if_dump_all (void) -- dump all interfaces

### Description

This function dumps information about all known network interfaces to the debug output.

### Function

struct iface * if_update (struct iface * new) -- update interface status

### Arguments

struct iface * new

  new interface status

### Description

if_update() is called by the low-level platform dependent code whenever it notices an interface change.

There exist two types of interface updates -- synchronous and asynchronous ones. In the synchronous case, the low-level code calls if_start_update(), scans all interfaces reported by the OS, uses if_update() and ifa_update() to pass them to the core and then it finishes the update sequence by calling if_end_update(). When working asynchronously, the sysdep code calls if_update() and ifa_update() whenever it notices a change.

if_update() will automatically notify all other modules about the change.

### Function

void if_feed_baby (struct proto * p) -- advertise interfaces to a new protocol

### Arguments

struct proto * p

  protocol to feed

### Description

When a new protocol starts, this function sends it a series of notifications about all existing interfaces.

### Function

struct iface * if_find_by_index (unsigned idx) -- find interface by ifindex

### Arguments

unsigned idx

  ifindex

### Description

This function finds an iface structure corresponding to an interface of the given index idx. Returns a pointer to the structure or NULL if no such structure exists.

### Function

struct iface * if_find_by_name (char * name) -- find interface by name

### Arguments

char * name

  interface name

### Description

This function finds an iface structure corresponding to an interface of the given name name. Returns a pointer to the structure or NULL if no such structure exists.

### Function

struct ifa * ifa_update (struct ifa * a) -- update interface address

### Arguments

struct ifa * a

  new interface address

### Description

This function adds address information to a network interface. It's called by the platform dependent code during the interface update process described under if_update().

### Function

void ifa_delete (struct ifa * a) -- remove interface address

### Arguments

struct ifa * a

  interface address

### Description

This function removes address information from a network interface. It's called by the platform dependent code during the interface update process described under if_update().

### Function

void if_init (void) -- initialize interface module

### Description

This function is called during BIRD startup to initialize all data structures of the interface module.

## 2.7 Neighbor cache

Most routing protocols need to associate their internal state data with neighboring routers, check whether an address given as the next hop attribute of a route is really an address of a directly connected host and which interface is it connected through. Also, they often need to be notified when a neighbor ceases to exist or when their long awaited neighbor becomes connected. The neighbor cache is there to solve all these problems.

The neighbor cache maintains a collection of neighbor entries. Each entry represents one IP address corresponding to either our directly connected neighbor or our own end of the link (when the scope of the address is set to SCOPE_HOST) together with per-neighbor data belonging to a single protocol.

Active entries represent known neighbors and are stored in a hash table (to allow fast retrieval based on the IP address of the node) and two linked lists: one global and one per-interface (allowing quick processing of interface change events). Inactive entries exist only when the protocol has explicitly requested it via the NEF_STICKY flag because it wishes to be notified when the node will again become a neighbor. Such entries are enqueued in a special list which is walked whenever an interface changes its state to up.

When a neighbor event occurs (a neighbor gets disconnected or a sticky inactive neighbor becomes connected), the protocol hook neigh_notify() is called to advertise the change.

### Function

neighbor * neigh_find (struct proto * p, ip_addr * a, unsigned flags) -- find or create a neighbor entry.

### Arguments

struct proto * p

  protocol which asks for the entry.

ip_addr * a

  pointer to IP address of the node to be searched for.

unsigned flags

  0 or NEF_STICKY if you want to create a sticky entry.

### Description

Search the neighbor cache for a node with given IP address. If it's found, a pointer to the neighbor entry is returned. If no such entry exists and the node is directly connected on one of our active interfaces, a new entry is created and returned to the caller with protocol-dependent fields initialized to zero. If the node is not connected directly or *a is not a valid unicast IP address, neigh_find() returns NULL.

### Function

void neigh_dump (neighbor * n) -- dump specified neighbor entry.

### Arguments

neighbor * n

  the entry to dump

### Description

This functions dumps the contents of a given neighbor entry to debug output.

### Function

void neigh_dump_all (void) -- dump all neighbor entries.

### Description

This function dumps the contents of the neighbor cache to debug output.

### Function

void neigh_if_up (struct iface * i)

### Arguments

struct iface * i

  interface in question

### Description

Tell the neighbor cache that a new interface became up.

The neighbor cache wakes up all inactive sticky neighbors with addresses belonging to prefixes of the interface i.

### Function

void neigh_if_down (struct iface * i) -- notify neighbor cache about interface down event

### Arguments

struct iface * i

  the interface in question

### Description

Notify the neighbor cache that an interface has ceased to exist.

It causes all entries belonging to neighbors connected to this interface to be flushed.

### Function

void neigh_prune (void) -- prune neighbor cache

### Description

neigh_prune() examines all neighbor entries cached and removes those corresponding to inactive protocols. It's called whenever a protocol is shut down to get rid of all its heritage.

### Function

void neigh_init (pool * if_pool) -- initialize the neighbor cache.

### Arguments

pool * if_pool

  resource pool to be used for neighbor entries.

### Description

This function is called during BIRD startup to initialize the neighbor cache module.

## 2.8 Command line interface

This module takes care of the BIRD's command-line interface (CLI). The CLI exists to provide a way to control BIRD remotely and to inspect its status. It uses a very simple textual protocol over a stream connection provided by the platform dependent code (on UNIX systems, it's a UNIX domain socket).

Each session of the CLI consists of a sequence of request and replies, slightly resembling the FTP and SMTP protocols. Requests are commands encoded as a single line of text, replies are sequences of lines starting with a four-digit code followed by either a space (if it's the last line of the reply) or a minus sign (when the reply is going to continue with the next line), the rest of the line contains a textual message semantics of which depends on the numeric code. If a reply line has the same code as the previous one and it's a continuation line, the whole prefix can be replaced by a single white space character.

Reply codes starting with 0 stand for `action successfully completed' messages, 1 means `table entry', 8 `runtime error' and 9 `syntax error'.

Each CLI session is internally represented by a cli structure and a resource pool containing all resources associated with the connection, so that it can be easily freed whenever the connection gets closed, not depending on the current state of command processing.

The CLI commands are declared as a part of the configuration grammar by using the `CF_CLI` macro. When a command is received, it is processed by the same lexical analyzer and parser as used for the configuration, but it's switched to a special mode by prepending a fake token to the text, so that it uses only the CLI command rules. Then the parser invokes an execution routine corresponding to the command, which either constructs the whole reply and returns it back or (in case it expects the reply will be long) it prints a partial reply and asks the CLI module (using the cont hook) to call it again when the output is transferred to the user.

The this_cli variable points to a cli structure of the session being currently parsed, but it's of course available only in command handlers not entered using the cont hook.

TX buffer management works as follows: At cli.tx_buf there is a list of TX buffers (struct cli_out), cli.tx_write is the buffer currently used by the producer (cli_printf(), cli_alloc_out()) and cli.tx_pos is the buffer currently used by the consumer (cli_write(), in system dependent code). The producer uses cli_out.wpos ptr as the current write position and the consumer uses cli_out.outpos ptr as the current read position. When the producer produces something, it calls cli_write_trigger(). If there is not enough space in the current buffer, the producer allocates the new one. When the consumer processes everything in the buffer queue, it calls cli_written(), tha frees all buffers (except the first one) and schedules cli.event .

### Function

void cli_printf (cli * c, int code, char * msg, ... ...) -- send reply to a CLI connection

### Arguments

cli * c

  CLI connection

int code

  numeric code of the reply, negative for continuation lines

char * msg

  a printf()-like formatting string.

... ...

  variable arguments

### Description

This function send a single line of reply to a given CLI connection. In works in all aspects like bsprintf() except that it automatically prepends the reply line prefix.

Please note that if the connection can be already busy sending some data in which case cli_printf() stores the output to a temporary buffer, so please avoid sending a large batch of replies without waiting for the buffers to be flushed.

If you want to write to the current CLI output, you can use the cli_msg() macro instead.

### Function

void cli_init (void) -- initialize the CLI module

### Description

This function is called during BIRD startup to initialize the internal data structures of the CLI module.

## 2.9 Object locks

The lock module provides a simple mechanism for avoiding conflicts between various protocols which would like to use a single physical resource (for example a network port). It would be easy to say that such collisions can occur only when the user specifies an invalid configuration and therefore he deserves to get what he has asked for, but unfortunately they can also arise legitimately when the daemon is reconfigured and there exists (although for a short time period only) an old protocol instance being shut down and a new one willing to start up on the same interface.

The solution is very simple: when any protocol wishes to use a network port or some other non-shareable resource, it asks the core to lock it and it doesn't use the resource until it's notified that it has acquired the lock.

Object locks are represented by object_lock structures which are in turn a kind of resource. Lockable resources are uniquely determined by resource type (OBJLOCK_UDP for a UDP port etc.), IP address (usually a broadcast or multicast address the port is bound to), port number and interface.

### Function

struct object_lock * olock_new (pool * p) -- create an object lock

### Arguments

pool * p

  resource pool to create the lock in.

### Description

The olock_new() function creates a new resource of type object_lock and returns a pointer to it. After filling in the structure, the caller should call olock_acquire() to do the real locking.

### Function

void olock_acquire (struct object_lock * l) -- acquire a lock

### Arguments

struct object_lock * l

  the lock to acquire

### Description

This function attempts to acquire exclusive access to the non-shareable resource described by the lock l. It returns immediately, but as soon as the resource becomes available, it calls the hook() function set up by the caller.

When you want to release the resource, just rfree() the lock.

### Function

void olock_init (void) -- initialize the object lock mechanism

### Description

This function is called during BIRD startup. It initializes all the internal data structures of the lock module.

Next Previous Contents