Next Previous Contents

3. Configuration

3.1 Configuration manager

Configuration of BIRD is complex, yet straightforward. There are three modules taking care of the configuration: config manager (which takes care 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 accompanied by a linear pool from which all information associated with the config and pointed to by the config structure is allocated.

There can exist up to four different configurations at one time: an active one (pointed to by config), configuration we are just switching from (old_config), one queued for the next reconfiguration (future_config; if it's non-NULL and the user wants to reconfigure once again, we just free the previous queued config and replace it with the new one) and finally a config being parsed (new_config).

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 fields of the structure and finally ask the config manager to switch to the new config by calling config_commit().

CLI commands are parsed in a very similar way -- there is also a stripped-down config structure associated with them and they are lex-ed and parsed by the same functions, only a special fake token is prepended before the command text to make the parser recognize only the rules corresponding to CLI commands.


Function

struct config * config_alloc (byte * name) -- allocate a new configuration

Arguments

byte * name

name of the config

Description

This function creates new config structure, attaches a resource pool and a linear memory pool to it and makes it available for further use. Returns a pointer to the structure.


Function

int config_parse (struct config * c) -- parse a configuration

Arguments

struct config * c

configuration

Description

config_parse() reads input by calling a hook function pointed to by cf_read_hook and parses it according to the configuration grammar. It also calls all the preconfig and postconfig hooks before, resp. after parsing.

Result

1 if the config has been parsed successfully, 0 if any error has occurred (such as anybody calling cf_error()) and the err_msg field has been set to the error message.


Function

int cli_parse (struct config * c) -- parse a CLI command

Arguments

struct config * c

temporary config structure

Description

cli_parse() is similar to config_parse(), but instead of a configuration, it parses a CLI command. See the CLI module for more information.


Function

void config_free (struct config * c) -- free a configuration

Arguments

struct config * c

configuration to be freed

Description

This function takes a config structure and frees all resources associated with it.


Function

int config_commit (struct config * c, int type) -- commit a configuration

Arguments

struct config * c

new configuration

int type

type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)

Description

When a configuration is parsed and prepared for use, the config_commit() function starts the process of reconfiguration. It checks whether there is already a reconfiguration in progress in which case it just queues the new config for later processing. Else it notifies all modules about the new configuration by calling their commit() functions which can either accept it immediately or call config_add_obstacle() to report that they need some time to complete the reconfiguration. After all such obstacles are removed using config_del_obstacle(), the old configuration is freed and everything runs according to the new one.

Result

CONF_DONE if the configuration has been accepted immediately, CONF_PROGRESS if it will take some time to switch to it, CONF_QUEUED if it's been queued due to another reconfiguration being in progress now or CONF_SHUTDOWN if BIRD is in shutdown mode and no new configurations are accepted.


Function

void order_shutdown (void) -- order BIRD shutdown

Description

This function initiates shutdown of BIRD. It's accomplished by asking for switching to an empty configuration.


Function

void cf_error (char * msg, ... ...) -- report a configuration error

Arguments

char * msg

printf-like format string

... ...

variable arguments

Description

cf_error() can be called during execution of config_parse(), that is from the parser, a preconfig hook or a postconfig hook, to report an error in the configuration.


Function

char * cfg_strdup (char * c) -- copy a string to config memory

Arguments

char * c

string to copy

Description

cfg_strdup() creates a new copy of the string in the memory pool associated with the configuration being currently parsed. It's often used when a string literal occurs in the configuration and we want to preserve it for further use.

3.2 Lexical analyzer

The lexical analyzer used for configuration files and CLI commands 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 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.

The keyword tables are generated from the grammar templates using the gen_keywords.m4 script.


Function

struct symbol * cf_find_symbol (byte * c) -- find a symbol by name

Arguments

byte * c

symbol name

Description

This functions searches the symbol table for a symbol of given name. First it examines the current scope, then the second recent one and so on until it either finds the symbol and returns a pointer to its symbol structure or reaches the end of the scope chain and returns NULL to signify no match.


Function

struct symbol * cf_define_symbol (struct symbol * sym, int type, void * def) -- define meaning of a symbol

Arguments

struct symbol * sym

symbol to be defined

int type

symbol class to assign

void * def

class dependent data

Description

Defines new meaning of a symbol. If the symbol is an undefined one (SYM_VOID), it's just re-defined to the new type. If it's defined in different scope, a new symbol in current scope is created and the meaning is assigned to it. If it's already defined in the current scope, an error is reported via cf_error().

Result

Pointer to the newly defined symbol. If we are in the top-level scope, it's the same sym as passed to the function.


Function

void cf_lex_init (int is_cli, struct config * c) -- initialize the lexer

Arguments

int is_cli

true if we're going to parse CLI command, false for configuration

struct config * c

-- undescribed --

Description

cf_lex_init() initializes the lexical analyzer and prepares it for parsing of a new input.


Function

void cf_push_scope (struct symbol * sym) -- enter new scope

Arguments

struct symbol * sym

symbol representing scope name

Description

If we want to enter a new scope to process declarations inside a nested block, we can just call cf_push_scope() to push a new scope onto the scope stack which will cause all new symbols to be defined in this scope and all existing symbols to be sought for in all scopes stored on the stack.


Function

void cf_pop_scope (void) -- leave a scope

Description

cf_pop_scope() pops the topmost scope from the scope stack, leaving all its symbols in the symbol table, but making them invisible to the rest of the config.


Function

char * cf_symbol_class_name (struct symbol * sym) -- get name of a symbol class

Arguments

struct symbol * sym

symbol

Description

This function returns a string representing the class of the given symbol.

3.3 Parser

Both the configuration and CLI commands are analyzed using a syntax driven parser generated by the bison tool from a grammar which is constructed from information gathered from grammar snippets by the gen_parser.m4 script.

Grammar snippets are files (usually with extension .Y) contributed by various BIRD modules in order to provide information about syntax of their configuration and their CLI commands. Each snipped consists of several sections, each of them starting with a special keyword: CF_HDR for a list of #include directives needed by the C code, CF_DEFINES for a list of C declarations, CF_DECLS for bison declarations including keyword definitions specified as CF_KEYWORDS, CF_GRAMMAR for the grammar rules, CF_CODE for auxiliary C code and finally CF_END at the end of the snippet.

To create references between the snippets, it's possible to define multi-part rules by utilizing the CF_ADDTO macro which adds a new alternative to a multi-part rule.

CLI commands are defined using a CF_CLI macro. Its parameters are: the list of keywords determining the command, the list of parameters, help text for the parameters and help text for the command.

Values of enum filter types can be defined using CF_ENUM with the following parameters: name of filter type, prefix common for all literals of this type and names of all the possible values.


Next Previous Contents