summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-rw-r--r--proto/bfd/bfd.c3
-rw-r--r--proto/bgp/bgp.c1
-rw-r--r--proto/bgp/config.Y6
-rw-r--r--proto/ospf/config.Y25
-rw-r--r--proto/ospf/ospf.c37
-rw-r--r--proto/ospf/rt.c5
-rw-r--r--proto/pipe/config.Y25
-rw-r--r--proto/pipe/pipe.c238
-rw-r--r--proto/pipe/pipe.h16
-rw-r--r--proto/radv/config.Y7
-rw-r--r--proto/radv/radv.c48
-rw-r--r--proto/radv/radv.h3
-rw-r--r--proto/rip/config.Y5
-rw-r--r--proto/rip/rip.c43
-rw-r--r--proto/static/config.Y11
-rw-r--r--proto/static/static.c69
16 files changed, 271 insertions, 271 deletions
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index 110bf931..62752e21 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -952,7 +952,7 @@ bfd_init_all(void)
static struct proto *
bfd_init(struct proto_config *c)
{
- struct proto *p = proto_new(c, sizeof(struct bfd_proto));
+ struct proto *p = proto_new(c);
p->neigh_notify = bfd_neigh_notify;
@@ -1118,6 +1118,7 @@ bfd_show_sessions(struct proto *P)
struct protocol proto_bfd = {
.name = "BFD",
.template = "bfd%d",
+ .proto_size = sizeof(struct bfd_proto),
.config_size = sizeof(struct bfd_config),
.init = bfd_init,
.start = bfd_start,
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index f549b0ed..cb5b108c 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1372,7 +1372,6 @@ 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));
}
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 85b93a6b..614ef08c 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -112,12 +112,6 @@ bgp_proto:
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
| bgp_proto PASSWORD text ';' { BGP_CFG->password = $3; }
- | bgp_proto ROUTE LIMIT expr ';' {
- this_proto->in_limit = cfg_allocz(sizeof(struct proto_limit));
- this_proto->in_limit->limit = $4;
- this_proto->in_limit->action = PLA_RESTART;
- log(L_WARN "%s: Route limit option is deprecated, use import limit", this_proto->name);
- }
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
| bgp_proto SECONDARY bool ';' { BGP_CFG->secondary = $3; }
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 881ec781..297774b5 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -68,6 +68,10 @@ ospf_proto_finish(void)
if (EMPTY_LIST(cf->area_list))
cf_error( "No configured areas in OSPF");
+ /* Define default channel */
+ if (EMPTY_LIST(this_proto->channels))
+ channel_config_new(NULL, this_proto->net_type, this_proto);
+
int areano = 0;
int backbone = 0;
int nssa = 0;
@@ -84,7 +88,7 @@ ospf_proto_finish(void)
cf->abr = areano > 1;
/* Route export or NSSA translation (RFC 3101 3.1) */
- cf->asbr = (this_proto->out_filter != FILTER_REJECT) || (nssa && cf->abr);
+ cf->asbr = (proto_cf_main_channel(this_proto)->out_filter != FILTER_REJECT) || (nssa && cf->abr);
if (cf->abr && !backbone)
{
@@ -145,14 +149,16 @@ ospf_variant:
| OSPF3 { $$ = 0; }
;
-ospf_proto_start: proto_start ospf_variant {
- this_proto = proto_config_new(&proto_ospf, $1);
- init_list(&OSPF_CFG->area_list);
- init_list(&OSPF_CFG->vlink_list);
- OSPF_CFG->tick = OSPF_DEFAULT_TICK;
- OSPF_CFG->ospf2 = $2;
- }
- ;
+ospf_proto_start: proto_start ospf_variant
+{
+ this_proto = proto_config_new(&proto_ospf, $1);
+ this_proto->net_type = $2 ? NET_IP4 : NET_IP6;
+
+ init_list(&OSPF_CFG->area_list);
+ init_list(&OSPF_CFG->vlink_list);
+ OSPF_CFG->tick = OSPF_DEFAULT_TICK;
+ OSPF_CFG->ospf2 = $2;
+};
ospf_proto:
ospf_proto_start proto_name '{'
@@ -161,6 +167,7 @@ ospf_proto:
ospf_proto_item:
proto_item
+ | proto_channel
| RFC1583COMPAT bool { OSPF_CFG->rfc1583 = $2; }
| STUB ROUTER bool { OSPF_CFG->stub_router = $3; }
| ECMP bool { OSPF_CFG->ecmp = $2 ? OSPF_DEFAULT_ECMP_LIMIT : 0; }
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 1c128794..d074600a 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -102,7 +102,7 @@
static int ospf_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool);
static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
static void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs);
-static int ospf_reload_routes(struct proto *P);
+static void ospf_reload_routes(struct channel *C);
static int ospf_rte_better(struct rte *new, struct rte *old);
static int ospf_rte_same(struct rte *new, struct rte *old);
static void ospf_disp(timer *timer);
@@ -297,15 +297,16 @@ ospf_dump(struct proto *P)
}
static struct proto *
-ospf_init(struct proto_config *c)
+ospf_init(struct proto_config *CF)
{
- struct ospf_config *oc = (struct ospf_config *) c;
- struct proto *P = proto_new(c, sizeof(struct ospf_proto));
+ struct ospf_config *cf = (struct ospf_config *) CF;
+ struct proto *P = proto_new(CF);
+
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- P->accept_ra_types = RA_OPTIMAL;
P->rt_notify = ospf_rt_notify;
P->if_notify = ospf_if_notify;
- P->ifa_notify = oc->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3;
+ P->ifa_notify = cf->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3;
P->import_control = ospf_import_control;
P->reload_routes = ospf_reload_routes;
P->make_tmp_attrs = ospf_make_tmp_attrs;
@@ -389,17 +390,16 @@ ospf_schedule_rtcalc(struct ospf_proto *p)
p->calcrt = 1;
}
-static int
-ospf_reload_routes(struct proto *P)
+static void
+ospf_reload_routes(struct channel *C)
{
- struct ospf_proto *p = (struct ospf_proto *) P;
+ struct ospf_proto *p = (struct ospf_proto *) C->proto;
- if (p->calcrt != 2)
- OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation with route reload");
+ if (p->calcrt == 2)
+ return;
+ OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation with route reload");
p->calcrt = 2;
-
- return 1;
}
@@ -637,17 +637,17 @@ ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
* nonbroadcast network, cost of interface, etc.
*/
static int
-ospf_reconfigure(struct proto *P, struct proto_config *c)
+ospf_reconfigure(struct proto *P, struct proto_config *CF)
{
struct ospf_proto *p = (struct ospf_proto *) P;
struct ospf_config *old = (struct ospf_config *) (P->cf);
- struct ospf_config *new = (struct ospf_config *) c;
+ struct ospf_config *new = (struct ospf_config *) CF;
struct ospf_area_config *nac;
struct ospf_area *oa, *oax;
struct ospf_iface *ifa, *ifx;
struct ospf_iface_patt *ip;
- if (proto_get_router_id(c) != p->router_id)
+ if (proto_get_router_id(CF) != p->router_id)
return 0;
if (p->ospf2 != new->ospf2)
@@ -659,6 +659,9 @@ ospf_reconfigure(struct proto *P, struct proto_config *c)
if (old->abr != new->abr)
return 0;
+ if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
+ return 0;
+
p->stub_router = new->stub_router;
p->merge_external = new->merge_external;
p->asbr = new->asbr;
@@ -1465,6 +1468,8 @@ struct protocol proto_ospf = {
.template = "ospf%d",
.attr_class = EAP_OSPF,
.preference = DEF_PREF_OSPF,
+ .channel_mask = NB_IP,
+ .proto_size = sizeof(struct ospf_proto),
.config_size = sizeof(struct ospf_config),
.init = ospf_init,
.dump = ospf_dump,
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 21a3e300..0855f21f 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -1973,7 +1973,7 @@ again1:
if (reload || ort_changed(nf, &a0))
{
- net *ne = net_get(p->p.table, nf->fn.addr);
+ net *ne = net_get(p->p.main_channel->table, nf->fn.addr);
rta *a = rta_lookup(&a0);
rte *e = rte_get_temp(a);
@@ -1985,7 +1985,6 @@ again1:
e->u.ospf.router_id = nf->old_rid = nf->n.rid;
e->pflags = 0;
e->net = ne;
- e->pref = p->p.preference;
DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
@@ -1998,7 +1997,7 @@ again1:
rta_free(nf->old_rta);
nf->old_rta = NULL;
- net *ne = net_get(p->p.table, nf->fn.addr);
+ net *ne = net_get(p->p.main_channel->table, nf->fn.addr);
rte_update(&p->p, ne, NULL);
}
diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y
index 8daf2e7c..f51ee575 100644
--- a/proto/pipe/config.Y
+++ b/proto/pipe/config.Y
@@ -16,28 +16,25 @@ CF_DEFINES
CF_DECLS
-CF_KEYWORDS(PIPE, PEER, TABLE, MODE, OPAQUE, TRANSPARENT)
+CF_KEYWORDS(PIPE, PEER, TABLE)
CF_GRAMMAR
-CF_ADDTO(proto, pipe_proto '}')
+CF_ADDTO(proto, pipe_proto '}' { this_channel = NULL; } )
-pipe_proto_start: proto_start PIPE {
- this_proto = proto_config_new(&proto_pipe, $1);
- PIPE_CFG->mode = PIPE_TRANSPARENT;
- }
- ;
+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->in_filter = FILTER_ACCEPT;
+ this_channel->out_filter = FILTER_ACCEPT;
+};
pipe_proto:
pipe_proto_start proto_name '{'
| pipe_proto proto_item ';'
- | pipe_proto PEER TABLE SYM ';' {
- if ($4->class != SYM_TABLE)
- cf_error("Routing table name expected");
- PIPE_CFG->peer = $4->def;
- }
- | pipe_proto MODE OPAQUE ';' { PIPE_CFG->mode = PIPE_OPAQUE; }
- | pipe_proto MODE TRANSPARENT ';' { PIPE_CFG->mode = PIPE_TRANSPARENT; }
+ | pipe_proto channel_item ';'
+ | pipe_proto PEER TABLE rtable ';' { PIPE_CFG->peer = $4; }
;
CF_CODE
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 42285880..57db3e8b 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -46,9 +46,8 @@
static void
pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, ea_list *attrs)
{
- struct pipe_proto *p = (struct pipe_proto *) P;
- struct announce_hook *ah = (src_table == P->table) ? p->peer_ahook : P->main_ahook;
- rtable *dst_table = ah->table;
+ struct pipe_proto *p = (void *) P;
+ struct channel *dst = (src_table == p->pri->table) ? p->sec : p->pri;
struct rte_src *src;
net *nn;
@@ -58,24 +57,18 @@ pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, e
if (!new && !old)
return;
- if (dst_table->pipe_busy)
+ if (dst->table->pipe_busy)
{
log(L_ERR "Pipe loop detected when sending %N to table %s",
- n->n.addr, dst_table->name);
+ n->n.addr, dst->table->name);
return;
}
- nn = net_get(dst_table, n->n.addr);
+ nn = net_get(dst->table, n->n.addr);
if (new)
{
memcpy(&a, new->attrs, sizeof(rta));
- if (p->mode == PIPE_OPAQUE)
- {
- a.src = P->main_source;
- a.source = RTS_PIPE;
- }
-
a.aflags = 0;
a.eattrs = attrs;
a.hostentry = NULL;
@@ -83,13 +76,10 @@ pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, e
e->net = nn;
e->pflags = 0;
- if (p->mode == PIPE_TRANSPARENT)
- {
- /* Copy protocol specific embedded attributes. */
- memcpy(&(e->u), &(new->u), sizeof(e->u));
- e->pref = new->pref;
- e->pflags = new->pflags;
- }
+ /* Copy protocol specific embedded attributes. */
+ memcpy(&(e->u), &(new->u), sizeof(e->u));
+ e->pref = new->pref;
+ e->pflags = new->pflags;
src = a.src;
}
@@ -100,7 +90,7 @@ pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, e
}
src_table->pipe_busy = 1;
- rte_update2(ah, nn, e, src);
+ rte_update2(dst, nn, e, src);
src_table->pipe_busy = 0;
}
@@ -111,171 +101,117 @@ pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpo
if (pp == P)
return -1; /* Avoid local loops automatically */
+
return 0;
}
-static int
-pipe_reload_routes(struct proto *P)
+static void
+pipe_reload_routes(struct channel *C)
{
- struct pipe_proto *p = (struct pipe_proto *) P;
-
- /*
- * Because the pipe protocol feeds routes from both routing tables
- * together, both directions are reloaded during refeed and 'reload
- * out' command works like 'reload' command. For symmetry, we also
- * request refeed when 'reload in' command is used.
- */
- proto_request_feeding(P);
+ struct pipe_proto *p = (void *) C->proto;
- proto_reset_limit(P->main_ahook->in_limit);
- proto_reset_limit(p->peer_ahook->in_limit);
-
- return 1;
+ /* Route reload on one channel is just refeed on the other */
+ channel_request_feeding((C == p->pri) ? p->sec : p->pri);
}
-static struct proto *
-pipe_init(struct proto_config *C)
-{
- struct pipe_config *c = (struct pipe_config *) C;
- struct proto *P = proto_new(C, sizeof(struct pipe_proto));
- struct pipe_proto *p = (struct pipe_proto *) P;
- p->mode = c->mode;
- p->peer_table = c->peer->table;
- P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
- P->rt_notify = pipe_rt_notify;
- P->import_control = pipe_import_control;
- P->reload_routes = pipe_reload_routes;
-
- return P;
-}
-
-static int
-pipe_start(struct proto *P)
+static void
+pipe_postconfig(struct proto_config *CF)
{
- struct pipe_config *cf = (struct pipe_config *) P->cf;
- struct pipe_proto *p = (struct pipe_proto *) P;
+ struct pipe_config *cf = (void *) CF;
+ struct channel_config *cc = proto_cf_main_channel(CF);
- /* Lock both tables, unlock is handled in pipe_cleanup() */
- rt_lock_table(P->table);
- rt_lock_table(p->peer_table);
+ if (!cc->table)
+ cf_error("Primary routing table not specified");
- /* Going directly to PS_UP - prepare for feeding,
- connect the protocol to both routing tables */
+ if (!cf->peer)
+ cf_error("Secondary routing table not specified");
- P->main_ahook = proto_add_announce_hook(P, P->table, &P->stats);
- P->main_ahook->out_filter = cf->c.out_filter;
- P->main_ahook->in_limit = cf->c.in_limit;
- proto_reset_limit(P->main_ahook->in_limit);
+ if (cc->table == cf->peer)
+ cf_error("Primary table and peer table must be different");
- p->peer_ahook = proto_add_announce_hook(P, p->peer_table, &p->peer_stats);
- p->peer_ahook->out_filter = cf->c.in_filter;
- p->peer_ahook->in_limit = cf->c.out_limit;
- proto_reset_limit(p->peer_ahook->in_limit);
+ if (cc->table->addr_type != cf->peer->addr_type)
+ cf_error("Primary table and peer table must have the same type");
- if (p->mode == PIPE_OPAQUE)
- {
- P->main_source = rt_get_source(P, 0);
- rt_lock_source(P->main_source);
- }
+ if (cc->rx_limit.action)
+ cf_error("Pipe protocol does not support receive limits");
- return PS_UP;
+ if (cc->in_keep_filtered)
+ cf_error("Pipe protocol prohibits keeping filtered routes");
}
-static void
-pipe_cleanup(struct proto *P)
+static int
+pipe_configure_channels(struct pipe_proto *p, struct pipe_config *cf)
{
- struct pipe_proto *p = (struct pipe_proto *) P;
-
- bzero(&P->stats, sizeof(struct proto_stats));
- bzero(&p->peer_stats, sizeof(struct proto_stats));
-
- P->main_ahook = NULL;
- p->peer_ahook = NULL;
-
- if (p->mode == PIPE_OPAQUE)
- rt_unlock_source(P->main_source);
- P->main_source = NULL;
-
- rt_unlock_table(P->table);
- rt_unlock_table(p->peer_table);
+ struct channel_config *cc = proto_cf_main_channel(&cf->c);
+
+ struct channel_config pri_cf = {
+ .name = "pri",
+ .channel = cc->channel,
+ .table = cc->table,
+ .out_filter = cc->out_filter,
+ .in_limit = cc->in_limit,
+ .ra_mode = RA_ANY
+ };
+
+ struct channel_config sec_cf = {
+ .name = "sec",
+ .channel = cc->channel,
+ .table = cf->peer,
+ .out_filter = cc->in_filter,
+ .in_limit = cc->out_limit,
+ .ra_mode = RA_ANY
+ };
+
+ return
+ proto_configure_channel(&p->p, &p->pri, &pri_cf) &&
+ proto_configure_channel(&p->p, &p->sec, &sec_cf);
}
-static void
-pipe_postconfig(struct proto_config *C)
+static struct proto *
+pipe_init(struct proto_config *CF)
{
- struct pipe_config *c = (struct pipe_config *) C;
+ struct proto *P = proto_new(CF);
+ struct pipe_proto *p = (void *) P;
+ struct pipe_config *cf = (void *) CF;
- if (!c->peer)
- cf_error("Name of peer routing table not specified");
- if (c->peer == C->table)
- cf_error("Primary table and peer table must be different");
+ P->rt_notify = pipe_rt_notify;
+ P->import_control = pipe_import_control;
+ P->reload_routes = pipe_reload_routes;
- if (C->in_keep_filtered)
- cf_error("Pipe protocol prohibits keeping filtered routes");
- if (C->rx_limit)
- cf_error("Pipe protocol does not support receive limits");
-}
+ pipe_configure_channels(p, cf);
-extern int proto_reconfig_type;
+ return P;
+}
static int
-pipe_reconfigure(struct proto *P, struct proto_config *new)
+pipe_reconfigure(struct proto *P, struct proto_config *CF)
{
- struct pipe_proto *p = (struct pipe_proto *)P;
- struct proto_config *old = P->cf;
- struct pipe_config *oc = (struct pipe_config *) old;
- struct pipe_config *nc = (struct pipe_config *) new;
-
- if ((oc->peer->table != nc->peer->table) || (oc->mode != nc->mode))
- return 0;
-
- /* Update output filters in ahooks */
- if (P->main_ahook)
- {
- P->main_ahook->out_filter = new->out_filter;
- P->main_ahook->in_limit = new->in_limit;
- proto_verify_limits(P->main_ahook);
- }
-
- if (p->peer_ahook)
- {
- p->peer_ahook->out_filter = new->in_filter;
- p->peer_ahook->in_limit = new->out_limit;
- proto_verify_limits(p->peer_ahook);
- }
-
- if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
- return 1;
-
- if ((new->preference != old->preference)
- || ! filter_same(new->in_filter, old->in_filter)
- || ! filter_same(new->out_filter, old->out_filter))
- proto_request_feeding(P);
+ struct pipe_proto *p = (void *) P;
+ struct pipe_config *cf = (void *) CF;
- return 1;
+ return pipe_configure_channels(p, cf);
}
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;
+ struct pipe_proto *p = (void *) P;
- bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer_table->name);
+ bsprintf(buf, "%s <=> %s", p->pri->table->name, p->sec->table->name);
}
static void
pipe_show_stats(struct pipe_proto *p)
{
- struct proto_stats *s1 = &p->p.stats;
- struct proto_stats *s2 = &p->peer_stats;
+ struct proto_stats *s1 = &p->pri->stats;
+ struct proto_stats *s2 = &p->sec->stats;
/*
* Pipe stats (as anything related to pipes) are a bit tricky. There
@@ -318,17 +254,16 @@ pipe_show_stats(struct pipe_proto *p)
static void
pipe_show_proto_info(struct proto *P)
{
- struct pipe_proto *p = (struct pipe_proto *) P;
- struct pipe_config *cf = (struct pipe_config *) P->cf;
+ struct pipe_proto *p = (void *) P;
- // cli_msg(-1006, " Table: %s", P->table->name);
- // cli_msg(-1006, " Peer table: %s", p->peer_table->name);
- cli_msg(-1006, " Preference: %d", P->preference);
- cli_msg(-1006, " Input filter: %s", filter_name(cf->c.in_filter));
- cli_msg(-1006, " Output filter: %s", filter_name(cf->c.out_filter));
+ cli_msg(-1006, " Channel %s", "main");
+ cli_msg(-1006, " Table: %s", p->pri->table->name);
+ cli_msg(-1006, " Peer table: %s", p->sec->table->name);
+ cli_msg(-1006, " Import filter: %s", filter_name(p->sec->out_filter));
+ cli_msg(-1006, " Export filter: %s", filter_name(p->pri->out_filter));
- proto_show_limit(cf->c.in_limit, "Import limit:");
- proto_show_limit(cf->c.out_limit, "Export limit:");
+ channel_show_limit(&p->pri->in_limit, "Import limit:");
+ channel_show_limit(&p->sec->in_limit, "Export limit:");
if (P->proto_state != PS_DOWN)
pipe_show_stats(p);
@@ -338,13 +273,10 @@ pipe_show_proto_info(struct proto *P)
struct protocol proto_pipe = {
.name = "Pipe",
.template = "pipe%d",
- .multitable = 1,
- .preference = DEF_PREF_PIPE,
+ .proto_size = sizeof(struct pipe_proto),
.config_size = sizeof(struct pipe_config),
.postconfig = pipe_postconfig,
.init = pipe_init,
- .start = pipe_start,
- .cleanup = pipe_cleanup,
.reconfigure = pipe_reconfigure,
.copy_config = pipe_copy_config,
.get_status = pipe_get_status,
diff --git a/proto/pipe/pipe.h b/proto/pipe/pipe.h
index 50b31698..038c6666 100644
--- a/proto/pipe/pipe.h
+++ b/proto/pipe/pipe.h
@@ -9,27 +9,15 @@
#ifndef _BIRD_PIPE_H_
#define _BIRD_PIPE_H_
-#define PIPE_OPAQUE 0
-#define PIPE_TRANSPARENT 1
-
struct pipe_config {
struct proto_config c;
struct rtable_config *peer; /* Table we're connected to */
- int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
};
struct pipe_proto {
struct proto p;
- struct rtable *peer_table;
- struct announce_hook *peer_ahook; /* Announce hook for direction peer->primary */
- struct proto_stats peer_stats; /* Statistics for the direction peer->primary */
- int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
+ struct channel *pri;
+ struct channel *sec;
};
-
-extern struct protocol proto_pipe;
-
-static inline int proto_is_pipe(struct proto *p)
-{ return p->proto == &proto_pipe; }
-
#endif
diff --git a/proto/radv/config.Y b/proto/radv/config.Y
index 5e655de4..7ba23205 100644
--- a/proto/radv/config.Y
+++ b/proto/radv/config.Y
@@ -41,6 +41,7 @@ CF_ADDTO(proto, radv_proto)
radv_proto_start: proto_start RADV
{
this_proto = proto_config_new(&proto_radv, $1);
+
init_list(&RADV_CFG->patt_list);
init_list(&RADV_CFG->pref_list);
init_list(&RADV_CFG->rdnss_list);
@@ -49,14 +50,12 @@ radv_proto_start: proto_start RADV
radv_proto_item:
proto_item
+ | proto_channel
| INTERFACE radv_iface
| PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
| RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_CFG->rdnss_list, &radv_dns_list); }
| DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_CFG->dnssl_list, &radv_dns_list); }
- | TRIGGER net_any {
- RADV_CFG->trigger = $2;
- RADV_CFG->trigger_valid = 1;
- }
+ | TRIGGER net_ip6 { RADV_CFG->trigger = $2; }
;
radv_proto_opts:
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index 97713b95..f9c0940f 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -256,9 +256,16 @@ radv_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
radv_iface_notify(ifa, RA_EV_CHANGE);
}
-static inline int radv_net_match_trigger(struct radv_config *cf, net *n)
+static inline int
+radv_trigger_valid(struct radv_config *cf)
{
- return cf->trigger_valid && net_equal(n->n.addr, cf->trigger);
+ return cf->trigger.type != 0;
+}
+
+static inline int
+radv_net_match_trigger(struct radv_config *cf, net *n)
+{
+ return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger);
}
int
@@ -301,22 +308,35 @@ radv_check_active(struct proto_radv *ra)
{
struct radv_config *cf = (struct radv_config *) (ra->p.cf);
- if (! cf->trigger_valid)
+ if (!radv_trigger_valid(cf))
return 1;
- return rt_examine(ra->p.table, cf->trigger, &ra->p, ra->p.cf->out_filter);
+ struct channel *c =ra->p.main_channel;
+ return rt_examine(c->table, &cf->trigger, &ra->p, c->out_filter);
+}
+
+static void
+radv_postconfig(struct proto_config *CF)
+{
+ // struct radv_config *cf = (void *) CF;
+
+ /* Define default channel */
+ if (EMPTY_LIST(CF->channels))
+ channel_config_new(NULL, NET_IP6, CF);
}
static struct proto *
-radv_init(struct proto_config *c)
+radv_init(struct proto_config *CF)
{
- struct proto *p = proto_new(c, sizeof(struct proto_radv));
+ struct proto *p = proto_new(CF);
+
+ p->main_channel = proto_add_channel(p, proto_cf_main_channel(CF));
- p->accept_ra_types = RA_OPTIMAL;
p->import_control = radv_import_control;
p->rt_notify = radv_rt_notify;
p->if_notify = radv_if_notify;
p->ifa_notify = radv_ifa_notify;
+
return p;
}
@@ -327,7 +347,7 @@ radv_start(struct proto *p)
struct radv_config *cf = (struct radv_config *) (p->cf);
init_list(&(ra->iface_list));
- ra->active = !cf->trigger_valid;
+ ra->active = !radv_trigger_valid(cf);
return PS_UP;
}
@@ -352,11 +372,11 @@ radv_shutdown(struct proto *p)
}
static int
-radv_reconfigure(struct proto *p, struct proto_config *c)
+radv_reconfigure(struct proto *p, struct proto_config *CF)
{
struct proto_radv *ra = (struct proto_radv *) p;
// struct radv_config *old = (struct radv_config *) (p->cf);
- struct radv_config *new = (struct radv_config *) c;
+ struct radv_config *new = (struct radv_config *) CF;
/*
* The question is why there is a reconfigure function for RAdv if
@@ -366,7 +386,10 @@ radv_reconfigure(struct proto *p, struct proto_config *c)
* causing nodes to temporary remove their default routes.
*/
- p->cf = c; /* radv_check_active() requires proper p->cf */
+ if (!proto_configure_channel(p, &p->main_channel, proto_cf_main_channel(CF)))
+ return 0;
+
+ p->cf = CF; /* radv_check_active() requires proper p->cf */
ra->active = radv_check_active(ra);
struct iface *iface;
@@ -423,7 +446,10 @@ radv_get_status(struct proto *p, byte *buf)
struct protocol proto_radv = {
.name = "RAdv",
.template = "radv%d",
+ .channel_mask = NB_IP6,
+ .proto_size = sizeof(struct proto_radv),
.config_size = sizeof(struct radv_config),
+ .postconfig = radv_postconfig,
.init = radv_init,
.start = radv_start,
.shutdown = radv_shutdown,
diff --git a/proto/radv/radv.h b/proto/radv/radv.h
index 755009d4..f8aa421d 100644
--- a/proto/radv/radv.h
+++ b/proto/radv/radv.h
@@ -50,8 +50,7 @@ struct radv_config
list rdnss_list; /* Global list of RDNSS configs (struct radv_rdnss_config) */
list dnssl_list; /* Global list of DNSSL configs (struct radv_dnssl_config) */
- net_addr *trigger; /* Prefix of a trigger route, if defined */
- u8 trigger_valid; /* Whether a trigger route is defined */
+ net_addr trigger; /* Prefix of a trigger route, if defined */
};
struct radv_iface_config
diff --git a/proto/rip/config.Y b/proto/rip/config.Y
index d81c42d7..79e57741 100644
--- a/proto/rip/config.Y
+++ b/proto/rip/config.Y
@@ -52,17 +52,18 @@ rip_variant:
rip_proto_start: proto_start rip_variant
{
this_proto = proto_config_new(&proto_rip, $1);
- init_list(&RIP_CFG->patt_list);
+ this_proto->net_type = $2 ? NET_IP4 : NET_IP6;
+ init_list(&RIP_CFG->patt_list);
RIP_CFG->rip2 = $2;
RIP_CFG->infinity = RIP_DEFAULT_INFINITY;
-
RIP_CFG->min_timeout_time = 60;
RIP_CFG->max_garbage_time = 60;
};
rip_proto_item:
proto_item
+ | proto_channel
| ECMP bool { RIP_CFG->ecmp = $2 ? RIP_DEFAULT_ECMP_LIMIT : 0; }
| ECMP bool LIMIT expr { RIP_CFG->ecmp = $2 ? $4 : 0; if ($4 < 0) cf_error("ECMP limit cannot be negative"); }
| INFINITY expr { RIP_CFG->infinity = $2; }
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 7e5d6802..f020bc5b 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -143,7 +143,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
if (rt)
{
/* Update */
- net *n = net_get(p->p.table, en->n.addr);
+ net *n = net_get(p->p.main_channel->table, en->n.addr);
rta a0 = {
.src = p->p.main_source,
@@ -212,7 +212,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
else
{
/* Withdraw */
- net *n = net_find(p->p.table, en->n.addr);
+ net *n = net_find(p->p.main_channel->table, en->n.addr);
rte_update(&p->p, n, NULL);
}
}
@@ -1027,19 +1027,17 @@ rip_import_control(struct proto *P, struct rte **rt, struct ea_list **attrs, str
return 0;
}
-static int
-rip_reload_routes(struct proto *P)
+static void
+rip_reload_routes(struct channel *C)
{
- struct rip_proto *p = (struct rip_proto *) P;
+ struct rip_proto *p = (struct rip_proto *) C->proto;
if (p->rt_reload)
- return 1;
+ return;
TRACE(D_EVENTS, "Scheduling route reload");
p->rt_reload = 1;
rip_kick_timer(p);
-
- return 1;
}
static struct ea_list *
@@ -1070,12 +1068,23 @@ rip_rte_same(struct rte *new, struct rte *old)
}
+static void
+rip_postconfig(struct proto_config *CF)
+{
+ // struct rip_config *cf = (void *) CF;
+
+ /* Define default channel */
+ if (EMPTY_LIST(CF->channels))
+ channel_config_new(NULL, CF->net_type, CF);
+}
+
static struct proto *
-rip_init(struct proto_config *cfg)
+rip_init(struct proto_config *CF)
{
- struct proto *P = proto_new(cfg, sizeof(struct rip_proto));
+ struct proto *P = proto_new(CF);
+
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- P->accept_ra_types = RA_OPTIMAL;
P->if_notify = rip_if_notify;
P->rt_notify = rip_rt_notify;
P->neigh_notify = rip_neigh_notify;
@@ -1115,10 +1124,10 @@ rip_start(struct proto *P)
}
static int
-rip_reconfigure(struct proto *P, struct proto_config *c)
+rip_reconfigure(struct proto *P, struct proto_config *CF)
{
struct rip_proto *p = (void *) P;
- struct rip_config *new = (void *) c;
+ struct rip_config *new = (void *) CF;
// struct rip_config *old = (void *) (P->cf);
if (new->rip2 != p->rip2)
@@ -1127,9 +1136,12 @@ rip_reconfigure(struct proto *P, struct proto_config *c)
if (new->infinity != p->infinity)
return 0;
+ if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
+ return 0;
+
TRACE(D_EVENTS, "Reconfiguring");
- p->p.cf = c;
+ p->p.cf = CF;
p->ecmp = new->ecmp;
rip_reconfigure_ifaces(p, new);
@@ -1270,7 +1282,10 @@ struct protocol proto_rip = {
.template = "rip%d",
.attr_class = EAP_RIP,
.preference = DEF_PREF_RIP,
+ .channel_mask = NB_IP,
+ .proto_size = sizeof(struct rip_proto),
.config_size = sizeof(struct rip_config),
+ .postconfig = rip_postconfig,
.init = rip_init,
.dump = rip_dump,
.start = rip_start,
diff --git a/proto/static/config.Y b/proto/static/config.Y
index 9e634803..86359f0b 100644
--- a/proto/static/config.Y
+++ b/proto/static/config.Y
@@ -38,15 +38,16 @@ CF_GRAMMAR
CF_ADDTO(proto, static_proto '}')
-static_proto_start: proto_start STATIC {
- this_proto = proto_config_new(&proto_static, $1);
- static_init_config((struct static_config *) this_proto);
- }
- ;
+static_proto_start: proto_start STATIC
+{
+ this_proto = proto_config_new(&proto_static, $1);
+ static_init_config(STATIC_CFG);
+};
static_proto:
static_proto_start proto_name '{'
| static_proto proto_item ';'
+ | static_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
| static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
| static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
diff --git a/proto/static/static.c b/proto/static/static.c
index 809c29fb..6239fccb 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -54,7 +54,7 @@ static inline rtable *
p_igp_table(struct proto *p)
{
struct static_config *cf = (void *) p->cf;
- return cf->igp_table ? cf->igp_table->table : p->table;
+ return cf->igp_table ? cf->igp_table->table : p->main_channel->table;
}
static void
@@ -108,11 +108,11 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
}
if (r->dest == RTDX_RECURSIVE)
- rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
+ rta_set_recursive_next_hop(p->main_channel->table, &a, p_igp_table(p), &r->via, &r->via);
/* We skip rta_lookup() here */
- n = net_get(p->table, r->net);
+ n = net_get(p->main_channel->table, r->net);
e = rte_get_temp(&a);
e->net = n;
e->pflags = 0;
@@ -136,7 +136,7 @@ static_remove(struct proto *p, struct static_route *r)
return;
DBG("Removing static route %N via %I\n", r->net, r->via);
- n = net_find(p->table, r->net);
+ n = net_find(p->main_channel->table, r->net);
rte_update(p, n, NULL);
r->installed = 0;
}
@@ -309,6 +309,17 @@ static_shutdown(struct proto *p)
r->installed = 0;
}
+ /* Handle failure during channel reconfigure */
+ /* FIXME: This should be handled in a better way */
+ cf = (void *) p->cf_new;
+ if (cf)
+ {
+ WALK_LIST(r, cf->iface_routes)
+ r->installed = 0;
+ WALK_LIST(r, cf->other_routes)
+ r->installed = 0;
+ }
+
return PS_DOWN;
}
@@ -450,16 +461,40 @@ static_init_config(struct static_config *c)
init_list(&c->other_routes);
}
+static void
+static_postconfig(struct proto_config *CF)
+{
+ struct static_config *cf = (void *) CF;
+ struct static_route *r;
+
+ if (EMPTY_LIST(CF->channels))
+ cf_error("Channel not specified");
+
+
+ WALK_LIST(r, cf->iface_routes)
+ if (r->net->type != CF->net_type)
+ cf_error("Route %N incompatible with channel type", r->net);
+
+ WALK_LIST(r, cf->other_routes)
+ if (r->net->type != CF->net_type)
+ cf_error("Route %N incompatible with channel type", r->net);
+}
+
+
static struct proto *
-static_init(struct proto_config *c)
+static_init(struct proto_config *CF)
{
- struct proto *p = proto_new(c, sizeof(struct proto));
+ struct proto *P = proto_new(CF);
+ // struct static_proto *p = (void *) P;
+ // struct static_config *cf = (void *) CF;
- p->neigh_notify = static_neigh_notify;
- p->if_notify = static_if_notify;
- p->rte_mergable = static_rte_mergable;
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- return p;
+ P->neigh_notify = static_neigh_notify;
+ P->if_notify = static_if_notify;
+ P->rte_mergable = static_rte_mergable;
+
+ return P;
}
static inline int
@@ -543,15 +578,18 @@ cf_igp_table(struct static_config *cf)
}
static int
-static_reconfigure(struct proto *p, struct proto_config *new)
+static_reconfigure(struct proto *p, struct proto_config *CF)
{
struct static_config *o = (void *) p->cf;
- struct static_config *n = (void *) new;
+ struct static_config *n = (void *) CF;
struct static_route *r;
if (cf_igp_table(o) != cf_igp_table(n))
return 0;
+ if (!proto_configure_channel(p, &p->main_channel, proto_cf_main_channel(CF)))
+ return 0;
+
/* Delete all obsolete routes and reset neighbor entries */
WALK_LIST(r, o->iface_routes)
static_match(p, r, n);
@@ -617,20 +655,19 @@ 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 = {
.name = "Static",
.template = "static%d",
.preference = DEF_PREF_STATIC,
+ .channel_mask = NB_ANY,
+ .proto_size = sizeof(struct proto),
.config_size = sizeof(struct static_config),
+ .postconfig = static_postconfig,
.init = static_init,
.dump = static_dump,
.start = static_start,