mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Implements protocol templates.
Based on the patch from Alexander V. Chernikov. Extended to support almost all protocols. Uses 'protocol bgp NAME from TEMPLATE { ... }' syntax.
This commit is contained in:
@@ -26,7 +26,7 @@ static int password_id;
|
||||
static inline void
|
||||
reset_passwords(void)
|
||||
{
|
||||
this_p_list = NULL;
|
||||
this_p_list = NULL;
|
||||
}
|
||||
|
||||
static inline list *
|
||||
@@ -37,10 +37,11 @@ get_passwords(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define DIRECT_CFG ((struct rt_dev_config *) this_proto)
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
||||
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
||||
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
|
||||
@@ -58,7 +59,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT, MULT
|
||||
%type <r> rtable
|
||||
%type <s> optsym
|
||||
%type <ra> r_args
|
||||
%type <i> echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport
|
||||
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport
|
||||
%type <ps> proto_patt proto_patt2
|
||||
|
||||
CF_GRAMMAR
|
||||
@@ -115,20 +116,30 @@ newtab: TABLE SYM {
|
||||
|
||||
CF_ADDTO(conf, proto)
|
||||
|
||||
proto_start: PROTOCOL
|
||||
proto_start:
|
||||
PROTOCOL { $$ = SYM_PROTO; }
|
||||
| TEMPLATE { $$ = SYM_TEMPLATE; }
|
||||
;
|
||||
|
||||
proto_name:
|
||||
/* EMPTY */ {
|
||||
struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
|
||||
s->class = SYM_PROTO;
|
||||
s->class = this_proto->class;
|
||||
s->def = this_proto;
|
||||
this_proto->name = s->name;
|
||||
}
|
||||
| SYM {
|
||||
cf_define_symbol($1, SYM_PROTO, this_proto);
|
||||
cf_define_symbol($1, this_proto->class, this_proto);
|
||||
this_proto->name = $1->name;
|
||||
}
|
||||
| SYM FROM SYM {
|
||||
if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
|
||||
|
||||
cf_define_symbol($1, this_proto->class, this_proto);
|
||||
this_proto->name = $1->name;
|
||||
|
||||
proto_copy_config(this_proto, $3->def);
|
||||
}
|
||||
;
|
||||
|
||||
proto_item:
|
||||
@@ -207,10 +218,9 @@ iface_patt_list:
|
||||
CF_ADDTO(proto, dev_proto '}')
|
||||
|
||||
dev_proto_start: proto_start DIRECT {
|
||||
struct rt_dev_config *p = proto_config_new(&proto_device, sizeof(struct rt_dev_config));
|
||||
this_proto = &p->c;
|
||||
p->c.preference = DEF_PREF_DIRECT;
|
||||
init_list(&p->iface_list);
|
||||
this_proto = proto_config_new(&proto_device, sizeof(struct rt_dev_config), $1);
|
||||
this_proto->preference = DEF_PREF_DIRECT;
|
||||
init_list(&DIRECT_CFG->iface_list);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -222,9 +232,8 @@ dev_proto:
|
||||
|
||||
dev_iface_init:
|
||||
/* EMPTY */ {
|
||||
struct rt_dev_config *p = (void *) this_proto;
|
||||
this_ipatt = cfg_allocz(sizeof(struct iface_patt));
|
||||
add_tail(&p->iface_list, NODE this_ipatt);
|
||||
add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
|
||||
init_list(&this_ipatt->ipn_list);
|
||||
}
|
||||
;
|
||||
|
64
nest/proto.c
64
nest/proto.c
@@ -175,6 +175,7 @@ proto_flush_hooks(struct proto *p)
|
||||
* proto_config_new - create a new protocol configuration
|
||||
* @pr: protocol the configuration will belong to
|
||||
* @size: size of the structure including generic data
|
||||
* @class: SYM_PROTO or SYM_TEMPLATE
|
||||
*
|
||||
* Whenever the configuration file says that a new instance
|
||||
* of a routing protocol should be created, the parser calls
|
||||
@@ -183,16 +184,23 @@ proto_flush_hooks(struct proto *p)
|
||||
* 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.
|
||||
*
|
||||
* The function is also used to create protocol templates (when class
|
||||
* SYM_TEMPLATE is specified), the only difference is that templates
|
||||
* are not added to the list of protocol instances and therefore not
|
||||
* initialized during protos_commit()).
|
||||
*/
|
||||
void *
|
||||
proto_config_new(struct protocol *pr, unsigned size)
|
||||
proto_config_new(struct protocol *pr, unsigned size, int class)
|
||||
{
|
||||
struct proto_config *c = cfg_allocz(size);
|
||||
|
||||
add_tail(&new_config->protos, &c->n);
|
||||
if (class == SYM_PROTO)
|
||||
add_tail(&new_config->protos, &c->n);
|
||||
c->global = new_config;
|
||||
c->protocol = pr;
|
||||
c->name = pr->name;
|
||||
c->class = class;
|
||||
c->out_filter = FILTER_REJECT;
|
||||
c->table = c->global->master_rtc;
|
||||
c->debug = new_config->proto_default_debug;
|
||||
@@ -200,6 +208,50 @@ proto_config_new(struct protocol *pr, unsigned size)
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* proto_copy_config - copy a protocol configuration
|
||||
* @dest: destination protocol configuration
|
||||
* @src: source protocol configuration
|
||||
*
|
||||
* Whenever a new instance of a routing protocol is created from the
|
||||
* template, proto_copy_config() is called to copy a content of
|
||||
* the source protocol configuration to the new protocol configuration.
|
||||
* Name, class and a node in protos list of @dest are kept intact.
|
||||
* copy_config() protocol hook is used to copy protocol-specific data.
|
||||
*/
|
||||
void
|
||||
proto_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||
{
|
||||
node old_node;
|
||||
int old_class;
|
||||
char *old_name;
|
||||
|
||||
if (dest->protocol != src->protocol)
|
||||
cf_error("Can't copy configuration from a different protocol type");
|
||||
|
||||
if (dest->protocol->copy_config == NULL)
|
||||
cf_error("Inheriting configuration for %s is not supported", src->protocol->name);
|
||||
|
||||
DBG("Copying configuration from %s to %s\n", src->name, dest->name);
|
||||
|
||||
/*
|
||||
* Copy struct proto_config here. Keep original node, class and name.
|
||||
* protocol-specific config copy is handled by protocol copy_config() hook
|
||||
*/
|
||||
|
||||
old_node = dest->n;
|
||||
old_class = dest->class;
|
||||
old_name = dest->name;
|
||||
|
||||
memcpy(dest, src, sizeof(struct proto_config));
|
||||
|
||||
dest->n = old_node;
|
||||
dest->class = old_class;
|
||||
dest->name = old_name;
|
||||
|
||||
dest->protocol->copy_config(dest, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* protos_preconfig - pre-configuration processing
|
||||
* @c: new configuration
|
||||
@@ -230,7 +282,8 @@ protos_preconfig(struct config *c)
|
||||
* @c: new configuration
|
||||
*
|
||||
* This function calls the postconfig() hooks of all protocol
|
||||
* instances specified in configuration @c.
|
||||
* instances specified in configuration @c. The hooks are not
|
||||
* called for protocol templates.
|
||||
*/
|
||||
void
|
||||
protos_postconfig(struct config *c)
|
||||
@@ -366,14 +419,15 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
|
||||
{
|
||||
struct proto_config *oc, *nc;
|
||||
struct proto *p, *n;
|
||||
struct symbol *sym;
|
||||
|
||||
DBG("protos_commit:\n");
|
||||
if (old)
|
||||
{
|
||||
WALK_LIST(oc, old->protos)
|
||||
{
|
||||
struct proto *p = oc->proto;
|
||||
struct symbol *sym = cf_find_symbol(oc->name);
|
||||
p = oc->proto;
|
||||
sym = cf_find_symbol(oc->name);
|
||||
if (sym && sym->class == SYM_PROTO && !new->shutdown)
|
||||
{
|
||||
/* Found match, let's check if we can smoothly switch to new configuration */
|
||||
|
@@ -53,6 +53,7 @@ struct protocol {
|
||||
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
|
||||
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
||||
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
||||
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
|
||||
};
|
||||
|
||||
void protos_build(void);
|
||||
@@ -85,12 +86,15 @@ struct proto_config {
|
||||
struct proto *proto; /* Instance we've created */
|
||||
char *name;
|
||||
char *dsc;
|
||||
int class; /* SYM_PROTO or SYM_TEMPLATE */
|
||||
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
||||
unsigned preference, disabled; /* Generic parameters */
|
||||
u32 router_id; /* Protocol specific router ID */
|
||||
struct rtable_config *table; /* Table we're attached to */
|
||||
struct filter *in_filter, *out_filter; /* Attached filters */
|
||||
|
||||
/* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */
|
||||
|
||||
/* Protocol-specific data follow... */
|
||||
};
|
||||
|
||||
@@ -203,9 +207,14 @@ struct proto_spec {
|
||||
|
||||
|
||||
void *proto_new(struct proto_config *, unsigned size);
|
||||
void *proto_config_new(struct protocol *, unsigned size);
|
||||
void *proto_config_new(struct protocol *, unsigned size, int class);
|
||||
void proto_copy_config(struct proto_config *dest, struct proto_config *src);
|
||||
void proto_request_feeding(struct proto *p);
|
||||
|
||||
static inline void
|
||||
proto_copy_rest(struct proto_config *dest, struct proto_config *src, unsigned size)
|
||||
{ memcpy(dest + 1, src + 1, size - sizeof(struct proto_config)); }
|
||||
|
||||
void proto_cmd_show(struct proto *, unsigned int, int);
|
||||
void proto_cmd_disable(struct proto *, unsigned int, int);
|
||||
void proto_cmd_enable(struct proto *, unsigned int, int);
|
||||
|
@@ -92,9 +92,24 @@ dev_reconfigure(struct proto *p, struct proto_config *new)
|
||||
return iface_patts_equal(&o->iface_list, &n->iface_list, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||
{
|
||||
struct rt_dev_config *d = (struct rt_dev_config *) dest;
|
||||
struct rt_dev_config *s = (struct rt_dev_config *) src;
|
||||
|
||||
/*
|
||||
* We copy iface_list as ifaces can be shared by more direct protocols.
|
||||
* Copy suffices to be is shallow, because new nodes can be added, but
|
||||
* old nodes cannot be modified (although they contain internal lists).
|
||||
*/
|
||||
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
|
||||
}
|
||||
|
||||
struct protocol proto_device = {
|
||||
name: "Direct",
|
||||
template: "direct%d",
|
||||
init: dev_init,
|
||||
reconfigure: dev_reconfigure
|
||||
reconfigure: dev_reconfigure,
|
||||
copy_config: dev_copy_config
|
||||
};
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
struct rt_dev_config {
|
||||
struct proto_config c;
|
||||
list iface_list;
|
||||
list iface_list; /* list of struct iface_patt */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user