summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/bird.sgml66
-rw-r--r--nest/config.Y2
-rw-r--r--nest/proto.c25
-rw-r--r--nest/protocol.h4
-rw-r--r--proto/bgp/config.Y16
-rw-r--r--proto/ospf/config.Y7
-rw-r--r--proto/pipe/config.Y2
-rw-r--r--proto/radv/radv.c2
-rw-r--r--proto/rip/rip.c2
-rw-r--r--proto/rpki/rpki.c2
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