From a7f23f581f5e3efe92ec97dfca7d01c66f31ab04 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 7 Nov 2011 00:31:23 +0100 Subject: Implements protocol templates. Based on the patch from Alexander V. Chernikov. Extended to support almost all protocols. Uses 'protocol bgp NAME from TEMPLATE { ... }' syntax. --- nest/proto.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) (limited to 'nest/proto.c') diff --git a/nest/proto.c b/nest/proto.c index 4a154d5..d55c348 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -175,6 +175,7 @@ proto_flush_hooks(struct proto *p) * proto_config_new - create a new protocol configuration * @pr: protocol the configuration will belong to * @size: size of the structure including generic data + * @class: SYM_PROTO or SYM_TEMPLATE * * Whenever the configuration file says that a new instance * of a routing protocol should be created, the parser calls @@ -183,16 +184,23 @@ proto_flush_hooks(struct proto *p) * containing all the generic items followed by protocol-specific * ones). Also, the configuration entry gets added to the list * of protocol instances kept in the configuration. + * + * The function is also used to create protocol templates (when class + * SYM_TEMPLATE is specified), the only difference is that templates + * are not added to the list of protocol instances and therefore not + * initialized during protos_commit()). */ void * -proto_config_new(struct protocol *pr, unsigned size) +proto_config_new(struct protocol *pr, unsigned size, int class) { struct proto_config *c = cfg_allocz(size); - add_tail(&new_config->protos, &c->n); + if (class == SYM_PROTO) + add_tail(&new_config->protos, &c->n); c->global = new_config; c->protocol = pr; c->name = pr->name; + c->class = class; c->out_filter = FILTER_REJECT; c->table = c->global->master_rtc; c->debug = new_config->proto_default_debug; @@ -200,6 +208,50 @@ proto_config_new(struct protocol *pr, unsigned size) return c; } +/** + * proto_copy_config - copy a protocol configuration + * @dest: destination protocol configuration + * @src: source protocol configuration + * + * Whenever a new instance of a routing protocol is created from the + * template, proto_copy_config() is called to copy a content of + * the source protocol configuration to the new protocol configuration. + * Name, class and a node in protos list of @dest are kept intact. + * copy_config() protocol hook is used to copy protocol-specific data. + */ +void +proto_copy_config(struct proto_config *dest, struct proto_config *src) +{ + node old_node; + int old_class; + char *old_name; + + if (dest->protocol != src->protocol) + cf_error("Can't copy configuration from a different protocol type"); + + if (dest->protocol->copy_config == NULL) + cf_error("Inheriting configuration for %s is not supported", src->protocol->name); + + DBG("Copying configuration from %s to %s\n", src->name, dest->name); + + /* + * Copy struct proto_config here. Keep original node, class and name. + * protocol-specific config copy is handled by protocol copy_config() hook + */ + + old_node = dest->n; + old_class = dest->class; + old_name = dest->name; + + memcpy(dest, src, sizeof(struct proto_config)); + + dest->n = old_node; + dest->class = old_class; + dest->name = old_name; + + dest->protocol->copy_config(dest, src); +} + /** * protos_preconfig - pre-configuration processing * @c: new configuration @@ -230,7 +282,8 @@ protos_preconfig(struct config *c) * @c: new configuration * * This function calls the postconfig() hooks of all protocol - * instances specified in configuration @c. + * instances specified in configuration @c. The hooks are not + * called for protocol templates. */ void protos_postconfig(struct config *c) @@ -366,14 +419,15 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty { struct proto_config *oc, *nc; struct proto *p, *n; + struct symbol *sym; DBG("protos_commit:\n"); if (old) { WALK_LIST(oc, old->protos) { - struct proto *p = oc->proto; - struct symbol *sym = cf_find_symbol(oc->name); + p = oc->proto; + sym = cf_find_symbol(oc->name); if (sym && sym->class == SYM_PROTO && !new->shutdown) { /* Found match, let's check if we can smoothly switch to new configuration */ -- cgit v1.2.3