diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-01-09 18:42:22 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-01-09 18:42:22 +0100 |
commit | 72163bd5f3ccefc1edda585f6f605c37e774a0b8 (patch) | |
tree | 59df1629a4c0884e2072c8082e9b4d392be648e4 | |
parent | 09c1e370b3084f7acb7c3777427670a69945368a (diff) |
Nest: Allow modification of channels inherited from templates
Multiple definitions of same channels are forbidden, but inherited
channel can be redefined. In such case channel options are merged.
-rw-r--r-- | doc/bird.sgml | 66 | ||||
-rw-r--r-- | nest/config.Y | 2 | ||||
-rw-r--r-- | nest/proto.c | 25 | ||||
-rw-r--r-- | nest/protocol.h | 4 | ||||
-rw-r--r-- | proto/bgp/config.Y | 16 | ||||
-rw-r--r-- | proto/ospf/config.Y | 7 | ||||
-rw-r--r-- | proto/pipe/config.Y | 2 | ||||
-rw-r--r-- | proto/radv/radv.c | 2 | ||||
-rw-r--r-- | proto/rip/rip.c | 2 | ||||
-rw-r--r-- | proto/rpki/rpki.c | 2 |
10 files changed, 93 insertions, 35 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 3a2607b4..bde825c3 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -407,31 +407,33 @@ extensive way. a comment, whitespace characters are treated as a single space. If there's a variable number of options, they are grouped using the <cf/{ }/ brackets. Each option is terminated by a <cf/;/. Configuration is case sensitive. There are two -ways how to name symbols (like protocol names, filter names, constants etc.). You -can either use a simple string starting with a letter followed by any -combination of letters and numbers (e.g. <cf/R123/, <cf/myfilter/, <cf/bgp5/) or you can -enclose the name into apostrophes (<cf/'/) and than you can use any combination -of numbers, letters. hyphens, dots and colons (e.g. <cf/'1:strange-name'/, -<cf/'-NAME-'/, <cf/'cool::name'/). +ways how to name symbols (like protocol names, filter names, constants etc.). +You can either use a simple string starting with a letter followed by any +combination of letters and numbers (e.g. <cf/R123/, <cf/myfilter/, <cf/bgp5/) or +you can enclose the name into apostrophes (<cf/'/) and than you can use any +combination of numbers, letters. hyphens, dots and colons (e.g. +<cf/'1:strange-name'/, <cf/'-NAME-'/, <cf/'cool::name'/). <p>Here is an example of a simple config file. It enables synchronization of -routing tables with OS kernel, scans for new network interfaces every 10 seconds -and runs RIP on all network interfaces found. +routing tables with OS kernel, learns network interfaces and runs RIP on all +network interfaces found. <code> protocol kernel { + ipv4 { + export all; # Default is export none + }; persist; # Don't remove routes on BIRD shutdown - scan time 20; # Scan kernel routing table every 20 seconds - export all; # Default is export none } protocol device { - scan time 10; # Scan interfaces every 10 seconds } protocol rip { - export all; - import all; + ipv4 { + import all; + export all; + }; interface "*"; } </code> @@ -775,8 +777,10 @@ agreement"). <label id="channel-opts"> <p>Every channel belongs to a protocol and is configured inside its block. The -minimal channel config is empty, then it uses the default values. The name of -the channel implies its nettype. +minimal channel config is empty, then it uses default values. The name of the +channel implies its nettype. Channel definitions can be inherited from protocol +templates. Multiple definitions of the same channel are forbidden, but channels +inherited from templates can be updated by new definitions. <descrip> <tag><label id="proto-table">table <m/name/</tag> @@ -841,7 +845,7 @@ protocol rip ng { } </code> -<p>And this is a non-trivial example. +<p>This is a non-trivial example. <code> protocol rip ng { ipv6 { @@ -854,6 +858,33 @@ protocol rip ng { } </code> +<p>And this is even more complicated example using templates. +<code> +template bgp { + local 198.51.100.14 as 65000; + + ipv4 { + table mytable4; + import filter { ... }; + }; + ipv6 { + table mytable6; + import filter { ... }; + }; +} + +protocol bgp from { + neighbor 198.51.100.130 as 64496; + + # IPv4 channel is inherited as-is, while IPv6 + # channel is adjusted by export filter option + ipv6 { + export filter { ... }; + }; +} +</code> + + <chapt>Remote control <label id="remote-control"> @@ -1051,6 +1082,7 @@ This argument can be omitted if there exists only a single instance. Evaluate given expression. </descrip> + <chapt>Filters <label id="filters"> @@ -2427,7 +2459,7 @@ together with their appropriate channels follows. </tabular> </table> -<p>BGP's channels have additional config options (together with the common ones): +<p>BGP channels have additional config options (together with the common ones): <descrip> <tag><label id="bgp-next-hop-keep">next hop keep</tag> diff --git a/nest/config.Y b/nest/config.Y index 5c4f2393..044aba2b 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -214,7 +214,7 @@ proto_item: channel_start: net_type { - $$ = this_channel = channel_config_new(NULL, $1, this_proto); + $$ = this_channel = channel_config_get(NULL, net_label[$1], $1, this_proto); }; channel_item: diff --git a/nest/proto.c b/nest/proto.c index e103fec6..d584cb93 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -455,11 +455,10 @@ const struct channel_class channel_basic = { }; void * -channel_config_new(const struct channel_class *cc, uint net_type, struct proto_config *proto) +channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto) { struct channel_config *cf = NULL; struct rtable_config *tab = NULL; - const char *name = NULL; if (net_type) { @@ -470,7 +469,6 @@ channel_config_new(const struct channel_class *cc, uint net_type, struct proto_c cf_error("Different channel type"); tab = new_config->def_tables[net_type]; - name = net_label[net_type]; } if (!cc) @@ -479,6 +477,7 @@ channel_config_new(const struct channel_class *cc, uint net_type, struct proto_c cf = cfg_allocz(cc->config_size); cf->name = name; cf->channel = cc; + cf->parent = proto; cf->table = tab; cf->out_filter = FILTER_REJECT; @@ -491,6 +490,26 @@ channel_config_new(const struct channel_class *cc, uint net_type, struct proto_c return cf; } +void * +channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto) +{ + struct channel_config *cf; + + /* We are using name as token, so no strcmp() */ + WALK_LIST(cf, proto->channels) + if (cf->name == name) + { + /* Allow to redefine channel only if inherited from template */ + if (cf->parent == proto) + cf_error("Multiple %s channels", name); + + cf->parent = proto; + return cf; + } + + return channel_config_new(cc, name, net_type, proto); +} + struct channel_config * channel_copy_config(struct channel_config *src, struct proto_config *proto) { diff --git a/nest/protocol.h b/nest/protocol.h index c8f37367..9afd3a0a 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -461,6 +461,7 @@ struct channel_config { const char *name; const struct channel_class *channel; + struct proto_config *parent; /* Where channel is defined (proto or template) */ struct rtable_config *table; /* Table we're attached to */ struct filter *in_filter, *out_filter; /* Attached filters */ struct channel_limit rx_limit; /* Limit for receiving routes from protocol @@ -585,7 +586,8 @@ static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP) static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); } void channel_request_feeding(struct channel *c); -void *channel_config_new(const struct channel_class *cc, uint net_type, struct proto_config *proto); +void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); +void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto); int channel_reconfigure(struct channel *c, struct channel_config *cf); diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 6ce0f1aa..4e819eb7 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -158,12 +158,16 @@ bgp_channel_start: bgp_afi if (!desc) cf_error("Unknown AFI/SAFI"); - this_channel = channel_config_new(&channel_bgp, desc->net, this_proto); - BGP_CC->c.name = desc->name; - BGP_CC->c.ra_mode = RA_UNDEF; - BGP_CC->afi = $1; - BGP_CC->desc = desc; - BGP_CC->gr_able = 0xff; /* undefined */ + this_channel = channel_config_get(&channel_bgp, desc->name, desc->net, this_proto); + + /* New channel */ + if (!BGP_CC->desc) + { + BGP_CC->c.ra_mode = RA_UNDEF; + BGP_CC->afi = $1; + BGP_CC->desc = desc; + BGP_CC->gr_able = 0xff; /* undefined */ + } }; bgp_channel_item: diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index ce409a3a..005f4381 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -84,8 +84,8 @@ ospf_proto_finish(void) /* Define default channel */ if (EMPTY_LIST(this_proto->channels)) { - this_proto->net_type = ospf_cfg_is_v2() ? NET_IP4 : NET_IP6; - channel_config_new(NULL, this_proto->net_type, this_proto); + uint net_type = this_proto->net_type = ospf_cfg_is_v2() ? NET_IP4 : NET_IP6; + channel_config_new(NULL, net_label[net_type], net_type, this_proto); } /* Propagate global instance ID to interfaces */ @@ -238,7 +238,8 @@ ospf_af_mc: /* We redefine proto_channel to add multicast flag */ ospf_channel_start: net_type ospf_af_mc { - $$ = this_channel = channel_config_new(NULL, $1, this_proto); + /* TODO: change name for multicast channels */ + $$ = this_channel = channel_config_get(NULL, net_label[$1], $1, this_proto); /* Save the multicast flag */ if (this_channel == proto_cf_main_channel(this_proto)) diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y index f51ee575..4f96fdcb 100644 --- a/proto/pipe/config.Y +++ b/proto/pipe/config.Y @@ -25,7 +25,7 @@ CF_ADDTO(proto, pipe_proto '}' { this_channel = NULL; } ) pipe_proto_start: proto_start PIPE { this_proto = proto_config_new(&proto_pipe, $1); - this_channel = channel_config_new(NULL, 0, this_proto); + this_channel = channel_config_new(NULL, NULL, 0, this_proto); this_channel->in_filter = FILTER_ACCEPT; this_channel->out_filter = FILTER_ACCEPT; }; diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 0a2a3e78..8a79dfaf 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -569,7 +569,7 @@ radv_postconfig(struct proto_config *CF) /* Define default channel */ if (EMPTY_LIST(CF->channels)) - channel_config_new(NULL, NET_IP6, CF); + channel_config_new(NULL, net_label[NET_IP6], NET_IP6, CF); } static struct proto * diff --git a/proto/rip/rip.c b/proto/rip/rip.c index a3eeaf17..85e37cea 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -1078,7 +1078,7 @@ rip_postconfig(struct proto_config *CF) /* Define default channel */ if (EMPTY_LIST(CF->channels)) - channel_config_new(NULL, CF->net_type, CF); + channel_config_new(NULL, net_label[CF->net_type], CF->net_type, CF); } static struct proto * diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 3145399b..74860071 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -901,7 +901,7 @@ rpki_postconfig(struct proto_config *CF) { /* Define default channel */ if (EMPTY_LIST(CF->channels)) - channel_config_new(NULL, CF->net_type, CF); + channel_config_new(NULL, net_label[CF->net_type], CF->net_type, CF); } static void |