Commit 58f7d004 authored by Martin Mareš's avatar Martin Mareš

Fixes to the progdoc.

parent 38203d78
......@@ -10,12 +10,12 @@
* DOC: Lexical analyzer
*
* The lexical analyzer used for configuration files and CLI commands
* is generated using the |flex| tool accompanied with a couple of
* is generated using the |flex| tool accompanied by a couple of
* functions maintaining the hash tables containing information about
* symbols and keywords.
*
* Each symbol is represented by a &symbol structure containing name
* of the symbol, its scope, symbol class (%SYM_PROTO for a name of a protocol,
* of the symbol, its lexical scope, symbol class (%SYM_PROTO for a name of a protocol,
* %SYM_NUMBER for a numeric constant etc.) and class dependent data.
* When an unknown symbol is encountered, it's automatically added to the
* symbol table with class %SYM_VOID.
......@@ -454,7 +454,7 @@ cf_symbol_class_name(struct symbol *sym)
* the |gen_parser.m4| script.
*
* Grammar snippets are files (usually with extension |.Y|) contributed
* by various BIRD modules to provide information about syntax of their
* by various BIRD modules in order to provide information about syntax of their
* configuration and their CLI commands. Each snipped consists of several
* section, each of them starting with a special keyword: |CF_HDR| for
* a list of |#include| directives needed by the C code, |CF_DEFINES|
......
......@@ -9,9 +9,9 @@
/**
* DOC: Configuration manager
*
* Configuration of BIRD is complex, but straightforward. There exist three
* Configuration of BIRD is complex, yet straightforward. There exist three
* modules taking care of the configuration: config manager (which takes care
* of storage of config information and controls switching between configs),
* of storage of the config information and controls switching between configs),
* lexical analyzer and parser.
*
* The configuration manager stores each config as a &config structure
......@@ -27,7 +27,7 @@
*
* Loading of new configuration is very simple: just call config_alloc()
* to get a new &config structure, then use config_parse() to parse a
* configuration file and fill all information in the structure
* configuration file and fill all fields of the structure
* and finally ask the config manager to switch to the new
* config by calling config_commit().
*
......
......@@ -2,12 +2,12 @@
<sect>Introduction
<p>This document describes the internal workings of the BIRD, its architecture,
<p>This document describes the internal workings of BIRD, its architecture,
design decisions and rationale behind them. It also contains documentation on
all the essential components of the system and their interfaces.
<p>Routing daemons are very complicated things which need to act in real time
to complex sequences external events, react correctly even to the most erroneous behavior
to complex sequences of external events, respond correctly even to the most erroneous behavior
of their environment and still handle enormous amount of data with reasonable
speed. Due to all of this, their design is very tricky as one needs to carefully
balance between efficiency, stability and (last, but not least) simplicity of
......@@ -21,7 +21,7 @@ by the program source itself together with comments contained therein.
<p>When planning the architecture of BIRD, we've taken a close look at the other existing routing
daemons and also at some of the operating systems used on dedicated routers, gathered all important
features and added lots of new ones to overcome their shortcomings and better match the requirements
features and added lots of new ones to overcome their shortcomings and to better match the requirements
of routing in today's Internet: IPv6, policy routing, route filtering and so on. From this
planning, the following set of design goals has arisen:
......@@ -36,8 +36,8 @@ This leads to abstraction of IP addresses and operations on them.
<item><it>Minimize OS dependent code to make porting as easy as possible.</it>
Unfortunately, such code cannot be avoided at all as the details of communication with
the IP stack differ from OS to OS and they often vary even between different
versions of the same OS, but we can isolate such code in special modules and
do the porting by changing just these modules.
versions of the same OS. But we can isolate such code in special modules and
do the porting by changing or replacing just these modules.
Also, don't rely on specific features of various operating systems, but be able
to make use of them if they are available.
......@@ -62,7 +62,7 @@ to read the new configuration and smoothly adapt to it without disturbing parts
the routing process which are not affected by the change.
<item><it>Be able to be controlled online.</it>
In addition to online reconfiguration, a routing daemon should be able to communicate
In addition to the online reconfiguration, a routing daemon should be able to communicate
with the user and with many other programs (primarily scripts used for network maintenance)
in order to make it possible to inspect contents of routing tables, status of all
routing protocols and also to control their behavior (i.e., it should be possible
......@@ -71,7 +71,7 @@ this, we implement a simple command-line protocol based on those used by FTP and
(that is textual commands and textual replies accompanied by a numeric code which makes
them both readable to a human and easy to recognize in software).
<item><it>Respond to all protocol events in real time.</it>
<item><it>Respond to all events in real time.</it>
A typical solution to this problem is to use lots of threads to separate the workings
of all the routing protocols and also of the user interface parts and to hope that
the scheduler will assign time to them in a fair enough manner. This is surely a good
......@@ -88,18 +88,18 @@ the following types of modules:
<descrip>
<tagp>Core modules</tagp> implement the core functions of BIRD as taking care
<tagp>Core modules</tagp> implement the core functions of BIRD: taking care
of routing tables, keeping protocol status, interacting with the user using
the Command-Line Interface (to be called CLI in the rest of this document)
etc.
<tagp>Library modules</tagp> form a large set of various library functions
implementing several data abstractions, utility functions and also functions
which are a part of standard libraries on some systems, but missing on other
which are a part of the standard libraries on some systems, but missing on other
ones.
<tagp>Resource management modules</tagp> take care of resources, their allocation
and automatic freeing when the module having requested them ceases to exist.
and automatic freeing when the module having requested shuts itself down.
<tagp>Configuration modules</tagp> are fragments of lexical analyzer,
grammar rules and the corresponding snippets of C code. For each group
......@@ -120,7 +120,7 @@ interface to the CLI.
<sect>Implementation
<p>BIRD has been written in GNU C. We've considered using of C++, but we've
<p>BIRD has been written in GNU C. We've considered using C++, but we've
preferred the simplicity and straightforward nature of C which gives us fine
control over all implementation details and on the other hand enough
instruments to build the abstractions we need.
......
......@@ -13,12 +13,10 @@
* Since BIRD is single-threaded, it requires long lasting tasks to be split to smaller
* parts, so that no module can monopolize the CPU. To split such a task, just create
* an &event resource, point it to the function you want to have called and call ev_schedule()
* to ask the core to run the event when nothing more important will require attention.
* to ask the core to run the event when nothing more important requires attention.
*
* You can also define your own event lists (the &event_list structure), enqueue your
* events in them and explicitly ask to run them.
*
* The actual implementation is system dependent.
*/
#include "nest/bird.h"
......
......@@ -21,7 +21,7 @@ modules of BIRD, deallocates everything automatically when a module
shuts down and it's is able to print out the list of resources and
the corresponding modules they are allocated by.
<p>Each allocated resource (and from now we'll speak about allocated
<p>Each allocated resource (from now we'll speak about allocated
resources only) is represented by a structure starting with a standard
header (struct <struct/resource/) consisting of a list node (resources are
often linked to various lists) and a pointer to <struct/resclass/ -- a resource
......
......@@ -19,10 +19,10 @@
* constructors and destructors.
*
* When the |DEBUGGING| switch is turned on, we automatically fill all
* newly allocated and freed blocks with a special patterns to make detection
* newly allocated and freed blocks with a special pattern to make detection
* of use of uninitialized or already freed memory easier.
*
* Example: Nodes of a FIB are allocated from a Slab.
* Example: Nodes of a FIB are allocated from a per-FIB Slab.
*/
#include <stdlib.h>
......
......@@ -26,12 +26,12 @@
* a continuation line, the whole prefix can be replaced by a single
* white space character.
*
* Reply codes starting with 0 describe `action successfully completed' messages,
* 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 closes, not depending
* 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
......@@ -40,9 +40,9 @@
* 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 or (in case it expects the reply will be long)
* the whole reply and returns 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 will be transferred to the user.
* 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
......
......@@ -15,14 +15,14 @@
* 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 being shut down and a new one
* 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 doesn't
* 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 which is in turn a kind of
* 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.
......
......@@ -20,17 +20,17 @@
* 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 data belonging to a
* 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 IP address of the node) and
* 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 becomes up.
* 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()
......
......@@ -9,7 +9,7 @@
/**
* DOC: Protocol hooks
*
* Each protocol provides a rich set of hook functions referred to by pointers
* 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
......
......@@ -67,7 +67,7 @@ the following states:
<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>At any time, the core code can ask the protocol to shut itself 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
......
......@@ -21,7 +21,7 @@
* 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 buckets are sorted according to the primary hash
* 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.
*
......@@ -400,7 +400,7 @@ fit_put(struct fib_iterator *i, struct fib_node *n)
* @f: FIB to be checked
*
* This debugging function audits a FIB by checking its internal consistency.
* Use when you suspect somebody from corrupting innocent data structures.
* Use when you suspect somebody of corrupting innocent data structures.
*/
void
fib_check(struct fib *f)
......
......@@ -16,7 +16,7 @@
* There exist 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)
* destination networks. For each network (represented by structure &net),
* there is a one-way linked list of network entries (&rte), the first entry
* on the list being the best possible one (i.e., the one we currently use
* for routing), the order of the other ones is undetermined.
......
......@@ -21,7 +21,7 @@
* many connections, but not too much and, which is more important, it makes
* BGP much easier to implement.
*
* Each instance of BGP (corresponding to one BGP peer) is described by a &bgp_proto
* Each instance of BGP (corresponding to a single BGP peer) is described by a &bgp_proto
* structure to which are attached individual connections represented by &bgp_connection
* (usually, there exists only one connection, but during BGP session setup, there
* can be more of them). The connections are handled according to the BGP state machine
......@@ -39,7 +39,7 @@
* immediately instead of sending both updates). There also exists a special bucket holding
* all the route withdrawals which cannot be queued anywhere else as they don't have any
* attributes. If we have any packet to send (due to either new routes or the connection
* tracking code wanting to send a Open, KeepAlive or Notification message), we call
* tracking code wanting to send a Open, Keepalive or Notification message), we call
* bgp_schedule_packet() which sets the corresponding bit in a @packet_to_send
* bit field in &bgp_conn and as soon as the transmit socket buffer becomes empty,
* we call bgp_fire_tx(). It inspects state of all the packet type bits and calls
......
......@@ -18,29 +18,30 @@
*/
/**
* DOC: Routing information protocol
* DOC: Routing Information Protocol
*
* Rip is pretty simple protocol so half of this code is interface
* with core. We maintain our own linked list of &rip_entry -- it serves
* as our small routing table. Rip never adds into this linked list at
* packet reception; instead, it lets core know about data from packet,
* and waits for core to call our rip_rte_notify.
* RIP is a pretty simple protocol, so about a half of its code is interface
* with the core.
*
* Within rip_tx(), this list is
* walked, and packet is generated using rip_tx_prepare(). This gets
* We maintain our own linked list of &rip_entry structures -- it serves
* as our small routing table. RIP never adds to this linked list upon
* packet reception; instead, it lets the core know about data from the packet
* and waits for the core to call rip_rte_notify().
*
* Within rip_tx(), the list is
* walked and a packet is generated using rip_tx_prepare(). This gets
* tricky because we may need to send more than one packet to one
* destination. Struct &rip_connection is used to hold info such as how
* many of &rip_entry's we already send, and is also used to protect
* from two concurrent sends to one destination. Each &rip_interface has
* destination. Struct &rip_connection is used to hold context information such as how
* many of &rip_entry's we have already sent and it's also used to protect
* against two concurrent sends to one destination. Each &rip_interface has
* at most one &rip_connection.
*
* We are not going to honor requests for sending part of
* routing table. That would need to turn split horizon off,
* etc.
* routing table. That would need to turn split horizon off etc.
*
* Triggered updates. RFC says: when triggered update was sent, don't send
* new one for something between 1 and 5 seconds (and send one
* after that). We do something else: once in 5 second
* About triggered updates, RFC says: when a triggered update was sent,
* don't send a new one for something between 1 and 5 seconds (and send one
* after that). We do something else: each 5 seconds,
* we look for any changed routes and broadcast them.
*/
......@@ -70,7 +71,7 @@ static struct rip_interface *new_iface(struct proto *p, struct iface *new, unsig
#define P_NAME p->name
/*
* DOC: Output processing
* Output processing
*
* This part is responsible for getting packets out to the network.
*/
......@@ -251,7 +252,7 @@ find_interface(struct proto *p, struct iface *what)
}
/*
* DOC: Input processing
* Input processing
*
* This part is responsible for any updates that come from network
*/
......@@ -466,7 +467,7 @@ rip_rx(sock *s, int size)
}
/*
* DOC: Interface to bird core
* Interface to BIRD core
*/
static void
......@@ -482,10 +483,10 @@ rip_dump_entry( struct rip_entry *e )
* @t: timer
*
* Broadcast routing tables periodically (using rip_tx) and kill
* routes that are too old. Rip keeps its own entries in main routing
* table linked by link list (functions rip_rte_insert() and
* rip_rte_delete() are responsible for that), walks this list in timer
* and in case entry is too old, it is discarded.
* routes that are too old. RIP keeps a list of its own entries present
* in the core table by a linked list (functions rip_rte_insert() and
* rip_rte_delete() are responsible for that), it walks this list in the timer
* and in case an entry is too old, it is discarded.
*/
static void
......@@ -636,13 +637,13 @@ kill_iface(struct proto *p, struct rip_interface *i)
/**
* new_iface
* @p: myself
* @new: interface to be created or %NULL if we are creating magic
* socket. Magic socket is used for listening, and is also used for
* sending requested responses.
* @new: interface to be created or %NULL if we are creating a magic
* socket. The magic socket is used for listening and also for
* sending requested responses.
* @flags: interface flags
* @patt: pattern this interface matched, used for access to config options
*
* actually create struct interface and start listening to it
* Create an interface structure and start listening on the interface.
*/
static struct rip_interface *
new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt )
......
......@@ -78,11 +78,11 @@ tracked_fopen(pool *p, char *name, char *mode)
*
* Timers are resources which represent a wish of a module to call
* a function at the specified time. The platform dependent code
* doesn't guarantee the exact timing, only that a timer function
* doesn't guarantee exact timing, only that a timer function
* won't be called before the requested time.
*
* In BIRD, real time is represented by values of the &bird_clock_t type
* which are integral numbers corresponding to a number of seconds since
* which are integral numbers interpreted as a number of seconds since
* a fixed (but platform dependent) epoch. The current time can be read
* from a variable @now with reasonable accuracy.
*
......
......@@ -26,14 +26,14 @@
* separate KRT protocols which cooperate with each other [Linux 2.2].
* In this case, we keep only a single scan timer.
*
* We use FIB node flags to keep track of route synchronization status. We also
* attach temporary &rte's to the routing tables, but it cannot harm the rest of
* BIRD since table synchronization is an atomic process.
* We use FIB node flags in the routing table to keep track of route
* synchronization status. We also attach temporary &rte's to the routing table,
* but it cannot do any harm to the rest of BIRD since table synchronization is
* an atomic process.
*
* When starting up, we cheat by looking if there is another
* KRT instance to be initialized later and performing table scan
* only once for all the instances.
*/
* only once for all the instances. */
/*
* If you are brave enough, continue now. You cannot say you haven't been warned.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment