diff options
Diffstat (limited to 'proto/babel/babel.c')
-rw-r--r-- | proto/babel/babel.c | 334 |
1 files changed, 202 insertions, 132 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 38be6909..67a59df6 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -53,8 +53,7 @@ static void babel_dump_route(struct babel_route *r); static void babel_select_route(struct babel_entry *e); static void babel_send_route_request(struct babel_entry *e, struct babel_neighbor *n); static void babel_send_wildcard_request(struct babel_iface *ifa); -static int babel_cache_seqno_request(struct babel_proto *p, ip_addr prefix, u8 plen, - u64 router_id, u16 seqno); +static int babel_cache_seqno_request(struct babel_proto *p, net_addr *n, u64 router_id, u16 seqno); static void babel_trigger_iface_update(struct babel_iface *ifa); static void babel_trigger_update(struct babel_proto *p); static void babel_send_seqno_request(struct babel_entry *e); @@ -67,27 +66,27 @@ static inline void babel_iface_kick_timer(struct babel_iface *ifa); */ static void -babel_init_entry(struct fib_node *n) +babel_init_entry(void *E) { - struct babel_entry *e = (void *) n; - e->proto = NULL; - e->selected_in = NULL; - e->selected_out = NULL; + struct babel_entry *e = E; + e->updated = now; init_list(&e->sources); init_list(&e->routes); } static inline struct babel_entry * -babel_find_entry(struct babel_proto *p, ip_addr prefix, u8 plen) +babel_find_entry(struct babel_proto *p, const net_addr *n) { - return fib_find(&p->rtable, &prefix, plen); + struct fib *rtable = (n->type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable; + return fib_find(rtable, n); } static struct babel_entry * -babel_get_entry(struct babel_proto *p, ip_addr prefix, u8 plen) +babel_get_entry(struct babel_proto *p, const net_addr *n) { - struct babel_entry *e = fib_get(&p->rtable, &prefix, plen); + struct fib *rtable = (n->type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable; + struct babel_entry *e = fib_get(rtable, n); e->proto = p; return e; } @@ -180,8 +179,8 @@ babel_flush_route(struct babel_route *r) { struct babel_proto *p = r->e->proto; - DBG("Babel: Flush route %I/%d router_id %lR neigh %I\n", - r->e->n.prefix, r->e->n.pxlen, r->router_id, r->neigh ? r->neigh->addr : IPA_NONE); + DBG("Babel: Flush route %N router_id %lR neigh %I\n", + r->e->n.addr, r->router_id, r->neigh ? r->neigh->addr : IPA_NONE); rem_node(NODE r); @@ -203,8 +202,8 @@ babel_expire_route(struct babel_route *r) struct babel_proto *p = r->e->proto; struct babel_entry *e = r->e; - TRACE(D_EVENTS, "Route expiry timer for %I/%d router-id %lR fired", - e->n.prefix, e->n.pxlen, r->router_id); + TRACE(D_EVENTS, "Route expiry timer for %N router-id %lR fired", + e->n.addr, r->router_id); if (r->metric < BABEL_INFINITY) { @@ -227,18 +226,16 @@ babel_refresh_route(struct babel_route *r) } static void -babel_expire_routes(struct babel_proto *p) +babel_expire_routes_(struct babel_proto *p UNUSED, struct fib *rtable) { - struct babel_entry *e; struct babel_route *r, *rx; struct fib_iterator fit; - FIB_ITERATE_INIT(&fit, &p->rtable); + FIB_ITERATE_INIT(&fit, rtable); loop: - FIB_ITERATE_START(&p->rtable, &fit, n) + FIB_ITERATE_START(rtable, &fit, struct babel_entry, e) { - e = (struct babel_entry *) n; int changed = 0; WALK_LIST_DELSAFE(r, rx, e->routes) @@ -258,10 +255,10 @@ loop: /* * We have to restart the iteration because there may be a cascade of * synchronous events babel_select_route() -> nest table change -> - * babel_rt_notify() -> p->rtable change, invalidating hidden variables. + * babel_rt_notify() -> rtable change, invalidating hidden variables. */ - FIB_ITERATE_PUT(&fit, n); + FIB_ITERATE_PUT(&fit); babel_select_route(e); goto loop; } @@ -271,12 +268,19 @@ loop: /* Remove empty entries */ if (EMPTY_LIST(e->sources) && EMPTY_LIST(e->routes)) { - FIB_ITERATE_PUT(&fit, n); - fib_delete(&p->rtable, e); + FIB_ITERATE_PUT(&fit); + fib_delete(rtable, e); goto loop; } } - FIB_ITERATE_END(n); + FIB_ITERATE_END; +} + +static void +babel_expire_routes(struct babel_proto *p) +{ + babel_expire_routes_(p, &p->ip4_rtable); + babel_expire_routes_(p, &p->ip6_rtable); } static struct babel_neighbor * @@ -473,38 +477,35 @@ static void babel_announce_rte(struct babel_proto *p, struct babel_entry *e) { struct babel_route *r = e->selected_in; + struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel; if (r) { - net *n = net_get(p->p.table, e->n.prefix, e->n.pxlen); - rta A = { + rta *ap0 = allocz(RTA_MAX_SIZE); + *ap0 = (rta) { .src = p->p.main_source, .source = RTS_BABEL, .scope = SCOPE_UNIVERSE, - .cast = RTC_UNICAST, - .dest = r->metric == BABEL_INFINITY ? RTD_UNREACHABLE : RTD_ROUTER, - .flags = 0, + .dest = r->metric == BABEL_INFINITY ? RTD_UNREACHABLE : RTD_UNICAST, .from = r->neigh->addr, - .iface = r->neigh->ifa->iface, + .nh.iface = r->neigh->ifa->iface, }; if (r->metric < BABEL_INFINITY) - A.gw = r->next_hop; + ap0->nh.gw = r->next_hop; - rta *a = rta_lookup(&A); + rta *a = rta_lookup(ap0); rte *rte = rte_get_temp(a); rte->u.babel.metric = r->metric; rte->u.babel.router_id = r->router_id; - rte->net = n; rte->pflags = 0; - rte_update(&p->p, n, rte); + rte_update2(c, e->n.addr, rte, p->p.main_source); } else { /* Retraction */ - net *n = net_find(p->p.table, e->n.prefix, e->n.pxlen); - rte_update(&p->p, n, NULL); + rte_update2(c, e->n.addr, NULL, p->p.main_source); } } @@ -541,8 +542,8 @@ babel_select_route(struct babel_entry *e) ((!e->selected_in && cur->metric < BABEL_INFINITY) || (e->selected_in && cur->metric < e->selected_in->metric))) { - TRACE(D_EVENTS, "Picked new route for prefix %I/%d: router id %lR metric %d", - e->n.prefix, e->n.pxlen, cur->router_id, cur->metric); + TRACE(D_EVENTS, "Picked new route for prefix %N: router id %lR metric %d", + e->n.addr, cur->router_id, cur->metric); e->selected_in = cur; e->updated = now; @@ -557,8 +558,8 @@ babel_select_route(struct babel_entry *e) babel_build_rte() will set the unreachable flag if the metric is BABEL_INFINITY.*/ if (e->selected_in) { - TRACE(D_EVENTS, "Lost feasible route for prefix %I/%d", - e->n.prefix, e->n.pxlen); + TRACE(D_EVENTS, "Lost feasible route for prefix %N", + e->n.addr); e->selected_in->metric = BABEL_INFINITY; e->updated = now; @@ -576,7 +577,7 @@ babel_select_route(struct babel_entry *e) /* No route currently selected, and no new one selected; this means we don't have a route to this destination anymore (and were probably called from an expiry timer). Remove the route from the nest. */ - TRACE(D_EVENTS, "Flushing route for prefix %I/%d", e->n.prefix, e->n.pxlen); + TRACE(D_EVENTS, "Flushing route for prefix %N", e->n.addr); e->selected_in = NULL; e->updated = now; @@ -663,12 +664,11 @@ babel_send_route_request(struct babel_entry *e, struct babel_neighbor *n) struct babel_iface *ifa = n->ifa; union babel_msg msg = {}; - TRACE(D_PACKETS, "Sending route request for %I/%d to %I", - e->n.prefix, e->n.pxlen, n->addr); + TRACE(D_PACKETS, "Sending route request for %N to %I", + e->n.addr, n->addr); msg.type = BABEL_TLV_ROUTE_REQUEST; - msg.route_request.prefix = e->n.prefix; - msg.route_request.plen = e->n.pxlen; + net_copy(&msg.route_request.net, e->n.addr); babel_send_unicast(&msg, ifa, n->addr); } @@ -698,18 +698,17 @@ babel_send_seqno_request(struct babel_entry *e) union babel_msg msg = {}; s = babel_find_source(e, r->router_id); - if (!s || !babel_cache_seqno_request(p, e->n.prefix, e->n.pxlen, r->router_id, s->seqno + 1)) + if (!s || !babel_cache_seqno_request(p, e->n.addr, r->router_id, s->seqno + 1)) return; - TRACE(D_PACKETS, "Sending seqno request for %I/%d router-id %lR seqno %d", - e->n.prefix, e->n.pxlen, r->router_id, s->seqno + 1); + TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d", + e->n.addr, r->router_id, s->seqno + 1); msg.type = BABEL_TLV_SEQNO_REQUEST; - msg.seqno_request.plen = e->n.pxlen; - msg.seqno_request.seqno = s->seqno + 1; msg.seqno_request.hop_count = BABEL_INITIAL_HOP_COUNT; + msg.seqno_request.seqno = s->seqno + 1; msg.seqno_request.router_id = r->router_id; - msg.seqno_request.prefix = e->n.prefix; + net_copy(&msg.seqno_request.net, e->n.addr); WALK_LIST(ifa, p->interfaces) babel_enqueue(&msg, ifa); @@ -725,18 +724,17 @@ babel_unicast_seqno_request(struct babel_route *r) union babel_msg msg = {}; s = babel_find_source(e, r->router_id); - if (!s || !babel_cache_seqno_request(p, e->n.prefix, e->n.pxlen, r->router_id, s->seqno + 1)) + if (!s || !babel_cache_seqno_request(p, e->n.addr, r->router_id, s->seqno + 1)) return; - TRACE(D_PACKETS, "Sending seqno request for %I/%d router-id %lR seqno %d", - e->n.prefix, e->n.pxlen, r->router_id, s->seqno + 1); + TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d", + e->n.addr, r->router_id, s->seqno + 1); msg.type = BABEL_TLV_SEQNO_REQUEST; - msg.seqno_request.plen = e->n.pxlen; - msg.seqno_request.seqno = s->seqno + 1; msg.seqno_request.hop_count = BABEL_INITIAL_HOP_COUNT; + msg.seqno_request.seqno = s->seqno + 1; msg.seqno_request.router_id = r->router_id; - msg.seqno_request.prefix = e->n.prefix; + net_copy(&msg.seqno_request.net, e->n.addr); babel_send_unicast(&msg, ifa, r->neigh->addr); } @@ -752,13 +750,12 @@ babel_unicast_seqno_request(struct babel_route *r) * transmitted entry is updated. */ static void -babel_send_update(struct babel_iface *ifa, bird_clock_t changed) +babel_send_update_(struct babel_iface *ifa, bird_clock_t changed, struct fib *rtable) { struct babel_proto *p = ifa->proto; - FIB_WALK(&p->rtable, n) + FIB_WALK(rtable, struct babel_entry, e) { - struct babel_entry *e = (void *) n; struct babel_route *r = e->selected_out; if (!r) @@ -776,17 +773,19 @@ babel_send_update(struct babel_iface *ifa, bird_clock_t changed) if (e->updated < changed) continue; - TRACE(D_PACKETS, "Sending update for %I/%d router-id %lR seqno %d metric %d", - e->n.prefix, e->n.pxlen, r->router_id, r->seqno, r->metric); + TRACE(D_PACKETS, "Sending update for %N router-id %lR seqno %d metric %d", + e->n.addr, r->router_id, r->seqno, r->metric); union babel_msg msg = {}; msg.type = BABEL_TLV_UPDATE; - msg.update.plen = e->n.pxlen; msg.update.interval = ifa->cf->update_interval; msg.update.seqno = r->seqno; msg.update.metric = r->metric; - msg.update.prefix = e->n.prefix; msg.update.router_id = r->router_id; + net_copy(&msg.update.net, e->n.addr); + + msg.update.next_hop = ((e->n.addr->type == NET_IP4) ? + ifa->next_hop_ip4 : ifa->next_hop_ip6); babel_enqueue(&msg, ifa); @@ -808,6 +807,15 @@ babel_send_update(struct babel_iface *ifa, bird_clock_t changed) } static void +babel_send_update(struct babel_iface *ifa, bird_clock_t changed) +{ + struct babel_proto *p = ifa->proto; + + babel_send_update_(ifa, changed, &p->ip4_rtable); + babel_send_update_(ifa, changed, &p->ip6_rtable); +} + +static void babel_trigger_iface_update(struct babel_iface *ifa) { struct babel_proto *p = ifa->proto; @@ -839,20 +847,18 @@ babel_trigger_update(struct babel_proto *p) /* A retraction is an update with an infinite metric */ static void -babel_send_retraction(struct babel_iface *ifa, ip_addr prefix, int plen) +babel_send_retraction(struct babel_iface *ifa, net_addr *n) { struct babel_proto *p = ifa->proto; union babel_msg msg = {}; - TRACE(D_PACKETS, "Sending retraction for %I/%d seqno %d", - prefix, plen, p->update_seqno); + TRACE(D_PACKETS, "Sending retraction for %N seqno %d", n, p->update_seqno); msg.type = BABEL_TLV_UPDATE; - msg.update.plen = plen; msg.update.interval = ifa->cf->update_interval; msg.update.seqno = p->update_seqno; msg.update.metric = BABEL_INFINITY; - msg.update.prefix = prefix; + msg.update.net = *n; babel_enqueue(&msg, ifa); } @@ -941,22 +947,20 @@ babel_expire_seqno_requests(struct babel_proto *p) * found. Otherwise, a new entry is stored in the cache. */ static int -babel_cache_seqno_request(struct babel_proto *p, ip_addr prefix, u8 plen, +babel_cache_seqno_request(struct babel_proto *p, net_addr *n, u64 router_id, u16 seqno) { struct babel_seqno_request *r; WALK_LIST(r, p->seqno_cache) { - if (ipa_equal(r->prefix, prefix) && (r->plen == plen) && - (r->router_id == router_id) && (r->seqno == seqno)) + if (net_equal(&r->net, n) && (r->router_id == router_id) && (r->seqno == seqno)) return 0; } /* no entries found */ r = sl_alloc(p->seqno_slab); - r->prefix = prefix; - r->plen = plen; + net_copy(&r->net, n); r->router_id = router_id; r->seqno = seqno; r->updated = now; @@ -973,8 +977,8 @@ babel_forward_seqno_request(struct babel_entry *e, struct babel_proto *p = e->proto; struct babel_route *r; - TRACE(D_PACKETS, "Forwarding seqno request for %I/%d router-id %lR seqno %d", - e->n.prefix, e->n.pxlen, in->router_id, in->seqno); + TRACE(D_PACKETS, "Forwarding seqno request for %N router-id %lR seqno %d", + e->n.addr, in->router_id, in->seqno); WALK_LIST(r, e->routes) { @@ -982,16 +986,15 @@ babel_forward_seqno_request(struct babel_entry *e, !OUR_ROUTE(r) && !ipa_equal(r->neigh->addr, sender)) { - if (!babel_cache_seqno_request(p, e->n.prefix, e->n.pxlen, in->router_id, in->seqno)) + if (!babel_cache_seqno_request(p, e->n.addr, in->router_id, in->seqno)) return; union babel_msg msg = {}; msg.type = BABEL_TLV_SEQNO_REQUEST; - msg.seqno_request.plen = in->plen; - msg.seqno_request.seqno = in->seqno; msg.seqno_request.hop_count = in->hop_count-1; + msg.seqno_request.seqno = in->seqno; msg.seqno_request.router_id = in->router_id; - msg.seqno_request.prefix = e->n.prefix; + net_copy(&msg.seqno_request.net, e->n.addr); babel_send_unicast(&msg, r->neigh->ifa, r->neigh->addr); return; @@ -1073,8 +1076,11 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa) node *n; int feasible; - TRACE(D_PACKETS, "Handling update for %I/%d with seqno %d metric %d", - msg->prefix, msg->plen, msg->seqno, msg->metric); + if (msg->wildcard) + TRACE(D_PACKETS, "Handling wildcard retraction", msg->seqno); + else + TRACE(D_PACKETS, "Handling update for %N with seqno %d metric %d", + &msg->net, msg->seqno, msg->metric); nbr = babel_find_neighbor(ifa, msg->sender); if (!nbr) @@ -1089,6 +1095,13 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa) return; } + struct channel *c = (msg->net.type == NET_IP4) ? p->ip4_channel : p->ip6_channel; + if (!c || (c->channel_state != CS_UP)) + { + DBG("Babel: Ignoring update for inactive address family.\n"); + return; + } + /* * RFC section 3.5.4: * @@ -1140,7 +1153,7 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa) } else { - e = babel_find_entry(p, msg->prefix, msg->plen); + e = babel_find_entry(p, &msg->net); if (!e) return; @@ -1159,7 +1172,7 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa) return; } - e = babel_get_entry(p, msg->prefix, msg->plen); + e = babel_get_entry(p, &msg->net); r = babel_find_route(e, nbr); /* the route entry indexed by neighbour */ s = babel_find_source(e, msg->router_id); /* for feasibility */ feasible = babel_is_feasible(s, msg->seqno, msg->metric); @@ -1231,14 +1244,14 @@ babel_handle_route_request(union babel_msg *m, struct babel_iface *ifa) return; } - TRACE(D_PACKETS, "Handling route request for %I/%d", msg->prefix, msg->plen); + TRACE(D_PACKETS, "Handling route request for %N", &msg->net); /* Non-wildcard request - see if we have an entry for the route. If not, send a retraction, otherwise send an update. */ - struct babel_entry *e = babel_find_entry(p, msg->prefix, msg->plen); + struct babel_entry *e = babel_find_entry(p, &msg->net); if (!e) { - babel_send_retraction(ifa, msg->prefix, msg->plen); + babel_send_retraction(ifa, &msg->net); } else { @@ -1256,11 +1269,11 @@ babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa) /* RFC 6126 3.8.1.2 */ - TRACE(D_PACKETS, "Handling seqno request for %I/%d router-id %lR seqno %d hop count %d", - msg->prefix, msg->plen, msg->router_id, msg->seqno, msg->hop_count); + TRACE(D_PACKETS, "Handling seqno request for %N router-id %lR seqno %d hop count %d", + &msg->net, msg->router_id, msg->seqno, msg->hop_count); /* Ignore if we have no such entry or entry has infinite metric */ - struct babel_entry *e = babel_find_entry(p, msg->prefix, msg->plen); + struct babel_entry *e = babel_find_entry(p, &msg->net); if (!e || !e->selected_out || (e->selected_out->metric == BABEL_INFINITY)) return; @@ -1491,14 +1504,26 @@ babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_con add_tail(&p->interfaces, NODE ifa); + ip_addr addr4 = IPA_NONE; struct ifa *addr; WALK_LIST(addr, new->addrs) + { if (ipa_is_link_local(addr->ip)) ifa->addr = addr->ip; + if (ipa_zero(addr4) && ipa_is_ip4(addr->ip)) + addr4 = addr->ip; + } + + ifa->next_hop_ip4 = ipa_nonzero(ic->next_hop_ip4) ? ic->next_hop_ip4 : addr4; + ifa->next_hop_ip6 = ipa_nonzero(ic->next_hop_ip6) ? ic->next_hop_ip6 : ifa->addr; + if (ipa_zero(ifa->addr)) log(L_WARN "%s: Cannot find link-local addr on %s", p->p.name, new->name); + if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel) + log(L_WARN "%s: Cannot find IPv4 next hop addr on %s", p->p.name, new->name); + init_list(&ifa->neigh_list); ifa->hello_seqno = 1; @@ -1590,6 +1615,26 @@ babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct b ifa->cf = new; + if (ipa_nonzero(new->next_hop_ip4)) + ifa->next_hop_ip4 = new->next_hop_ip4; + else + { + ifa->next_hop_ip4 = IPA_NONE; + + struct ifa *addr; + WALK_LIST(addr, ifa->iface->addrs) + if (ipa_is_ip4(addr->ip)) + { + ifa->next_hop_ip4 = addr->ip; + break; + } + } + + ifa->next_hop_ip6 = ipa_nonzero(new->next_hop_ip6) ? new->next_hop_ip6 : ifa->addr; + + if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel) + log(L_WARN "%s: Cannot find IPv4 next hop addr on %s", p->p.name, ifa->ifname); + if (ifa->next_hello > (now + new->hello_interval)) ifa->next_hello = now + (random() % new->hello_interval) + 1; @@ -1668,7 +1713,7 @@ babel_dump_entry(struct babel_entry *e) struct babel_source *s; struct babel_route *r; - debug("Babel: Entry %I/%d:\n", e->n.prefix, e->n.pxlen); + debug("Babel: Entry %N:\n", e->n.addr); WALK_LIST(s,e->sources) { debug(" "); babel_dump_source(s); } @@ -1696,9 +1741,10 @@ babel_dump_iface(struct babel_iface *ifa) { struct babel_neighbor *n; - debug("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %d %d\n", + debug("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %d %d", ifa->ifname, ifa->addr, ifa->cf->rxcost, ifa->cf->type, ifa->hello_seqno, ifa->cf->hello_interval, ifa->cf->update_interval); + debug(" next hop v4 %I next hop v6 %I\n", ifa->next_hop_ip4, ifa->next_hop_ip6); WALK_LIST(n, ifa->neigh_list) { debug(" "); babel_dump_neighbor(n); } @@ -1715,9 +1761,14 @@ babel_dump(struct proto *P) WALK_LIST(ifa, p->interfaces) babel_dump_iface(ifa); - FIB_WALK(&p->rtable, n) + FIB_WALK(&p->ip4_rtable, struct babel_entry, e) { - babel_dump_entry((struct babel_entry *) n); + babel_dump_entry(e); + } + FIB_WALK_END; + FIB_WALK(&p->ip6_rtable, struct babel_entry, e) + { + babel_dump_entry(e); } FIB_WALK_END; } @@ -1765,8 +1816,9 @@ babel_show_interfaces(struct proto *P, char *iff) } cli_msg(-1023, "%s:", p->p.name); - cli_msg(-1023, "%-10s %-6s %7s %6s %6s", - "Interface", "State", "RX cost", "Nbrs", "Timer"); + cli_msg(-1023, "%-10s %-6s %7s %6s %6s %-15s %s", + "Interface", "State", "RX cost", "Nbrs", "Timer", + "Next hop (v4)", "Next hop (v6)"); WALK_LIST(ifa, p->interfaces) { @@ -1778,8 +1830,10 @@ babel_show_interfaces(struct proto *P, char *iff) nbrs++; int timer = MIN(ifa->next_regular, ifa->next_hello) - now; - cli_msg(-1023, "%-10s %-6s %7u %6u %6u", - ifa->iface->name, (ifa->up ? "Up" : "Down"), ifa->cf->rxcost, nbrs, MAX(timer, 0)); + cli_msg(-1023, "%-10s %-6s %7u %6u %6u %-15I %I", + ifa->iface->name, (ifa->up ? "Up" : "Down"), + ifa->cf->rxcost, nbrs, MAX(timer, 0), + ifa->next_hop_ip4, ifa->next_hop_ip6); } cli_msg(0, ""); @@ -1824,39 +1878,22 @@ babel_show_neighbors(struct proto *P, char *iff) cli_msg(0, ""); } -void -babel_show_entries(struct proto *P) +static void +babel_show_entries_(struct babel_proto *p, struct fib *rtable) { - struct babel_proto *p = (void *) P; - struct babel_entry *e = NULL; struct babel_source *s = NULL; struct babel_route *r = NULL; - char ipbuf[STD_ADDRESS_P_LENGTH+5]; char ridbuf[ROUTER_ID_64_LENGTH+1]; - if (p->p.proto_state != PS_UP) + FIB_WALK(rtable, struct babel_entry, e) { - cli_msg(-1025, "%s: is not up", p->p.name); - cli_msg(0, ""); - return; - } - - cli_msg(-1025, "%s:", p->p.name); - cli_msg(-1025, "%-29s %-23s %6s %5s %7s %7s", - "Prefix", "Router ID", "Metric", "Seqno", "Expires", "Sources"); - - FIB_WALK(&p->rtable, n) - { - e = (struct babel_entry *) n; r = e->selected_in ? e->selected_in : e->selected_out; int srcs = 0; WALK_LIST(s, e->sources) srcs++; - bsprintf(ipbuf, "%I/%u", e->n.prefix, e->n.pxlen); - if (r) { if (r->router_id == p->router_id) @@ -1865,15 +1902,35 @@ babel_show_entries(struct proto *P) bsprintf(ridbuf, "%lR", r->router_id); int time = r->expires ? r->expires - now : 0; - cli_msg(-1025, "%-29s %-23s %6u %5u %7u %7u", - ipbuf, ridbuf, r->metric, r->seqno, MAX(time, 0), srcs); + cli_msg(-1025, "%-29N %-23s %6u %5u %7u %7u", + e->n.addr, ridbuf, r->metric, r->seqno, MAX(time, 0), srcs); } else { - cli_msg(-1025, "%-29s %-44s %7u", ipbuf, "<pending>", srcs); + cli_msg(-1025, "%-29N %-44s %7u", e->n.addr, "<pending>", srcs); } } FIB_WALK_END; +} + +void +babel_show_entries(struct proto *P) +{ + struct babel_proto *p = (void *) P; + + if (p->p.proto_state != PS_UP) + { + cli_msg(-1025, "%s: is not up", p->p.name); + cli_msg(0, ""); + return; + } + + cli_msg(-1025, "%s:", p->p.name); + cli_msg(-1025, "%-29s %-23s %6s %5s %7s %7s", + "Prefix", "Router ID", "Metric", "Seqno", "Expires", "Sources"); + + babel_show_entries_(p, &p->ip4_rtable); + babel_show_entries_(p, &p->ip6_rtable); cli_msg(0, ""); } @@ -1964,7 +2021,7 @@ babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) * so store it into our data structures. */ static void -babel_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net, +babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, struct rte *new, struct rte *old UNUSED, struct ea_list *attrs UNUSED) { struct babel_proto *p = (void *) P; @@ -1974,7 +2031,7 @@ babel_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *ne if (new) { /* Update */ - e = babel_get_entry(p, net->n.prefix, net->n.pxlen); + e = babel_get_entry(p, net->n.addr); if (new->attrs->src->proto != P) { @@ -1996,7 +2053,7 @@ babel_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *ne else { /* Withdraw */ - e = babel_find_entry(p, net->n.prefix, net->n.pxlen); + e = babel_find_entry(p, net->n.addr); if (!e || !e->selected_out) return; @@ -2046,11 +2103,14 @@ babel_rte_same(struct rte *new, struct rte *old) static struct proto * -babel_init(struct proto_config *cfg) +babel_init(struct proto_config *CF) { - struct proto *P = proto_new(cfg, sizeof(struct babel_proto)); + struct proto *P = proto_new(CF); + struct babel_proto *p = (void *) P; + + proto_configure_channel(P, &p->ip4_channel, proto_cf_find_channel(CF, NET_IP4)); + proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6)); - P->accept_ra_types = RA_OPTIMAL; P->if_notify = babel_if_notify; P->rt_notify = babel_rt_notify; P->import_control = babel_import_control; @@ -2068,7 +2128,11 @@ babel_start(struct proto *P) struct babel_proto *p = (void *) P; struct babel_config *cf = (void *) P->cf; - fib_init(&p->rtable, P->pool, sizeof(struct babel_entry), 0, babel_init_entry); + fib_init(&p->ip4_rtable, P->pool, NET_IP4, sizeof(struct babel_entry), + OFFSETOF(struct babel_entry, n), 0, babel_init_entry); + fib_init(&p->ip6_rtable, P->pool, NET_IP6, sizeof(struct babel_entry), + OFFSETOF(struct babel_entry, n), 0, babel_init_entry); + init_list(&p->interfaces); p->timer = tm_new_set(P->pool, babel_timer, p, 0, 1); tm_start(p->timer, 2); @@ -2111,14 +2175,18 @@ babel_shutdown(struct proto *P) } static int -babel_reconfigure(struct proto *P, struct proto_config *c) +babel_reconfigure(struct proto *P, struct proto_config *CF) { struct babel_proto *p = (void *) P; - struct babel_config *new = (void *) c; + struct babel_config *new = (void *) CF; TRACE(D_EVENTS, "Reconfiguring"); - p->p.cf = c; + if (!proto_configure_channel(P, &p->ip4_channel, proto_cf_find_channel(CF, NET_IP4)) || + !proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6))) + return 0; + + p->p.cf = CF; babel_reconfigure_ifaces(p, new); babel_trigger_update(p); @@ -2133,6 +2201,8 @@ struct protocol proto_babel = { .template = "babel%d", .attr_class = EAP_BABEL, .preference = DEF_PREF_BABEL, + .channel_mask = NB_IP, + .proto_size = sizeof(struct babel_proto), .config_size = sizeof(struct babel_config), .init = babel_init, .dump = babel_dump, |