summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/config.Y2
-rw-r--r--nest/proto.c25
-rw-r--r--nest/protocol.h4
3 files changed, 26 insertions, 5 deletions
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);