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
|
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
|
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
|
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
|
ways how to name symbols (like protocol names, filter names, constants etc.).
|
||||||
can either use a simple string starting with a letter followed by any
|
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
|
combination of letters and numbers (e.g. <cf/R123/, <cf/myfilter/, <cf/bgp5/) or
|
||||||
enclose the name into apostrophes (<cf/'/) and than you can use any combination
|
you can enclose the name into apostrophes (<cf/'/) and than you can use any
|
||||||
of numbers, letters. hyphens, dots and colons (e.g. <cf/'1:strange-name'/,
|
combination of numbers, letters. hyphens, dots and colons (e.g.
|
||||||
<cf/'-NAME-'/, <cf/'cool::name'/).
|
<cf/'1:strange-name'/, <cf/'-NAME-'/, <cf/'cool::name'/).
|
||||||
|
|
||||||
<p>Here is an example of a simple config file. It enables synchronization of
|
<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
|
routing tables with OS kernel, learns network interfaces and runs RIP on all
|
||||||
and runs RIP on all network interfaces found.
|
network interfaces found.
|
||||||
|
|
||||||
<code>
|
<code>
|
||||||
protocol kernel {
|
protocol kernel {
|
||||||
|
ipv4 {
|
||||||
|
export all; # Default is export none
|
||||||
|
};
|
||||||
persist; # Don't remove routes on BIRD shutdown
|
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 {
|
protocol device {
|
||||||
scan time 10; # Scan interfaces every 10 seconds
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol rip {
|
protocol rip {
|
||||||
export all;
|
ipv4 {
|
||||||
import all;
|
import all;
|
||||||
|
export all;
|
||||||
|
};
|
||||||
interface "*";
|
interface "*";
|
||||||
}
|
}
|
||||||
</code>
|
</code>
|
||||||
|
@ -775,8 +777,10 @@ agreement").
|
||||||
<label id="channel-opts">
|
<label id="channel-opts">
|
||||||
|
|
||||||
<p>Every channel belongs to a protocol and is configured inside its block. The
|
<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
|
minimal channel config is empty, then it uses default values. The name of the
|
||||||
the channel implies its nettype.
|
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>
|
<descrip>
|
||||||
<tag><label id="proto-table">table <m/name/</tag>
|
<tag><label id="proto-table">table <m/name/</tag>
|
||||||
|
@ -841,7 +845,7 @@ protocol rip ng {
|
||||||
}
|
}
|
||||||
</code>
|
</code>
|
||||||
|
|
||||||
<p>And this is a non-trivial example.
|
<p>This is a non-trivial example.
|
||||||
<code>
|
<code>
|
||||||
protocol rip ng {
|
protocol rip ng {
|
||||||
ipv6 {
|
ipv6 {
|
||||||
|
@ -854,6 +858,33 @@ protocol rip ng {
|
||||||
}
|
}
|
||||||
</code>
|
</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
|
<chapt>Remote control
|
||||||
<label id="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.
|
Evaluate given expression.
|
||||||
</descrip>
|
</descrip>
|
||||||
|
|
||||||
|
|
||||||
<chapt>Filters
|
<chapt>Filters
|
||||||
<label id="filters">
|
<label id="filters">
|
||||||
|
|
||||||
|
@ -2427,7 +2459,7 @@ together with their appropriate channels follows.
|
||||||
</tabular>
|
</tabular>
|
||||||
</table>
|
</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>
|
<descrip>
|
||||||
<tag><label id="bgp-next-hop-keep">next hop keep</tag>
|
<tag><label id="bgp-next-hop-keep">next hop keep</tag>
|
||||||
|
|
|
@ -214,7 +214,7 @@ proto_item:
|
||||||
|
|
||||||
channel_start: net_type
|
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:
|
channel_item:
|
||||||
|
|
25
nest/proto.c
25
nest/proto.c
|
@ -455,11 +455,10 @@ const struct channel_class channel_basic = {
|
||||||
};
|
};
|
||||||
|
|
||||||
void *
|
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 channel_config *cf = NULL;
|
||||||
struct rtable_config *tab = NULL;
|
struct rtable_config *tab = NULL;
|
||||||
const char *name = NULL;
|
|
||||||
|
|
||||||
if (net_type)
|
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");
|
cf_error("Different channel type");
|
||||||
|
|
||||||
tab = new_config->def_tables[net_type];
|
tab = new_config->def_tables[net_type];
|
||||||
name = net_label[net_type];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cc)
|
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 = cfg_allocz(cc->config_size);
|
||||||
cf->name = name;
|
cf->name = name;
|
||||||
cf->channel = cc;
|
cf->channel = cc;
|
||||||
|
cf->parent = proto;
|
||||||
cf->table = tab;
|
cf->table = tab;
|
||||||
cf->out_filter = FILTER_REJECT;
|
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;
|
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 *
|
struct channel_config *
|
||||||
channel_copy_config(struct channel_config *src, struct proto_config *proto)
|
channel_copy_config(struct channel_config *src, struct proto_config *proto)
|
||||||
{
|
{
|
||||||
|
|
|
@ -461,6 +461,7 @@ struct channel_config {
|
||||||
const char *name;
|
const char *name;
|
||||||
const struct channel_class *channel;
|
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 rtable_config *table; /* Table we're attached to */
|
||||||
struct filter *in_filter, *out_filter; /* Attached filters */
|
struct filter *in_filter, *out_filter; /* Attached filters */
|
||||||
struct channel_limit rx_limit; /* Limit for receiving routes from protocol
|
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); }
|
static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); }
|
||||||
|
|
||||||
void channel_request_feeding(struct channel *c);
|
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);
|
int channel_reconfigure(struct channel *c, struct channel_config *cf);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -158,12 +158,16 @@ bgp_channel_start: bgp_afi
|
||||||
if (!desc)
|
if (!desc)
|
||||||
cf_error("Unknown AFI/SAFI");
|
cf_error("Unknown AFI/SAFI");
|
||||||
|
|
||||||
this_channel = channel_config_new(&channel_bgp, desc->net, this_proto);
|
this_channel = channel_config_get(&channel_bgp, desc->name, desc->net, this_proto);
|
||||||
BGP_CC->c.name = desc->name;
|
|
||||||
BGP_CC->c.ra_mode = RA_UNDEF;
|
/* New channel */
|
||||||
BGP_CC->afi = $1;
|
if (!BGP_CC->desc)
|
||||||
BGP_CC->desc = desc;
|
{
|
||||||
BGP_CC->gr_able = 0xff; /* undefined */
|
BGP_CC->c.ra_mode = RA_UNDEF;
|
||||||
|
BGP_CC->afi = $1;
|
||||||
|
BGP_CC->desc = desc;
|
||||||
|
BGP_CC->gr_able = 0xff; /* undefined */
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bgp_channel_item:
|
bgp_channel_item:
|
||||||
|
|
|
@ -84,8 +84,8 @@ ospf_proto_finish(void)
|
||||||
/* Define default channel */
|
/* Define default channel */
|
||||||
if (EMPTY_LIST(this_proto->channels))
|
if (EMPTY_LIST(this_proto->channels))
|
||||||
{
|
{
|
||||||
this_proto->net_type = ospf_cfg_is_v2() ? NET_IP4 : NET_IP6;
|
uint net_type = this_proto->net_type = ospf_cfg_is_v2() ? NET_IP4 : NET_IP6;
|
||||||
channel_config_new(NULL, this_proto->net_type, this_proto);
|
channel_config_new(NULL, net_label[net_type], net_type, this_proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Propagate global instance ID to interfaces */
|
/* Propagate global instance ID to interfaces */
|
||||||
|
@ -238,7 +238,8 @@ ospf_af_mc:
|
||||||
/* We redefine proto_channel to add multicast flag */
|
/* We redefine proto_channel to add multicast flag */
|
||||||
ospf_channel_start: net_type ospf_af_mc
|
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 */
|
/* Save the multicast flag */
|
||||||
if (this_channel == proto_cf_main_channel(this_proto))
|
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
|
pipe_proto_start: proto_start PIPE
|
||||||
{
|
{
|
||||||
this_proto = proto_config_new(&proto_pipe, $1);
|
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->in_filter = FILTER_ACCEPT;
|
||||||
this_channel->out_filter = FILTER_ACCEPT;
|
this_channel->out_filter = FILTER_ACCEPT;
|
||||||
};
|
};
|
||||||
|
|
|
@ -569,7 +569,7 @@ radv_postconfig(struct proto_config *CF)
|
||||||
|
|
||||||
/* Define default channel */
|
/* Define default channel */
|
||||||
if (EMPTY_LIST(CF->channels))
|
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 *
|
static struct proto *
|
||||||
|
|
|
@ -1078,7 +1078,7 @@ rip_postconfig(struct proto_config *CF)
|
||||||
|
|
||||||
/* Define default channel */
|
/* Define default channel */
|
||||||
if (EMPTY_LIST(CF->channels))
|
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 *
|
static struct proto *
|
||||||
|
|
|
@ -901,7 +901,7 @@ rpki_postconfig(struct proto_config *CF)
|
||||||
{
|
{
|
||||||
/* Define default channel */
|
/* Define default channel */
|
||||||
if (EMPTY_LIST(CF->channels))
|
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
|
static void
|
||||||
|
|
Loading…
Reference in a new issue