To read about an overview of how the policy module works, see here.

Policy module type declarations

type dest_mask_internal

This is an internal node in a Patricia tree of policy expressions. The tree is traversed based on a network address and mask. The node contains the byte number within the address and the bit number within the byte to test when the traversal reaches this node.

type dest_mask

This structure is stored in a union in each adv_entry. It is used to specify the destination address and mask that matches a particular policy expression.

type rtq_entry

This structure forms part of each route entry, rt_entry. This structure is used to doubly link together a number of different route entries through this structure. In addition, this structure is stored in each gw_entry. It is used as the head of a doubly linked list of route entries.

type gw_entry

This structure forms part of a BGP peer descriptor block, the bgpPeer. It contains most of the peer specific information, including the peer's address, the peer AS numbers, the list of routes received from the peer and the peer import and export policies.

type adv_results

This structure stores the results of a policy search and is part of each control list element adv_entry. The values stored include a metric and a preference and some flags. It is used as well as an in-out argument to the policy enforcement routine to return the results of a policy check on a given route.

type config_entry

This structure, a list of which is contained in each control list element adv_entry, stores the configured preference associated with a policy expression.

type config_entry

A singly-linked list of config_entry elements.

type adv_entry

This is a single control list element. A single route filter in the policy expression language maps onto one adv_entry. A single adv_entry may specify for example, that a route entry must match a destination and mask, and an AS path and other AS specific data. The adv_list field specifies which of these conjunctive matches must hold for a match to occur in a single adv_entry.

Policy module macros

macro DMI_WALK

Perform a depth first search of the Patricia tree, storing untaken branches in a stack and then unwinding the stack when a leaf node has been reached. This macro is used to start a loop whenever a DFS traversal of the tree is necessary.

macro DMI_WALK_END

End the loop started by DMI_WALK.

macro DMI_WALK_ALL

Perform a depth first search of the Patricia tree, and in addition, at each internal node, traverse the list of adv_entries.

macro DMI_WALK_ALL_END

End the loop started by DMI_WALK_ALL.

macro RTQ_*

This set of macros permits manipulation of the rtq_entrys and lists of such entries. Such manipulations include finding the superstructure (e.g. rt_entry) to which this entry belongs, sequential traversal of such a list and so on.

Policy module function definitions

function adv_destmask_insert()

Called when the policy specifications are being parsed, to insert a control list element into the Patricia tree. The basic algorithm is as follows: search down the tree until we reach a dead-end or an internal node with a bitmask greater than ours. If we reach a dead-end, we have to create an internal node at the dead-end. If we have passed our appropriate position in the tree, we create a split in the tree above the node where we stopped.

function adv_destmask_match()

Called when we need to locate the list of policies governing a particular destination address and mask. Given a list of control list elements (adv_entrys), locate the root of the Patricia tree corresponding to that list. Search down the tree with the given destination and mask until either the mask is exhausted or we have reached a dead-end. Store all intermediate visited nodes in a stack. Depending on whether a refined or exact match is to be performed, wrap back the stack until the appropriate internal node is found. Return the corresponding adv_entry.

function adv_aggregate_match()

Called from rt_aggregate_match(). Given a route, traverse the Patricia tree to find out the longest match on the routes destination and mask. Test to see if the route passes the filters in the adv_entrys. Such a route can probably be aggregated into the less specific route.

function adv_destmask_free_list()

Walk through the entire tree and from each internal node, delete every element of the attached control list.

function adv_destmask_finish()

During configuration parsing, the list of adv_entrys is built up as is read from the configuration file. We actually want the adv_entrys to be listed in the order in which they appear in the Patricia tree and for each adv_entry to contain a pointer to the root of the tree. This function, called at the end of policy expression parsing, achieves that.

function adv_destmask_depth()

Do a complete tree traversal to compute the depth of each internal node of the tree. Sore this depth value in the metric field of the associated control list element adv_entry.

function adv_alloc()

Allocate a single adv_entry with the specified protocol and flags field.

function adv_free_list()

Called during cleanup of different protocol adv lists. Free each control list element and recursively, all its children (indicated by the adv_list field of the adv_entry).

function adv_cleanup()

Repeatedly call adv_free_list() on each of the specified lists.

function export()

Called when we want to verify if a route entry matches one of the export filters specified in a adv_entry list. For each element in the control list (i.e. traversing down the adv_next pointers of the adv_entry) check if the route's parameters matches the adv_entry's policy restrictions. We do this by traversing the adv_list pointers and checking for a match along each restriction (e.g. AS match, AS path match etc). Finally, the matching adv_list element might have a restriction on whether we are allowed to tell the peer this route's destination. We do a Patricia tree search for this.

function import()

Called to verify if we can add an incoming route to the GateD database. This code is similar to export(), with the only difference being that only a single level of lookup is necessary in the list of adv_entrys (figure out why).

function gw_lookup()

The parser maintains a list of gateways or peers defined so far. Given this list and an address and protocol, find a matching gw_entry in such a list of gateways.

function gw_add()

Given a gw_entry and a list of such entries, add this entry to the end of the list. Appropriately initialize the list.

function gw_locate()

Find a matching gw_entry in the specified list. If none exists, create an entry and add it to the list.

function gw_timestamp()

In addition to the parser, some protocols (e.g. HELLO) maintain their own list of gw_entrys. Update the timer on the matching gw_entry.

function gw_init()

Initialize a gw_entry if we are given one, otherwise create one.

function gw_freelist()

Walk down the specified list and free each gw_entry.

Functions related to config_entries

This code appears to be entirely used by the parser to store and process interface specifications. To be documented later.