Added documentation on protocols.

Protocol hooks deserve an extra chapter (to come soon).
This commit is contained in:
Martin Mares 2000-06-02 13:42:36 +00:00
parent e4ba0ec197
commit 3c6269b8fe
3 changed files with 213 additions and 1 deletions

91
doc/prog-proto.sgml Normal file
View file

@ -0,0 +1,91 @@
<!--
BIRD Programmer's Guide: Protocols
(c) 2000 Martin Mares <mj@ucw.cz>
-->
<sect1>Routing protocols
<sect2>Introduction
<p>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 <tt/nest/ :-).
<p>When talking about protocols, one need to distinguish between <em/protocols/
and protocol <em/instances/. A protocol exists exactly once, not depending on whether
it's configured on 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.
<p>A protocol is represented by a <struct/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 <param/protocol_list/ list.
<p>Each instance has its own <struct/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 <struct/proto/ in
<tt/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 <struct/proto/). The instance is always linked in both the global instance list
(<param/proto_list/) and a per-status list (either <param/active_proto_list/ for
running protocols, <param/initial_proto_list/ for protocols being initialized or
<param/flush_proto_list/ when the protocol is being shut down).
<p>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 <func/proto_commit/ function.
<sect2>Protocol states
<p>As startup and shutdown of each protocol are complex processes which can be affected
by lots of external events (user's actions, reconfigurations, behaviour 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.
<p>The <em/protocol state machine/ corresponds to internal state of the protocol
and the protocol can alter its state whenever it wants to. There exist
the following states:
<descrip>
<tag/PS_DOWN/ The protocol is down and waits for being woken up by calling its
start() hook.
<tag/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.
<tag/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.
<tag/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).
</descrip>
<p>Unless the protocol is in the <tt/PS_DOWN/ state, it can decide to change
its state by calling the <func/proto_notify_state/ function.
<p>At any time, the core code can ask the protocol to shut down by calling its stop() hook.
<p>The <em/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 exist the following core states:
<descrip>
<tag/FS_HUNGRY/ The protocol is down, it doesn't have any routes and
doesn't want them.
<tag/FS_FEEDING/ The protocol has reached the <tt/PS_UP/ state, but
we are still busy sending the initial set of routes to it.
<tag/FS_HAPPY/ The protocol is up and has complete routing information.
<tag/FS_FLUSHING/ The protocol is shutting down (it's in either <tt/PS_STOP/
or <tt/PS_DOWN/ state) and we're flushing all of its routes from the
routing tables.
</descrip>
<sect2>Functions of the protocol module
<p>The protocol module provides the following functions:

View file

@ -2,8 +2,10 @@ H Core
S rt-fib.c S rt-fib.c
S rt-table.c S rt-table.c
S rt-attr.c S rt-attr.c
D prog-proto.sgml
S proto.c
#S proto-hooks.c
S neighbor.c S neighbor.c
#S cli.c #S cli.c
#S iface.c #S iface.c
S locks.c S locks.c
#S proto.c

View file

@ -85,6 +85,20 @@ proto_relink(struct proto *p)
proto_enqueue(l, p); proto_enqueue(l, p);
} }
/**
* proto_new - create a new protocol instance
* @c: protocol configuration
* @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)
*
* When a new configuration has been read in, the core code starts
* initializing all the protocol instandces 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.
*/
void * void *
proto_new(struct proto_config *c, unsigned size) proto_new(struct proto_config *c, unsigned size)
{ {
@ -116,6 +130,20 @@ proto_init_instance(struct proto *p)
rt_lock_table(p->table); rt_lock_table(p->table);
} }
/**
* proto_add_announce_hook - connect protocol to a routing table
* @p: protocol instance
* @t: routing table to connect to
*
* 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.
*/
struct announce_hook * struct announce_hook *
proto_add_announce_hook(struct proto *p, struct rtable *t) proto_add_announce_hook(struct proto *p, struct rtable *t)
{ {
@ -144,6 +172,19 @@ proto_flush_hooks(struct proto *p)
p->ahooks = NULL; p->ahooks = NULL;
} }
/**
* proto_config_new - create a new protocol configuration
* @pr: protocol the configuration will belong to
* @size: size of the structure including generic data
*
* 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.
*/
void * void *
proto_config_new(struct protocol *pr, unsigned size) proto_config_new(struct protocol *pr, unsigned size)
{ {
@ -159,6 +200,14 @@ proto_config_new(struct protocol *pr, unsigned size)
return c; return c;
} }
/**
* protos_preconfig - pre-configuration processing
* @c: new configuration
*
* This function calls the preconfig() hooks of all routing
* protocols available to prepare them for reading of the new
* configuration.
*/
void void
protos_preconfig(struct config *c) protos_preconfig(struct config *c)
{ {
@ -176,6 +225,13 @@ protos_preconfig(struct config *c)
DBG("\n"); DBG("\n");
} }
/**
* protos_postconfig - post-configuration processing
* @c: new configuration
*
* This function calls the postconfig() hooks of all protocol
* instances specified in configuration @c.
*/
void void
protos_postconfig(struct config *c) protos_postconfig(struct config *c)
{ {
@ -207,6 +263,31 @@ proto_init(struct proto_config *c)
return q; return q;
} }
/**
* protos_commit - commit new protocol configuration
* @new: new configuration
* @old: old configuration or %NULL if it's boot time config
* @force_reconfig: force restart of all protocols (used for example
* when the router ID changes)
*
* 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 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.
*/
void void
protos_commit(struct config *new, struct config *old, int force_reconfig) protos_commit(struct config *new, struct config *old, int force_reconfig)
{ {
@ -332,6 +413,15 @@ proto_rethink_goal(struct proto *p)
} }
} }
/**
* protos_dump_all - dump status of all protocols
*
* 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.
*/
void void
protos_dump_all(void) protos_dump_all(void)
{ {
@ -360,6 +450,14 @@ protos_dump_all(void)
debug(" flushing %s\n", p->name); debug(" flushing %s\n", p->name);
} }
/**
* proto_build - make a single protocol available
* @p: the protocol
*
* 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 infrom the core that they exist.
*/
void void
proto_build(struct protocol *p) proto_build(struct protocol *p)
{ {
@ -371,6 +469,15 @@ proto_build(struct protocol *p)
} }
} }
/**
* protos_build - build a protocol list
*
* 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.
*/
void void
protos_build(void) protos_build(void)
{ {
@ -441,6 +548,18 @@ proto_feed(void *P)
proto_feed_more(P); proto_feed_more(P);
} }
/**
* proto_notify_state - notify core about protocol state change
* @p: protocol the state of which has changed
* @ps: the new status
*
* 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.
*/
void void
proto_notify_state(struct proto *p, unsigned ps) proto_notify_state(struct proto *p, unsigned ps)
{ {