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.
This commit is contained in:
parent
09c1e370b3
commit
72163bd5f3
10 changed files with 93 additions and 35 deletions
|
@ -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 {
|
||||
persist; # Don't remove routes on BIRD shutdown
|
||||
scan time 20; # Scan kernel routing table every 20 seconds
|
||||
ipv4 {
|
||||
export all; # Default is export none
|
||||
};
|
||||
persist; # Don't remove routes on BIRD shutdown
|
||||
}
|
||||
|
||||
protocol device {
|
||||
scan time 10; # Scan interfaces every 10 seconds
|
||||
}
|
||||
|
||||
protocol rip {
|
||||
export 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>
|
||||
|
|
|
@ -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:
|
||||
|
|
25
nest/proto.c
25
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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue