mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Implements protocol templates.
Based on the patch from Alexander V. Chernikov. Extended to support almost all protocols. Uses 'protocol bgp NAME from TEMPLATE { ... }' syntax.
This commit is contained in:
parent
74add5df17
commit
a7f23f581f
@ -533,6 +533,8 @@ cf_symbol_class_name(struct symbol *sym)
|
|||||||
return "routing table";
|
return "routing table";
|
||||||
case SYM_IPA:
|
case SYM_IPA:
|
||||||
return "network address";
|
return "network address";
|
||||||
|
case SYM_TEMPLATE:
|
||||||
|
return "protocol template";
|
||||||
default:
|
default:
|
||||||
return "unknown type";
|
return "unknown type";
|
||||||
}
|
}
|
||||||
|
15
conf/conf.c
15
conf/conf.c
@ -377,3 +377,18 @@ cfg_strdup(char *c)
|
|||||||
memcpy(z, c, l);
|
memcpy(z, c, l);
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cfg_copy_list(list *dest, list *src, unsigned node_size)
|
||||||
|
{
|
||||||
|
node *dn, *sn;
|
||||||
|
|
||||||
|
init_list(dest);
|
||||||
|
WALK_LIST(sn, *src)
|
||||||
|
{
|
||||||
|
dn = cfg_alloc(node_size);
|
||||||
|
memcpy(dn, sn, node_size);
|
||||||
|
add_tail(dest, dn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -84,6 +84,7 @@ extern linpool *cfg_mem;
|
|||||||
#define cfg_allocu(size) lp_allocu(cfg_mem, size)
|
#define cfg_allocu(size) lp_allocu(cfg_mem, size)
|
||||||
#define cfg_allocz(size) lp_allocz(cfg_mem, size)
|
#define cfg_allocz(size) lp_allocz(cfg_mem, size)
|
||||||
char *cfg_strdup(char *c);
|
char *cfg_strdup(char *c);
|
||||||
|
void cfg_copy_list(list *dest, list *src, unsigned node_size);
|
||||||
|
|
||||||
/* Lexer */
|
/* Lexer */
|
||||||
|
|
||||||
@ -108,6 +109,7 @@ struct symbol {
|
|||||||
#define SYM_FILTER 4
|
#define SYM_FILTER 4
|
||||||
#define SYM_TABLE 5
|
#define SYM_TABLE 5
|
||||||
#define SYM_IPA 6
|
#define SYM_IPA 6
|
||||||
|
#define SYM_TEMPLATE 7
|
||||||
|
|
||||||
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
|
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
|
||||||
|
|
||||||
|
@ -202,3 +202,16 @@ protocol static {
|
|||||||
# reject;
|
# reject;
|
||||||
# };
|
# };
|
||||||
#}
|
#}
|
||||||
|
#
|
||||||
|
# Template usage example
|
||||||
|
#template bgp rr_client {
|
||||||
|
# disabled;
|
||||||
|
# local as 65000;
|
||||||
|
# multihop;
|
||||||
|
# rr client;
|
||||||
|
# rr cluster id 1.0.0.1;
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
#protocol bgp rr_abcd from rr_client {
|
||||||
|
# neighbor 10.1.4.7 as 65000;
|
||||||
|
#}
|
||||||
|
@ -296,10 +296,21 @@ protocol rip {
|
|||||||
<tag>function <m/name/ (<m/parameters/) <m/local variables/ { <m/commands/ }</tag> Define a function. You can learn more
|
<tag>function <m/name/ (<m/parameters/) <m/local variables/ { <m/commands/ }</tag> Define a function. You can learn more
|
||||||
about functions in the following chapter.
|
about functions in the following chapter.
|
||||||
|
|
||||||
<tag>protocol rip|ospf|bgp|... <m/[name]/ { <m>protocol options</m> }</tag> Define a protocol
|
<tag>protocol rip|ospf|bgp|... [<m/name/ [from <m/name2/]] { <m>protocol options</m> }</tag>
|
||||||
instance called <cf><m/name/</cf> (or with a name like "rip5" generated automatically if you don't specify any <cf><m/name/</cf>). You can learn more
|
Define a protocol instance called <cf><m/name/</cf> (or with a name like "rip5" generated
|
||||||
about configuring protocols in their own chapters. You can run more than one instance of
|
automatically if you don't specify any <cf><m/name/</cf>). You can learn more about
|
||||||
most protocols (like RIP or BGP). By default, no instances are configured.
|
configuring protocols in their own chapters. When <cf>from <m/name2/</cf> expression is
|
||||||
|
used, initial protocol options are taken from protocol or template <cf><m/name2/</cf>
|
||||||
|
You can run more than one instance of most protocols (like RIP or BGP). By default, no
|
||||||
|
instances are configured.
|
||||||
|
|
||||||
|
<tag>template rip|bgp|... [<m/name/ [from <m/name2/]] { <m>protocol options</m> }</tag>
|
||||||
|
Define a protocol template instance called <cf><m/name/</cf> (or with a name like "bgp1"
|
||||||
|
generated automatically if you don't specify any <cf><m/name/</cf>). Protocol templates can
|
||||||
|
be used to group common options when many similarly configured protocol instances are to be
|
||||||
|
defined. Protocol instances (and other templates) can use templates by using <cf/from/
|
||||||
|
expression and the name of the template. At the moment templates (and <cf/from/ expression)
|
||||||
|
are not implemented for OSPF protocol.
|
||||||
|
|
||||||
<tag>define <m/constant/ = (<m/expression/)|<m/number/|<m/IP address/</tag>
|
<tag>define <m/constant/ = (<m/expression/)|<m/number/|<m/IP address/</tag>
|
||||||
Define a constant. You can use it later in every place you could use a simple integer or an IP address.
|
Define a constant. You can use it later in every place you could use a simple integer or an IP address.
|
||||||
|
@ -37,10 +37,11 @@ get_passwords(void)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DIRECT_CFG ((struct rt_dev_config *) this_proto)
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
||||||
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
|
||||||
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
|
||||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
|
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
|
||||||
@ -58,7 +59,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT, MULT
|
|||||||
%type <r> rtable
|
%type <r> rtable
|
||||||
%type <s> optsym
|
%type <s> optsym
|
||||||
%type <ra> r_args
|
%type <ra> r_args
|
||||||
%type <i> echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport
|
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport
|
||||||
%type <ps> proto_patt proto_patt2
|
%type <ps> proto_patt proto_patt2
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
@ -115,20 +116,30 @@ newtab: TABLE SYM {
|
|||||||
|
|
||||||
CF_ADDTO(conf, proto)
|
CF_ADDTO(conf, proto)
|
||||||
|
|
||||||
proto_start: PROTOCOL
|
proto_start:
|
||||||
|
PROTOCOL { $$ = SYM_PROTO; }
|
||||||
|
| TEMPLATE { $$ = SYM_TEMPLATE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
proto_name:
|
proto_name:
|
||||||
/* EMPTY */ {
|
/* EMPTY */ {
|
||||||
struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
|
struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
|
||||||
s->class = SYM_PROTO;
|
s->class = this_proto->class;
|
||||||
s->def = this_proto;
|
s->def = this_proto;
|
||||||
this_proto->name = s->name;
|
this_proto->name = s->name;
|
||||||
}
|
}
|
||||||
| SYM {
|
| SYM {
|
||||||
cf_define_symbol($1, SYM_PROTO, this_proto);
|
cf_define_symbol($1, this_proto->class, this_proto);
|
||||||
this_proto->name = $1->name;
|
this_proto->name = $1->name;
|
||||||
}
|
}
|
||||||
|
| SYM FROM SYM {
|
||||||
|
if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
|
||||||
|
|
||||||
|
cf_define_symbol($1, this_proto->class, this_proto);
|
||||||
|
this_proto->name = $1->name;
|
||||||
|
|
||||||
|
proto_copy_config(this_proto, $3->def);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
proto_item:
|
proto_item:
|
||||||
@ -207,10 +218,9 @@ iface_patt_list:
|
|||||||
CF_ADDTO(proto, dev_proto '}')
|
CF_ADDTO(proto, dev_proto '}')
|
||||||
|
|
||||||
dev_proto_start: proto_start DIRECT {
|
dev_proto_start: proto_start DIRECT {
|
||||||
struct rt_dev_config *p = proto_config_new(&proto_device, sizeof(struct rt_dev_config));
|
this_proto = proto_config_new(&proto_device, sizeof(struct rt_dev_config), $1);
|
||||||
this_proto = &p->c;
|
this_proto->preference = DEF_PREF_DIRECT;
|
||||||
p->c.preference = DEF_PREF_DIRECT;
|
init_list(&DIRECT_CFG->iface_list);
|
||||||
init_list(&p->iface_list);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -222,9 +232,8 @@ dev_proto:
|
|||||||
|
|
||||||
dev_iface_init:
|
dev_iface_init:
|
||||||
/* EMPTY */ {
|
/* EMPTY */ {
|
||||||
struct rt_dev_config *p = (void *) this_proto;
|
|
||||||
this_ipatt = cfg_allocz(sizeof(struct iface_patt));
|
this_ipatt = cfg_allocz(sizeof(struct iface_patt));
|
||||||
add_tail(&p->iface_list, NODE this_ipatt);
|
add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
|
||||||
init_list(&this_ipatt->ipn_list);
|
init_list(&this_ipatt->ipn_list);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
62
nest/proto.c
62
nest/proto.c
@ -175,6 +175,7 @@ proto_flush_hooks(struct proto *p)
|
|||||||
* proto_config_new - create a new protocol configuration
|
* proto_config_new - create a new protocol configuration
|
||||||
* @pr: protocol the configuration will belong to
|
* @pr: protocol the configuration will belong to
|
||||||
* @size: size of the structure including generic data
|
* @size: size of the structure including generic data
|
||||||
|
* @class: SYM_PROTO or SYM_TEMPLATE
|
||||||
*
|
*
|
||||||
* Whenever the configuration file says that a new instance
|
* Whenever the configuration file says that a new instance
|
||||||
* of a routing protocol should be created, the parser calls
|
* 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
|
* containing all the generic items followed by protocol-specific
|
||||||
* ones). Also, the configuration entry gets added to the list
|
* ones). Also, the configuration entry gets added to the list
|
||||||
* of protocol instances kept in the configuration.
|
* 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 *
|
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);
|
struct proto_config *c = cfg_allocz(size);
|
||||||
|
|
||||||
|
if (class == SYM_PROTO)
|
||||||
add_tail(&new_config->protos, &c->n);
|
add_tail(&new_config->protos, &c->n);
|
||||||
c->global = new_config;
|
c->global = new_config;
|
||||||
c->protocol = pr;
|
c->protocol = pr;
|
||||||
c->name = pr->name;
|
c->name = pr->name;
|
||||||
|
c->class = class;
|
||||||
c->out_filter = FILTER_REJECT;
|
c->out_filter = FILTER_REJECT;
|
||||||
c->table = c->global->master_rtc;
|
c->table = c->global->master_rtc;
|
||||||
c->debug = new_config->proto_default_debug;
|
c->debug = new_config->proto_default_debug;
|
||||||
@ -200,6 +208,50 @@ proto_config_new(struct protocol *pr, unsigned size)
|
|||||||
return c;
|
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
|
* protos_preconfig - pre-configuration processing
|
||||||
* @c: new configuration
|
* @c: new configuration
|
||||||
@ -230,7 +282,8 @@ protos_preconfig(struct config *c)
|
|||||||
* @c: new configuration
|
* @c: new configuration
|
||||||
*
|
*
|
||||||
* This function calls the postconfig() hooks of all protocol
|
* 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
|
void
|
||||||
protos_postconfig(struct config *c)
|
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_config *oc, *nc;
|
||||||
struct proto *p, *n;
|
struct proto *p, *n;
|
||||||
|
struct symbol *sym;
|
||||||
|
|
||||||
DBG("protos_commit:\n");
|
DBG("protos_commit:\n");
|
||||||
if (old)
|
if (old)
|
||||||
{
|
{
|
||||||
WALK_LIST(oc, old->protos)
|
WALK_LIST(oc, old->protos)
|
||||||
{
|
{
|
||||||
struct proto *p = oc->proto;
|
p = oc->proto;
|
||||||
struct symbol *sym = cf_find_symbol(oc->name);
|
sym = cf_find_symbol(oc->name);
|
||||||
if (sym && sym->class == SYM_PROTO && !new->shutdown)
|
if (sym && sym->class == SYM_PROTO && !new->shutdown)
|
||||||
{
|
{
|
||||||
/* Found match, let's check if we can smoothly switch to new configuration */
|
/* Found match, let's check if we can smoothly switch to new configuration */
|
||||||
|
@ -53,6 +53,7 @@ struct protocol {
|
|||||||
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
|
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
|
||||||
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
||||||
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
||||||
|
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
|
||||||
};
|
};
|
||||||
|
|
||||||
void protos_build(void);
|
void protos_build(void);
|
||||||
@ -85,12 +86,15 @@ struct proto_config {
|
|||||||
struct proto *proto; /* Instance we've created */
|
struct proto *proto; /* Instance we've created */
|
||||||
char *name;
|
char *name;
|
||||||
char *dsc;
|
char *dsc;
|
||||||
|
int class; /* SYM_PROTO or SYM_TEMPLATE */
|
||||||
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
|
||||||
unsigned preference, disabled; /* Generic parameters */
|
unsigned preference, disabled; /* Generic parameters */
|
||||||
u32 router_id; /* Protocol specific router ID */
|
u32 router_id; /* Protocol specific router ID */
|
||||||
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 */
|
||||||
|
|
||||||
|
/* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */
|
||||||
|
|
||||||
/* Protocol-specific data follow... */
|
/* Protocol-specific data follow... */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -203,9 +207,14 @@ struct proto_spec {
|
|||||||
|
|
||||||
|
|
||||||
void *proto_new(struct proto_config *, unsigned size);
|
void *proto_new(struct proto_config *, unsigned size);
|
||||||
void *proto_config_new(struct protocol *, unsigned size);
|
void *proto_config_new(struct protocol *, unsigned size, int class);
|
||||||
|
void proto_copy_config(struct proto_config *dest, struct proto_config *src);
|
||||||
void proto_request_feeding(struct proto *p);
|
void proto_request_feeding(struct proto *p);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
proto_copy_rest(struct proto_config *dest, struct proto_config *src, unsigned size)
|
||||||
|
{ memcpy(dest + 1, src + 1, size - sizeof(struct proto_config)); }
|
||||||
|
|
||||||
void proto_cmd_show(struct proto *, unsigned int, int);
|
void proto_cmd_show(struct proto *, unsigned int, int);
|
||||||
void proto_cmd_disable(struct proto *, unsigned int, int);
|
void proto_cmd_disable(struct proto *, unsigned int, int);
|
||||||
void proto_cmd_enable(struct proto *, unsigned int, int);
|
void proto_cmd_enable(struct proto *, unsigned int, int);
|
||||||
|
@ -92,9 +92,24 @@ dev_reconfigure(struct proto *p, struct proto_config *new)
|
|||||||
return iface_patts_equal(&o->iface_list, &n->iface_list, NULL);
|
return iface_patts_equal(&o->iface_list, &n->iface_list, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
struct rt_dev_config *d = (struct rt_dev_config *) dest;
|
||||||
|
struct rt_dev_config *s = (struct rt_dev_config *) src;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We copy iface_list as ifaces can be shared by more direct protocols.
|
||||||
|
* Copy suffices to be is shallow, because new nodes can be added, but
|
||||||
|
* old nodes cannot be modified (although they contain internal lists).
|
||||||
|
*/
|
||||||
|
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
|
||||||
|
}
|
||||||
|
|
||||||
struct protocol proto_device = {
|
struct protocol proto_device = {
|
||||||
name: "Direct",
|
name: "Direct",
|
||||||
template: "direct%d",
|
template: "direct%d",
|
||||||
init: dev_init,
|
init: dev_init,
|
||||||
reconfigure: dev_reconfigure
|
reconfigure: dev_reconfigure,
|
||||||
|
copy_config: dev_copy_config
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
struct rt_dev_config {
|
struct rt_dev_config {
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
list iface_list;
|
list iface_list; /* list of struct iface_patt */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
122
proto/bgp/bgp.c
122
proto/bgp/bgp.c
@ -919,6 +919,73 @@ bgp_init(struct proto_config *C)
|
|||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
bgp_check_config(struct bgp_config *c)
|
||||||
|
{
|
||||||
|
int internal = (c->local_as == c->remote_as);
|
||||||
|
|
||||||
|
/* Do not check templates at all */
|
||||||
|
if (c->c.class == SYM_TEMPLATE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!c->local_as)
|
||||||
|
cf_error("Local AS number must be set");
|
||||||
|
|
||||||
|
if (!c->remote_as)
|
||||||
|
cf_error("Neighbor must be configured");
|
||||||
|
|
||||||
|
if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF))
|
||||||
|
cf_error("Neighbor AS number out of range (AS4 not available)");
|
||||||
|
|
||||||
|
if (!internal && c->rr_client)
|
||||||
|
cf_error("Only internal neighbor can be RR client");
|
||||||
|
|
||||||
|
if (internal && c->rs_client)
|
||||||
|
cf_error("Only external neighbor can be RS client");
|
||||||
|
|
||||||
|
if (c->multihop && (c->gw_mode == GW_DIRECT))
|
||||||
|
cf_error("Multihop BGP cannot use direct gateway mode");
|
||||||
|
|
||||||
|
/* Different default based on rs_client */
|
||||||
|
if (!c->missing_lladdr)
|
||||||
|
c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
|
||||||
|
|
||||||
|
/* Different default for gw_mode */
|
||||||
|
if (!c->gw_mode)
|
||||||
|
c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bgp_reconfigure(struct proto *P, struct proto_config *C)
|
||||||
|
{
|
||||||
|
struct bgp_config *new = (struct bgp_config *) C;
|
||||||
|
struct bgp_proto *p = (struct bgp_proto *) P;
|
||||||
|
struct bgp_config *old = p->cf;
|
||||||
|
|
||||||
|
int same = !memcmp(((byte *) old) + sizeof(struct proto_config),
|
||||||
|
((byte *) new) + sizeof(struct proto_config),
|
||||||
|
// password item is last and must be checked separately
|
||||||
|
OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config))
|
||||||
|
&& ((!old->password && !new->password)
|
||||||
|
|| (old->password && new->password && !strcmp(old->password, new->password)))
|
||||||
|
&& (get_igp_table(old) == get_igp_table(new));
|
||||||
|
|
||||||
|
/* We should update our copy of configuration ptr as old configuration will be freed */
|
||||||
|
if (same)
|
||||||
|
p->cf = new;
|
||||||
|
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bgp_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
/* Just a shallow copy */
|
||||||
|
proto_copy_rest(dest, src, sizeof(struct bgp_config));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bgp_error - report a protocol error
|
* bgp_error - report a protocol error
|
||||||
* @c: connection
|
* @c: connection
|
||||||
@ -983,38 +1050,6 @@ bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code)
|
|||||||
p->last_error_code = code;
|
p->last_error_code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
bgp_check(struct bgp_config *c)
|
|
||||||
{
|
|
||||||
int internal = (c->local_as == c->remote_as);
|
|
||||||
|
|
||||||
if (!c->local_as)
|
|
||||||
cf_error("Local AS number must be set");
|
|
||||||
|
|
||||||
if (!c->remote_as)
|
|
||||||
cf_error("Neighbor must be configured");
|
|
||||||
|
|
||||||
if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF))
|
|
||||||
cf_error("Neighbor AS number out of range (AS4 not available)");
|
|
||||||
|
|
||||||
if (!internal && c->rr_client)
|
|
||||||
cf_error("Only internal neighbor can be RR client");
|
|
||||||
|
|
||||||
if (internal && c->rs_client)
|
|
||||||
cf_error("Only external neighbor can be RS client");
|
|
||||||
|
|
||||||
if (c->multihop && (c->gw_mode == GW_DIRECT))
|
|
||||||
cf_error("Multihop BGP cannot use direct gateway mode");
|
|
||||||
|
|
||||||
/* Different default based on rs_client */
|
|
||||||
if (!c->missing_lladdr)
|
|
||||||
c->missing_lladdr = c->rs_client ? MLL_IGNORE : MLL_SELF;
|
|
||||||
|
|
||||||
/* Different default for gw_mode */
|
|
||||||
if (!c->gw_mode)
|
|
||||||
c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
|
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
|
||||||
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""};
|
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""};
|
||||||
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket" };
|
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket" };
|
||||||
@ -1124,28 +1159,6 @@ bgp_show_proto_info(struct proto *P)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
bgp_reconfigure(struct proto *P, struct proto_config *C)
|
|
||||||
{
|
|
||||||
struct bgp_config *new = (struct bgp_config *) C;
|
|
||||||
struct bgp_proto *p = (struct bgp_proto *) P;
|
|
||||||
struct bgp_config *old = p->cf;
|
|
||||||
|
|
||||||
int same = !memcmp(((byte *) old) + sizeof(struct proto_config),
|
|
||||||
((byte *) new) + sizeof(struct proto_config),
|
|
||||||
// password item is last and must be checked separately
|
|
||||||
OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config))
|
|
||||||
&& ((!old->password && !new->password)
|
|
||||||
|| (old->password && new->password && !strcmp(old->password, new->password)))
|
|
||||||
&& (get_igp_table(old) == get_igp_table(new));
|
|
||||||
|
|
||||||
/* We should update our copy of configuration ptr as old configuration will be freed */
|
|
||||||
if (same)
|
|
||||||
p->cf = new;
|
|
||||||
|
|
||||||
return same;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct protocol proto_bgp = {
|
struct protocol proto_bgp = {
|
||||||
name: "BGP",
|
name: "BGP",
|
||||||
template: "bgp%d",
|
template: "bgp%d",
|
||||||
@ -1155,6 +1168,7 @@ struct protocol proto_bgp = {
|
|||||||
shutdown: bgp_shutdown,
|
shutdown: bgp_shutdown,
|
||||||
cleanup: bgp_cleanup,
|
cleanup: bgp_cleanup,
|
||||||
reconfigure: bgp_reconfigure,
|
reconfigure: bgp_reconfigure,
|
||||||
|
copy_config: bgp_copy_config,
|
||||||
get_status: bgp_get_status,
|
get_status: bgp_get_status,
|
||||||
get_attr: bgp_get_attr,
|
get_attr: bgp_get_attr,
|
||||||
get_route_info: bgp_get_route_info,
|
get_route_info: bgp_get_route_info,
|
||||||
|
@ -141,7 +141,7 @@ extern struct linpool *bgp_linpool;
|
|||||||
|
|
||||||
|
|
||||||
void bgp_start_timer(struct timer *t, int value);
|
void bgp_start_timer(struct timer *t, int value);
|
||||||
void bgp_check(struct bgp_config *c);
|
void bgp_check_config(struct bgp_config *c);
|
||||||
void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
|
void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len);
|
||||||
void bgp_close_conn(struct bgp_conn *c);
|
void bgp_close_conn(struct bgp_conn *c);
|
||||||
void bgp_update_startup_delay(struct bgp_proto *p);
|
void bgp_update_startup_delay(struct bgp_proto *p);
|
||||||
|
@ -29,10 +29,10 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
|
|||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
CF_ADDTO(proto, bgp_proto '}' { bgp_check(BGP_CFG); } )
|
CF_ADDTO(proto, bgp_proto '}' { bgp_check_config(BGP_CFG); } )
|
||||||
|
|
||||||
bgp_proto_start: proto_start BGP {
|
bgp_proto_start: proto_start BGP {
|
||||||
this_proto = proto_config_new(&proto_bgp, sizeof(struct bgp_config));
|
this_proto = proto_config_new(&proto_bgp, sizeof(struct bgp_config), $1);
|
||||||
this_proto->preference = DEF_PREF_BGP;
|
this_proto->preference = DEF_PREF_BGP;
|
||||||
BGP_CFG->hold_time = 240;
|
BGP_CFG->hold_time = 240;
|
||||||
BGP_CFG->connect_retry_time = 120;
|
BGP_CFG->connect_retry_time = 120;
|
||||||
|
@ -128,7 +128,7 @@ CF_GRAMMAR
|
|||||||
CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } )
|
CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } )
|
||||||
|
|
||||||
ospf_proto_start: proto_start OSPF {
|
ospf_proto_start: proto_start OSPF {
|
||||||
this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config));
|
this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
|
||||||
this_proto->preference = DEF_PREF_OSPF;
|
this_proto->preference = DEF_PREF_OSPF;
|
||||||
init_list(&OSPF_CFG->area_list);
|
init_list(&OSPF_CFG->area_list);
|
||||||
init_list(&OSPF_CFG->vlink_list);
|
init_list(&OSPF_CFG->vlink_list);
|
||||||
|
@ -85,8 +85,8 @@ struct ospf_config
|
|||||||
byte rfc1583;
|
byte rfc1583;
|
||||||
byte abr;
|
byte abr;
|
||||||
int ecmp;
|
int ecmp;
|
||||||
list area_list;
|
list area_list; /* list of struct ospf_area_config */
|
||||||
list vlink_list;
|
list vlink_list; /* list of struct ospf_iface_patt */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nbma_node
|
struct nbma_node
|
||||||
|
@ -23,7 +23,7 @@ CF_GRAMMAR
|
|||||||
CF_ADDTO(proto, pipe_proto '}')
|
CF_ADDTO(proto, pipe_proto '}')
|
||||||
|
|
||||||
pipe_proto_start: proto_start PIPE {
|
pipe_proto_start: proto_start PIPE {
|
||||||
this_proto = proto_config_new(&proto_pipe, sizeof(struct pipe_config));
|
this_proto = proto_config_new(&proto_pipe, sizeof(struct pipe_config), $1);
|
||||||
this_proto->preference = DEF_PREF_PIPE;
|
this_proto->preference = DEF_PREF_PIPE;
|
||||||
PIPE_CFG->mode = PIPE_TRANSPARENT;
|
PIPE_CFG->mode = PIPE_TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
@ -165,14 +165,6 @@ pipe_postconfig(struct proto_config *C)
|
|||||||
cf_error("Primary table and peer table must be different");
|
cf_error("Primary table and peer table must be different");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pipe_get_status(struct proto *P, byte *buf)
|
|
||||||
{
|
|
||||||
struct pipe_proto *p = (struct pipe_proto *) P;
|
|
||||||
|
|
||||||
bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pipe_reconfigure(struct proto *P, struct proto_config *new)
|
pipe_reconfigure(struct proto *P, struct proto_config *new)
|
||||||
{
|
{
|
||||||
@ -186,6 +178,21 @@ pipe_reconfigure(struct proto *P, struct proto_config *new)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pipe_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
/* Just a shallow copy, not many items here */
|
||||||
|
proto_copy_rest(dest, src, sizeof(struct pipe_config));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pipe_get_status(struct proto *P, byte *buf)
|
||||||
|
{
|
||||||
|
struct pipe_proto *p = (struct pipe_proto *) P;
|
||||||
|
|
||||||
|
bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct protocol proto_pipe = {
|
struct protocol proto_pipe = {
|
||||||
name: "Pipe",
|
name: "Pipe",
|
||||||
@ -195,5 +202,6 @@ struct protocol proto_pipe = {
|
|||||||
start: pipe_start,
|
start: pipe_start,
|
||||||
cleanup: pipe_cleanup,
|
cleanup: pipe_cleanup,
|
||||||
reconfigure: pipe_reconfigure,
|
reconfigure: pipe_reconfigure,
|
||||||
|
copy_config: pipe_copy_config,
|
||||||
get_status: pipe_get_status,
|
get_status: pipe_get_status,
|
||||||
};
|
};
|
||||||
|
@ -318,6 +318,19 @@ radv_reconfigure(struct proto *p, struct proto_config *c)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
radv_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
struct radv_config *d = (struct radv_config *) dest;
|
||||||
|
struct radv_config *s = (struct radv_config *) src;
|
||||||
|
|
||||||
|
/* We clean up patt_list, ifaces are non-sharable */
|
||||||
|
init_list(&d->patt_list);
|
||||||
|
|
||||||
|
/* We copy pref_list, shallow copy suffices */
|
||||||
|
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct protocol proto_radv = {
|
struct protocol proto_radv = {
|
||||||
.name = "RAdv",
|
.name = "RAdv",
|
||||||
@ -325,5 +338,6 @@ struct protocol proto_radv = {
|
|||||||
.init = radv_init,
|
.init = radv_init,
|
||||||
.start = radv_start,
|
.start = radv_start,
|
||||||
.shutdown = radv_shutdown,
|
.shutdown = radv_shutdown,
|
||||||
.reconfigure = radv_reconfigure
|
.reconfigure = radv_reconfigure,
|
||||||
|
.copy_config = radv_copy_config
|
||||||
};
|
};
|
||||||
|
@ -46,14 +46,14 @@
|
|||||||
struct radv_config
|
struct radv_config
|
||||||
{
|
{
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
list patt_list; /* List of iface configs */
|
list patt_list; /* List of iface configs (struct radv_iface_config) */
|
||||||
list pref_list; /* Global list of prefix configs */
|
list pref_list; /* Global list of prefix configs (struct radv_prefix_config) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct radv_iface_config
|
struct radv_iface_config
|
||||||
{
|
{
|
||||||
struct iface_patt i;
|
struct iface_patt i;
|
||||||
list pref_list; /* Local list of prefix configs */
|
list pref_list; /* Local list of prefix configs (struct radv_prefix_config) */
|
||||||
|
|
||||||
u32 min_ra_int; /* Standard options from RFC 4261 */
|
u32 min_ra_int; /* Standard options from RFC 4261 */
|
||||||
u32 max_ra_int;
|
u32 max_ra_int;
|
||||||
|
@ -37,7 +37,7 @@ CF_GRAMMAR
|
|||||||
CF_ADDTO(proto, rip_cfg '}' { RIP_CFG->passwords = get_passwords(); } )
|
CF_ADDTO(proto, rip_cfg '}' { RIP_CFG->passwords = get_passwords(); } )
|
||||||
|
|
||||||
rip_cfg_start: proto_start RIP {
|
rip_cfg_start: proto_start RIP {
|
||||||
this_proto = proto_config_new(&proto_rip, sizeof(struct rip_proto_config));
|
this_proto = proto_config_new(&proto_rip, sizeof(struct rip_proto_config), $1);
|
||||||
rip_init_config(RIP_CFG);
|
rip_init_config(RIP_CFG);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -1015,6 +1015,19 @@ rip_reconfigure(struct proto *p, struct proto_config *c)
|
|||||||
sizeof(struct rip_proto_config) - generic);
|
sizeof(struct rip_proto_config) - generic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rip_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
/* Shallow copy of everything */
|
||||||
|
proto_copy_rest(dest, src, sizeof(struct rip_proto_config));
|
||||||
|
|
||||||
|
/* We clean up iface_list, ifaces are non-sharable */
|
||||||
|
init_list(&((struct rip_proto_config *) dest)->iface_list);
|
||||||
|
|
||||||
|
/* Copy of passwords is OK, it just will be replaced in dest when used */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct protocol proto_rip = {
|
struct protocol proto_rip = {
|
||||||
name: "RIP",
|
name: "RIP",
|
||||||
template: "rip%d",
|
template: "rip%d",
|
||||||
@ -1026,4 +1039,5 @@ struct protocol proto_rip = {
|
|||||||
dump: rip_dump,
|
dump: rip_dump,
|
||||||
start: rip_start,
|
start: rip_start,
|
||||||
reconfigure: rip_reconfigure,
|
reconfigure: rip_reconfigure,
|
||||||
|
copy_config: rip_copy_config
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,7 @@ CF_GRAMMAR
|
|||||||
CF_ADDTO(proto, static_proto '}')
|
CF_ADDTO(proto, static_proto '}')
|
||||||
|
|
||||||
static_proto_start: proto_start STATIC {
|
static_proto_start: proto_start STATIC {
|
||||||
this_proto = proto_config_new(&proto_static, sizeof(struct static_config));
|
this_proto = proto_config_new(&proto_static, sizeof(struct static_config), $1);
|
||||||
static_init_config((struct static_config *) this_proto);
|
static_init_config((struct static_config *) this_proto);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -470,6 +470,58 @@ static_reconfigure(struct proto *p, struct proto_config *new)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
static_copy_routes(list *dlst, list *slst)
|
||||||
|
{
|
||||||
|
struct static_route *dr, *sr;
|
||||||
|
|
||||||
|
init_list(dlst);
|
||||||
|
WALK_LIST(sr, *slst)
|
||||||
|
{
|
||||||
|
/* copy one route */
|
||||||
|
dr = cfg_alloc(sizeof(struct static_route));
|
||||||
|
memcpy(dr, sr, sizeof(struct static_route));
|
||||||
|
|
||||||
|
/* This fn is supposed to be called on fresh src routes, which have 'live'
|
||||||
|
fields (like .chain, .neigh or .installed) zero, so no need to zero them */
|
||||||
|
|
||||||
|
/* We need to copy multipath chain, because there are backptrs in 'if_name' */
|
||||||
|
if (dr->dest == RTD_MULTIPATH)
|
||||||
|
{
|
||||||
|
struct static_route *md, *ms, **mp_last;
|
||||||
|
|
||||||
|
mp_last = &(dr->mp_next);
|
||||||
|
for (ms = sr->mp_next; ms; ms = ms->mp_next)
|
||||||
|
{
|
||||||
|
md = cfg_alloc(sizeof(struct static_route));
|
||||||
|
memcpy(md, ms, sizeof(struct static_route));
|
||||||
|
md->if_name = (void *) dr; /* really */
|
||||||
|
|
||||||
|
*mp_last = md;
|
||||||
|
mp_last = &(md->mp_next);
|
||||||
|
}
|
||||||
|
*mp_last = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_tail(dlst, (node *) dr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
static_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
struct static_config *d = (struct static_config *) dest;
|
||||||
|
struct static_config *s = (struct static_config *) src;
|
||||||
|
|
||||||
|
/* Shallow copy of everything */
|
||||||
|
proto_copy_rest(dest, src, sizeof(struct static_config));
|
||||||
|
|
||||||
|
/* Copy route lists */
|
||||||
|
static_copy_routes(&d->iface_routes, &s->iface_routes);
|
||||||
|
static_copy_routes(&d->other_routes, &s->other_routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct protocol proto_static = {
|
struct protocol proto_static = {
|
||||||
name: "Static",
|
name: "Static",
|
||||||
template: "static%d",
|
template: "static%d",
|
||||||
@ -479,6 +531,7 @@ struct protocol proto_static = {
|
|||||||
shutdown: static_shutdown,
|
shutdown: static_shutdown,
|
||||||
cleanup: static_cleanup,
|
cleanup: static_cleanup,
|
||||||
reconfigure: static_reconfigure,
|
reconfigure: static_reconfigure,
|
||||||
|
copy_config: static_copy_config
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -12,6 +12,14 @@
|
|||||||
/*
|
/*
|
||||||
* We don't have split iface/scan/set parts. See krt-sock.h.
|
* We don't have split iface/scan/set parts. See krt-sock.h.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct krt_if_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_if_status {
|
||||||
|
};
|
||||||
|
|
||||||
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
||||||
|
static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,5 +17,6 @@ struct krt_scan_status {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static inline int krt_scan_params_same(struct krt_scan_params *o UNUSED, struct krt_scan_params *n UNUSED) { return 1; }
|
static inline int krt_scan_params_same(struct krt_scan_params *o UNUSED, struct krt_scan_params *n UNUSED) { return 1; }
|
||||||
|
static inline void krt_scan_copy_params(struct krt_scan_params *d UNUSED, struct krt_scan_params *s UNUSED) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,13 +34,9 @@ struct krt_set_params {
|
|||||||
struct krt_set_status {
|
struct krt_set_status {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct krt_if_params {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct krt_if_status {
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
||||||
|
static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
|
||||||
|
|
||||||
void krt_read_msg(struct proto *p, struct ks_msg *msg, int scan);
|
void krt_read_msg(struct proto *p, struct ks_msg *msg, int scan);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,5 +24,6 @@ static inline void krt_if_shutdown(struct kif_proto *p UNUSED) { };
|
|||||||
static inline void krt_if_io_init(void) { };
|
static inline void krt_if_io_init(void) { };
|
||||||
|
|
||||||
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
||||||
|
static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,4 +30,7 @@ static inline int krt_scan_params_same(struct krt_scan_params *o, struct krt_sca
|
|||||||
return o->table_id == n->table_id;
|
return o->table_id == n->table_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void krt_scan_copy_params(struct krt_scan_params *d UNUSED, struct krt_scan_params *s UNUSED) { }
|
||||||
|
/* table_id copied in krt_copy_config() */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,5 +23,6 @@ static inline void krt_set_construct(struct krt_config *c UNUSED) { };
|
|||||||
static inline void krt_set_start(struct krt_proto *p UNUSED, int first UNUSED) { };
|
static inline void krt_set_start(struct krt_proto *p UNUSED, int first UNUSED) { };
|
||||||
static inline void krt_set_shutdown(struct krt_proto *p UNUSED, int last UNUSED) { };
|
static inline void krt_set_shutdown(struct krt_proto *p UNUSED, int last UNUSED) { };
|
||||||
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
||||||
|
static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,6 +17,7 @@ struct krt_if_status {
|
|||||||
|
|
||||||
extern int if_scan_sock;
|
extern int if_scan_sock;
|
||||||
|
|
||||||
static inline int kif_params_same(struct krt_if_params *old, struct krt_if_params *new) { return 1; }
|
static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; }
|
||||||
|
static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,5 +16,6 @@ struct krt_set_status {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; }
|
||||||
|
static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,7 @@ kern_proto_start: proto_start KERNEL {
|
|||||||
if (cf_krt)
|
if (cf_krt)
|
||||||
cf_error("Kernel protocol already defined");
|
cf_error("Kernel protocol already defined");
|
||||||
#endif
|
#endif
|
||||||
cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config));
|
cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), $1);
|
||||||
this_proto->preference = DEF_PREF_INHERITED;
|
this_proto->preference = DEF_PREF_INHERITED;
|
||||||
THIS_KRT->scan_time = 60;
|
THIS_KRT->scan_time = 60;
|
||||||
THIS_KRT->learn = THIS_KRT->persist = 0;
|
THIS_KRT->learn = THIS_KRT->persist = 0;
|
||||||
@ -66,7 +66,7 @@ CF_ADDTO(proto, kif_proto '}')
|
|||||||
kif_proto_start: proto_start DEVICE {
|
kif_proto_start: proto_start DEVICE {
|
||||||
if (cf_kif)
|
if (cf_kif)
|
||||||
cf_error("Kernel device protocol already defined");
|
cf_error("Kernel device protocol already defined");
|
||||||
cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct kif_config));
|
cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct kif_config), $1);
|
||||||
this_proto->preference = DEF_PREF_DIRECT;
|
this_proto->preference = DEF_PREF_DIRECT;
|
||||||
THIS_KIF->scan_time = 60;
|
THIS_KIF->scan_time = 60;
|
||||||
init_list(&THIS_KIF->primary);
|
init_list(&THIS_KIF->primary);
|
||||||
|
@ -216,6 +216,23 @@ kif_reconfigure(struct proto *p, struct proto_config *new)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kif_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
struct kif_config *d = (struct kif_config *) dest;
|
||||||
|
struct kif_config *s = (struct kif_config *) src;
|
||||||
|
|
||||||
|
/* Shallow copy of everything (just scan_time currently) */
|
||||||
|
proto_copy_rest(dest, src, sizeof(struct krt_config));
|
||||||
|
|
||||||
|
/* Copy primary addr list */
|
||||||
|
cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item));
|
||||||
|
|
||||||
|
/* Fix sysdep parts */
|
||||||
|
kif_copy_params(&d->iface, &s->iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct protocol proto_unix_iface = {
|
struct protocol proto_unix_iface = {
|
||||||
name: "Device",
|
name: "Device",
|
||||||
template: "device%d",
|
template: "device%d",
|
||||||
@ -224,6 +241,7 @@ struct protocol proto_unix_iface = {
|
|||||||
start: kif_start,
|
start: kif_start,
|
||||||
shutdown: kif_shutdown,
|
shutdown: kif_shutdown,
|
||||||
reconfigure: kif_reconfigure,
|
reconfigure: kif_reconfigure,
|
||||||
|
copy_config: kif_copy_config
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -908,6 +926,19 @@ krt_reconfigure(struct proto *p, struct proto_config *new)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
krt_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||||
|
{
|
||||||
|
struct krt_config *d = (struct krt_config *) dest;
|
||||||
|
struct krt_config *s = (struct krt_config *) src;
|
||||||
|
|
||||||
|
/* Shallow copy of everything */
|
||||||
|
proto_copy_rest(dest, src, sizeof(struct krt_config));
|
||||||
|
|
||||||
|
/* Fix sysdep parts */
|
||||||
|
krt_set_copy_params(&d->set, &s->set);
|
||||||
|
krt_scan_copy_params(&d->scan, &s->scan);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_get_attr(eattr * a, byte * buf, int buflen UNUSED)
|
krt_get_attr(eattr * a, byte * buf, int buflen UNUSED)
|
||||||
@ -936,6 +967,7 @@ struct protocol proto_unix_kernel = {
|
|||||||
start: krt_start,
|
start: krt_start,
|
||||||
shutdown: krt_shutdown,
|
shutdown: krt_shutdown,
|
||||||
reconfigure: krt_reconfigure,
|
reconfigure: krt_reconfigure,
|
||||||
|
copy_config: krt_copy_config,
|
||||||
get_attr: krt_get_attr,
|
get_attr: krt_get_attr,
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
dump: krt_dump,
|
dump: krt_dump,
|
||||||
|
@ -100,7 +100,7 @@ struct kif_config {
|
|||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
struct krt_if_params iface;
|
struct krt_if_params iface;
|
||||||
int scan_time; /* How often we re-scan interfaces */
|
int scan_time; /* How often we re-scan interfaces */
|
||||||
list primary; /* Preferences for primary addresses */
|
list primary; /* Preferences for primary addresses (struct kif_primary_item) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kif_proto {
|
struct kif_proto {
|
||||||
|
Loading…
Reference in New Issue
Block a user