mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 12:48:43 +00:00
Added documentation on protocols.
Protocol hooks deserve an extra chapter (to come soon).
This commit is contained in:
parent
e4ba0ec197
commit
3c6269b8fe
91
doc/prog-proto.sgml
Normal file
91
doc/prog-proto.sgml
Normal 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:
|
4
nest/Doc
4
nest/Doc
@ -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
|
|
||||||
|
119
nest/proto.c
119
nest/proto.c
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user