diff options
-rw-r--r-- | doc/prog-proto.sgml | 91 | ||||
-rw-r--r-- | nest/Doc | 4 | ||||
-rw-r--r-- | nest/proto.c | 119 |
3 files changed, 213 insertions, 1 deletions
diff --git a/doc/prog-proto.sgml b/doc/prog-proto.sgml new file mode 100644 index 00000000..ab90b7a4 --- /dev/null +++ b/doc/prog-proto.sgml @@ -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: @@ -2,8 +2,10 @@ H Core S rt-fib.c S rt-table.c S rt-attr.c +D prog-proto.sgml +S proto.c +#S proto-hooks.c S neighbor.c #S cli.c #S iface.c S locks.c -#S proto.c diff --git a/nest/proto.c b/nest/proto.c index 5ec793ed..82756384 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -85,6 +85,20 @@ proto_relink(struct proto *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 * proto_new(struct proto_config *c, unsigned size) { @@ -116,6 +130,20 @@ proto_init_instance(struct proto *p) 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 * proto_add_announce_hook(struct proto *p, struct rtable *t) { @@ -144,6 +172,19 @@ proto_flush_hooks(struct proto *p) 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 * proto_config_new(struct protocol *pr, unsigned size) { @@ -159,6 +200,14 @@ proto_config_new(struct protocol *pr, unsigned size) 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 protos_preconfig(struct config *c) { @@ -176,6 +225,13 @@ protos_preconfig(struct config *c) 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 protos_postconfig(struct config *c) { @@ -207,6 +263,31 @@ proto_init(struct proto_config *c) 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 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 protos_dump_all(void) { @@ -360,6 +450,14 @@ protos_dump_all(void) 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 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 protos_build(void) { @@ -441,6 +548,18 @@ proto_feed(void *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 proto_notify_state(struct proto *p, unsigned ps) { |