summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2018-01-09 18:42:22 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2018-01-09 18:42:22 +0100
commit72163bd5f3ccefc1edda585f6f605c37e774a0b8 (patch)
tree59df1629a4c0884e2072c8082e9b4d392be648e4 /nest
parent09c1e370b3084f7acb7c3777427670a69945368a (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.
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);