diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/bfd/bfd.c | 3 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 1 | ||||
-rw-r--r-- | proto/bgp/config.Y | 6 | ||||
-rw-r--r-- | proto/ospf/config.Y | 25 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 37 | ||||
-rw-r--r-- | proto/ospf/rt.c | 5 | ||||
-rw-r--r-- | proto/pipe/config.Y | 25 | ||||
-rw-r--r-- | proto/pipe/pipe.c | 238 | ||||
-rw-r--r-- | proto/pipe/pipe.h | 16 | ||||
-rw-r--r-- | proto/radv/config.Y | 7 | ||||
-rw-r--r-- | proto/radv/radv.c | 48 | ||||
-rw-r--r-- | proto/radv/radv.h | 3 | ||||
-rw-r--r-- | proto/rip/config.Y | 5 | ||||
-rw-r--r-- | proto/rip/rip.c | 43 | ||||
-rw-r--r-- | proto/static/config.Y | 11 | ||||
-rw-r--r-- | proto/static/static.c | 69 |
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, |