Babel: Fix handling of seqno requests
Old behavior has several deficiencies compared to standard behavior (no triggered updates for replies, no retransmissions, ...).
This commit is contained in:
parent
672fb78e12
commit
dbf1ed263c
2 changed files with 189 additions and 144 deletions
|
@ -48,19 +48,20 @@
|
||||||
static inline int ge_mod64k(uint a, uint b)
|
static inline int ge_mod64k(uint a, uint b)
|
||||||
{ return (u16)(a - b) < 0x8000; }
|
{ return (u16)(a - b) < 0x8000; }
|
||||||
|
|
||||||
static void babel_dump_entry(struct babel_entry *e);
|
static void babel_expire_requests(struct babel_proto *p, struct babel_entry *e);
|
||||||
static void babel_dump_route(struct babel_route *r);
|
|
||||||
static void babel_select_route(struct babel_proto *p, struct babel_entry *e);
|
static void babel_select_route(struct babel_proto *p, struct babel_entry *e);
|
||||||
static void babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n);
|
static void babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n);
|
||||||
static void babel_send_wildcard_request(struct babel_iface *ifa);
|
static void babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr);
|
||||||
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_proto *p, struct babel_entry *e);
|
|
||||||
static void babel_update_cost(struct babel_neighbor *n);
|
static void babel_update_cost(struct babel_neighbor *n);
|
||||||
static inline void babel_kick_timer(struct babel_proto *p);
|
static inline void babel_kick_timer(struct babel_proto *p);
|
||||||
static inline void babel_iface_kick_timer(struct babel_iface *ifa);
|
static inline void babel_iface_kick_timer(struct babel_iface *ifa);
|
||||||
|
|
||||||
|
static inline void babel_lock_neighbor(struct babel_neighbor *nbr)
|
||||||
|
{ if (nbr) nbr->uc++; }
|
||||||
|
|
||||||
|
static inline void babel_unlock_neighbor(struct babel_neighbor *nbr)
|
||||||
|
{ if (nbr && !--nbr->uc) mb_free(nbr); }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions to maintain data structures
|
* Functions to maintain data structures
|
||||||
|
@ -72,6 +73,7 @@ babel_init_entry(void *E)
|
||||||
struct babel_entry *e = E;
|
struct babel_entry *e = E;
|
||||||
|
|
||||||
e->updated = current_time();
|
e->updated = current_time();
|
||||||
|
init_list(&e->requests);
|
||||||
init_list(&e->sources);
|
init_list(&e->sources);
|
||||||
init_list(&e->routes);
|
init_list(&e->routes);
|
||||||
}
|
}
|
||||||
|
@ -260,9 +262,10 @@ loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
babel_expire_sources(p, e);
|
babel_expire_sources(p, e);
|
||||||
|
babel_expire_requests(p, e);
|
||||||
|
|
||||||
/* Remove empty entries */
|
/* Remove empty entries */
|
||||||
if (EMPTY_LIST(e->sources) && EMPTY_LIST(e->routes))
|
if (EMPTY_LIST(e->sources) && EMPTY_LIST(e->routes) && EMPTY_LIST(e->requests))
|
||||||
{
|
{
|
||||||
FIB_ITERATE_PUT(&fit);
|
FIB_ITERATE_PUT(&fit);
|
||||||
fib_delete(rtable, e);
|
fib_delete(rtable, e);
|
||||||
|
@ -279,6 +282,110 @@ babel_expire_routes(struct babel_proto *p)
|
||||||
babel_expire_routes_(p, &p->ip6_rtable);
|
babel_expire_routes_(p, &p->ip6_rtable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int seqno_request_valid(struct babel_seqno_request *sr)
|
||||||
|
{ return !sr->nbr || sr->nbr->ifa; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add seqno request to the table of pending requests (RFC 6216 3.2.6) and send
|
||||||
|
* it to network. Do nothing if it is already in the table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
||||||
|
u64 router_id, u16 seqno, u8 hop_count,
|
||||||
|
struct babel_neighbor *nbr)
|
||||||
|
{
|
||||||
|
struct babel_seqno_request *sr;
|
||||||
|
|
||||||
|
WALK_LIST(sr, e->requests)
|
||||||
|
if (sr->router_id == router_id)
|
||||||
|
{
|
||||||
|
/* Found matching or newer */
|
||||||
|
if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Found older */
|
||||||
|
babel_unlock_neighbor(sr->nbr);
|
||||||
|
rem_node(NODE sr);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No entries found */
|
||||||
|
sr = sl_alloc(p->seqno_slab);
|
||||||
|
|
||||||
|
found:
|
||||||
|
sr->router_id = router_id;
|
||||||
|
sr->seqno = seqno;
|
||||||
|
sr->hop_count = hop_count;
|
||||||
|
sr->count = 0;
|
||||||
|
sr->expires = current_time() + BABEL_SEQNO_REQUEST_EXPIRY;
|
||||||
|
babel_lock_neighbor(sr->nbr = nbr);
|
||||||
|
add_tail(&e->requests, NODE sr);
|
||||||
|
|
||||||
|
babel_send_seqno_request(p, e, sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
babel_remove_seqno_request(struct babel_proto *p, struct babel_seqno_request *sr)
|
||||||
|
{
|
||||||
|
babel_unlock_neighbor(sr->nbr);
|
||||||
|
rem_node(NODE sr);
|
||||||
|
sl_free(p->seqno_slab, sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
||||||
|
u64 router_id, u16 seqno)
|
||||||
|
{
|
||||||
|
struct babel_seqno_request *sr;
|
||||||
|
|
||||||
|
WALK_LIST(sr, e->requests)
|
||||||
|
if ((sr->router_id == router_id) && ge_mod64k(seqno, sr->seqno))
|
||||||
|
{
|
||||||
|
/* Found the request, remove it */
|
||||||
|
babel_remove_seqno_request(p, sr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
babel_expire_requests(struct babel_proto *p, struct babel_entry *e)
|
||||||
|
{
|
||||||
|
struct babel_seqno_request *sr, *srx;
|
||||||
|
btime now_ = current_time();
|
||||||
|
|
||||||
|
WALK_LIST_DELSAFE(sr, srx, e->requests)
|
||||||
|
{
|
||||||
|
/* Remove seqno requests sent to dead neighbors */
|
||||||
|
if (!seqno_request_valid(sr))
|
||||||
|
{
|
||||||
|
babel_remove_seqno_request(p, sr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle expired requests - resend or remove */
|
||||||
|
if (sr->expires && sr->expires <= now_)
|
||||||
|
{
|
||||||
|
if (sr->count < BABEL_SEQNO_REQUEST_RETRY)
|
||||||
|
{
|
||||||
|
sr->count++;
|
||||||
|
sr->expires += (BABEL_SEQNO_REQUEST_EXPIRY << sr->count);
|
||||||
|
babel_send_seqno_request(p, e, sr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE(D_EVENTS, "Seqno request for %N router-id %lR expired",
|
||||||
|
e->n.addr, sr->router_id);
|
||||||
|
|
||||||
|
babel_remove_seqno_request(p, sr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct babel_neighbor *
|
static struct babel_neighbor *
|
||||||
babel_find_neighbor(struct babel_iface *ifa, ip_addr addr)
|
babel_find_neighbor(struct babel_iface *ifa, ip_addr addr)
|
||||||
{
|
{
|
||||||
|
@ -309,6 +416,7 @@ babel_get_neighbor(struct babel_iface *ifa, ip_addr addr)
|
||||||
nbr->txcost = BABEL_INFINITY;
|
nbr->txcost = BABEL_INFINITY;
|
||||||
nbr->cost = BABEL_INFINITY;
|
nbr->cost = BABEL_INFINITY;
|
||||||
init_list(&nbr->routes);
|
init_list(&nbr->routes);
|
||||||
|
babel_lock_neighbor(nbr);
|
||||||
add_tail(&ifa->neigh_list, NODE nbr);
|
add_tail(&ifa->neigh_list, NODE nbr);
|
||||||
|
|
||||||
return nbr;
|
return nbr;
|
||||||
|
@ -333,8 +441,9 @@ babel_flush_neighbor(struct babel_proto *p, struct babel_neighbor *nbr)
|
||||||
babel_select_route(p, e);
|
babel_select_route(p, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nbr->ifa = NULL;
|
||||||
rem_node(NODE nbr);
|
rem_node(NODE nbr);
|
||||||
mb_free(nbr);
|
babel_unlock_neighbor(nbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -588,14 +697,14 @@ babel_select_route(struct babel_proto *p, struct babel_entry *e)
|
||||||
(as unreachable), then send a seqno request.
|
(as unreachable), then send a seqno request.
|
||||||
|
|
||||||
babel_build_rte() will set the unreachable flag if the metric is BABEL_INFINITY.*/
|
babel_build_rte() will set the unreachable flag if the metric is BABEL_INFINITY.*/
|
||||||
if (e->selected_in)
|
if (best)
|
||||||
{
|
{
|
||||||
TRACE(D_EVENTS, "Lost feasible route for prefix %N", e->n.addr);
|
TRACE(D_EVENTS, "Lost feasible route for prefix %N", e->n.addr);
|
||||||
|
|
||||||
e->selected_in->metric = e->selected_in->advert_metric = BABEL_INFINITY;
|
best->metric = best->advert_metric = BABEL_INFINITY;
|
||||||
e->updated = current_time();
|
e->updated = current_time();
|
||||||
|
|
||||||
babel_send_seqno_request(p, e);
|
babel_add_seqno_request(p, e, best->router_id, best->seqno + 1, 0, NULL);
|
||||||
babel_announce_rte(p, e);
|
babel_announce_rte(p, e);
|
||||||
|
|
||||||
/* Section 3.6 of the RFC forbids an infeasible from being selected. This
|
/* Section 3.6 of the RFC forbids an infeasible from being selected. This
|
||||||
|
@ -695,7 +804,6 @@ babel_send_hello(struct babel_iface *ifa)
|
||||||
static void
|
static void
|
||||||
babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n)
|
babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n)
|
||||||
{
|
{
|
||||||
struct babel_iface *ifa = n->ifa;
|
|
||||||
union babel_msg msg = {};
|
union babel_msg msg = {};
|
||||||
|
|
||||||
TRACE(D_PACKETS, "Sending route request for %N to %I",
|
TRACE(D_PACKETS, "Sending route request for %N to %I",
|
||||||
|
@ -704,7 +812,7 @@ babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct ba
|
||||||
msg.type = BABEL_TLV_ROUTE_REQUEST;
|
msg.type = BABEL_TLV_ROUTE_REQUEST;
|
||||||
net_copy(&msg.route_request.net, e->n.addr);
|
net_copy(&msg.route_request.net, e->n.addr);
|
||||||
|
|
||||||
babel_send_unicast(&msg, ifa, n->addr);
|
babel_send_unicast(&msg, n->ifa, n->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -723,48 +831,32 @@ babel_send_wildcard_request(struct babel_iface *ifa)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e)
|
babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr)
|
||||||
{
|
|
||||||
struct babel_route *r = e->selected_in;
|
|
||||||
struct babel_iface *ifa = NULL;
|
|
||||||
struct babel_source *s = NULL;
|
|
||||||
union babel_msg msg = {};
|
|
||||||
|
|
||||||
s = babel_find_source(e, r->router_id);
|
|
||||||
if (!s || !babel_cache_seqno_request(p, e->n.addr, r->router_id, s->seqno + 1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
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.hop_count = BABEL_INITIAL_HOP_COUNT;
|
|
||||||
msg.seqno_request.seqno = s->seqno + 1;
|
|
||||||
msg.seqno_request.router_id = r->router_id;
|
|
||||||
net_copy(&msg.seqno_request.net, e->n.addr);
|
|
||||||
|
|
||||||
WALK_LIST(ifa, p->interfaces)
|
|
||||||
babel_enqueue(&msg, ifa);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
babel_unicast_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_source *s, struct babel_neighbor *nbr)
|
|
||||||
{
|
{
|
||||||
union babel_msg msg = {};
|
union babel_msg msg = {};
|
||||||
|
|
||||||
if (!s || !babel_cache_seqno_request(p, e->n.addr, s->router_id, s->seqno + 1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d",
|
|
||||||
e->n.addr, s->router_id, s->seqno + 1);
|
|
||||||
|
|
||||||
msg.type = BABEL_TLV_SEQNO_REQUEST;
|
msg.type = BABEL_TLV_SEQNO_REQUEST;
|
||||||
msg.seqno_request.hop_count = BABEL_INITIAL_HOP_COUNT;
|
msg.seqno_request.hop_count = sr->hop_count ?: BABEL_INITIAL_HOP_COUNT;
|
||||||
msg.seqno_request.seqno = s->seqno + 1;
|
msg.seqno_request.seqno = sr->seqno;
|
||||||
msg.seqno_request.router_id = s->router_id;
|
msg.seqno_request.router_id = sr->router_id;
|
||||||
net_copy(&msg.seqno_request.net, e->n.addr);
|
net_copy(&msg.seqno_request.net, e->n.addr);
|
||||||
|
|
||||||
babel_send_unicast(&msg, nbr->ifa, nbr->addr);
|
if (sr->nbr)
|
||||||
|
{
|
||||||
|
TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d to %I on %s",
|
||||||
|
e->n.addr, sr->router_id, sr->seqno, sr->nbr->addr, sr->nbr->ifa->ifname);
|
||||||
|
|
||||||
|
babel_send_unicast(&msg, sr->nbr->ifa, sr->nbr->addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE(D_PACKETS, "Sending broadcast seqno request for %N router-id %lR seqno %d",
|
||||||
|
e->n.addr, sr->router_id, sr->seqno);
|
||||||
|
|
||||||
|
struct babel_iface *ifa;
|
||||||
|
WALK_LIST(ifa, p->interfaces)
|
||||||
|
babel_enqueue(&msg, ifa);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -966,81 +1058,6 @@ babel_update_hello_history(struct babel_neighbor *n, u16 seqno, uint interval)
|
||||||
n->last_hello_int = interval;
|
n->last_hello_int = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
babel_expire_seqno_requests(struct babel_proto *p)
|
|
||||||
{
|
|
||||||
btime now_ = current_time();
|
|
||||||
|
|
||||||
struct babel_seqno_request *n, *nx;
|
|
||||||
WALK_LIST_DELSAFE(n, nx, p->seqno_cache)
|
|
||||||
{
|
|
||||||
if ((n->updated + BABEL_SEQNO_REQUEST_EXPIRY) <= now_)
|
|
||||||
{
|
|
||||||
rem_node(NODE n);
|
|
||||||
sl_free(p->seqno_slab, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks the seqno request cache for a matching request and returns failure if
|
|
||||||
* found. Otherwise, a new entry is stored in the cache.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
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 (net_equal(&r->net, n) && (r->router_id == router_id) && (r->seqno == seqno))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no entries found */
|
|
||||||
r = sl_alloc(p->seqno_slab);
|
|
||||||
net_copy(&r->net, n);
|
|
||||||
r->router_id = router_id;
|
|
||||||
r->seqno = seqno;
|
|
||||||
r->updated = current_time();
|
|
||||||
add_tail(&p->seqno_cache, NODE r);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
babel_forward_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
|
||||||
struct babel_msg_seqno_request *in,
|
|
||||||
ip_addr sender)
|
|
||||||
{
|
|
||||||
struct babel_route *r;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if ((r->router_id == in->router_id) &&
|
|
||||||
!OUR_ROUTE(r) &&
|
|
||||||
!ipa_equal(r->neigh->addr, sender))
|
|
||||||
{
|
|
||||||
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.hop_count = in->hop_count-1;
|
|
||||||
msg.seqno_request.seqno = in->seqno;
|
|
||||||
msg.seqno_request.router_id = in->router_id;
|
|
||||||
net_copy(&msg.seqno_request.net, e->n.addr);
|
|
||||||
|
|
||||||
babel_send_unicast(&msg, r->neigh->ifa, r->neigh->addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TLV handlers
|
* TLV handlers
|
||||||
|
@ -1227,7 +1244,7 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
|
||||||
/* RFC section 3.8.2.2 - Dealing with unfeasible updates */
|
/* RFC section 3.8.2.2 - Dealing with unfeasible updates */
|
||||||
if (!feasible && (metric != BABEL_INFINITY) &&
|
if (!feasible && (metric != BABEL_INFINITY) &&
|
||||||
(!best || (r == best) || (metric < best->metric)))
|
(!best || (r == best) || (metric < best->metric)))
|
||||||
babel_unicast_seqno_request(p, e, s, nbr);
|
babel_add_seqno_request(p, e, s->router_id, s->seqno + 1, 0, nbr);
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
{
|
{
|
||||||
|
@ -1264,6 +1281,13 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
|
||||||
r->expires = current_time() + r->expiry_interval;
|
r->expires = current_time() + r->expiry_interval;
|
||||||
if (r->expiry_interval > BABEL_ROUTE_REFRESH_INTERVAL)
|
if (r->expiry_interval > BABEL_ROUTE_REFRESH_INTERVAL)
|
||||||
r->refresh_time = current_time() + r->expiry_interval - BABEL_ROUTE_REFRESH_INTERVAL;
|
r->refresh_time = current_time() + r->expiry_interval - BABEL_ROUTE_REFRESH_INTERVAL;
|
||||||
|
|
||||||
|
/* If received update satisfies seqno request, we send triggered updates */
|
||||||
|
if (babel_satisfy_seqno_request(p, e, msg->router_id, msg->seqno))
|
||||||
|
{
|
||||||
|
babel_trigger_update(p);
|
||||||
|
e->updated = current_time();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
babel_select_route(p, e);
|
babel_select_route(p, e);
|
||||||
|
@ -1301,7 +1325,6 @@ babel_handle_route_request(union babel_msg *m, struct babel_iface *ifa)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa)
|
babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa)
|
||||||
{
|
{
|
||||||
|
@ -1335,11 +1358,31 @@ babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa)
|
||||||
p->update_seqno_inc = 1;
|
p->update_seqno_inc = 1;
|
||||||
babel_trigger_update(p);
|
babel_trigger_update(p);
|
||||||
}
|
}
|
||||||
else
|
else if (msg->hop_count > 1)
|
||||||
{
|
{
|
||||||
/* Not ours; forward if TTL allows it */
|
/* Not ours; forward if TTL allows it */
|
||||||
if (msg->hop_count > 1)
|
|
||||||
babel_forward_seqno_request(p, e, msg, msg->sender);
|
/* Find best admissible route */
|
||||||
|
struct babel_route *r, *best1 = NULL, *best2 = NULL;
|
||||||
|
WALK_LIST(r, e->routes)
|
||||||
|
if ((r->router_id == msg->router_id) && r->neigh && !ipa_equal(r->neigh->addr, msg->sender))
|
||||||
|
{
|
||||||
|
/* Find best feasible route */
|
||||||
|
if (babel_is_feasible(babel_find_source(e, r->router_id), r->seqno, r->advert_metric) &&
|
||||||
|
(!best1 || r->metric < best1->metric))
|
||||||
|
best1 = r;
|
||||||
|
|
||||||
|
/* Find best not necessary feasible route */
|
||||||
|
if (!best2 || r->metric < best2->metric)
|
||||||
|
best2 = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no route is found, do nothing */
|
||||||
|
r = best1 ?: best2;
|
||||||
|
if (!r)
|
||||||
|
return;
|
||||||
|
|
||||||
|
babel_add_seqno_request(p, e, msg->router_id, msg->seqno, msg->hop_count-1, r->neigh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1396,7 +1439,7 @@ babel_iface_timer(timer *t)
|
||||||
{
|
{
|
||||||
TRACE(D_EVENTS, "Sending triggered updates on %s", ifa->ifname);
|
TRACE(D_EVENTS, "Sending triggered updates on %s", ifa->ifname);
|
||||||
babel_send_update(ifa, ifa->want_triggered);
|
babel_send_update(ifa, ifa->want_triggered);
|
||||||
ifa->next_triggered = now_ + MIN(5 S, update_period / 2);
|
ifa->next_triggered = now_ + MIN(1 S, update_period / 2);
|
||||||
ifa->want_triggered = 0;
|
ifa->want_triggered = 0;
|
||||||
p->triggered = 0;
|
p->triggered = 0;
|
||||||
}
|
}
|
||||||
|
@ -1422,7 +1465,7 @@ babel_iface_start(struct babel_iface *ifa)
|
||||||
|
|
||||||
ifa->next_hello = current_time() + (random() % ifa->cf->hello_interval);
|
ifa->next_hello = current_time() + (random() % ifa->cf->hello_interval);
|
||||||
ifa->next_regular = current_time() + (random() % ifa->cf->update_interval);
|
ifa->next_regular = current_time() + (random() % ifa->cf->update_interval);
|
||||||
ifa->next_triggered = current_time() + MIN(5 S, ifa->cf->update_interval / 2);
|
ifa->next_triggered = current_time() + MIN(1 S, ifa->cf->update_interval / 2);
|
||||||
ifa->want_triggered = 0; /* We send an immediate update (below) */
|
ifa->want_triggered = 0; /* We send an immediate update (below) */
|
||||||
tm2_start(ifa->timer, 100 MS);
|
tm2_start(ifa->timer, 100 MS);
|
||||||
ifa->up = 1;
|
ifa->up = 1;
|
||||||
|
@ -1988,7 +2031,6 @@ babel_timer(timer *t)
|
||||||
struct babel_proto *p = t->data;
|
struct babel_proto *p = t->data;
|
||||||
|
|
||||||
babel_expire_routes(p);
|
babel_expire_routes(p);
|
||||||
babel_expire_seqno_requests(p);
|
|
||||||
babel_expire_neighbors(p);
|
babel_expire_neighbors(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2177,7 +2219,6 @@ babel_start(struct proto *P)
|
||||||
p->source_slab = sl_new(P->pool, sizeof(struct babel_source));
|
p->source_slab = sl_new(P->pool, sizeof(struct babel_source));
|
||||||
p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node));
|
p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node));
|
||||||
p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request));
|
p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request));
|
||||||
init_list(&p->seqno_cache);
|
|
||||||
|
|
||||||
p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
|
p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@
|
||||||
#define BABEL_ROUTE_EXPIRY_FACTOR(X) ((btime)(X)*7/2) /* 3.5 */
|
#define BABEL_ROUTE_EXPIRY_FACTOR(X) ((btime)(X)*7/2) /* 3.5 */
|
||||||
#define BABEL_ROUTE_REFRESH_INTERVAL (2 S_) /* Time before route expiry to send route request */
|
#define BABEL_ROUTE_REFRESH_INTERVAL (2 S_) /* Time before route expiry to send route request */
|
||||||
#define BABEL_HOLD_TIME (10 S_) /* Expiry time for our own routes */
|
#define BABEL_HOLD_TIME (10 S_) /* Expiry time for our own routes */
|
||||||
#define BABEL_SEQNO_REQUEST_EXPIRY (60 S_)
|
#define BABEL_SEQNO_REQUEST_RETRY 4
|
||||||
|
#define BABEL_SEQNO_REQUEST_EXPIRY (2 S_)
|
||||||
#define BABEL_GARBAGE_INTERVAL (300 S_)
|
#define BABEL_GARBAGE_INTERVAL (300 S_)
|
||||||
#define BABEL_RXCOST_WIRED 96
|
#define BABEL_RXCOST_WIRED 96
|
||||||
#define BABEL_RXCOST_WIRELESS 256
|
#define BABEL_RXCOST_WIRELESS 256
|
||||||
|
@ -147,9 +148,7 @@ struct babel_proto {
|
||||||
slab *route_slab;
|
slab *route_slab;
|
||||||
slab *source_slab;
|
slab *source_slab;
|
||||||
slab *msg_slab;
|
slab *msg_slab;
|
||||||
|
|
||||||
slab *seqno_slab;
|
slab *seqno_slab;
|
||||||
list seqno_cache; /* Seqno requests in the cache (struct babel_seqno_request) */
|
|
||||||
|
|
||||||
struct tbf log_pkt_tbf; /* TBF for packet messages */
|
struct tbf log_pkt_tbf; /* TBF for packet messages */
|
||||||
};
|
};
|
||||||
|
@ -190,6 +189,7 @@ struct babel_neighbor {
|
||||||
struct babel_iface *ifa;
|
struct babel_iface *ifa;
|
||||||
|
|
||||||
ip_addr addr;
|
ip_addr addr;
|
||||||
|
uint uc; /* Reference counter for seqno requests */
|
||||||
u16 rxcost; /* Sent in last IHU */
|
u16 rxcost; /* Sent in last IHU */
|
||||||
u16 txcost; /* Received in last IHU */
|
u16 txcost; /* Received in last IHU */
|
||||||
u16 cost; /* Computed neighbor cost */
|
u16 cost; /* Computed neighbor cost */
|
||||||
|
@ -231,12 +231,23 @@ struct babel_route {
|
||||||
btime expiry_interval;
|
btime expiry_interval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct babel_seqno_request {
|
||||||
|
node n;
|
||||||
|
u64 router_id;
|
||||||
|
u16 seqno;
|
||||||
|
u8 hop_count;
|
||||||
|
u8 count;
|
||||||
|
btime expires;
|
||||||
|
struct babel_neighbor *nbr;
|
||||||
|
};
|
||||||
|
|
||||||
struct babel_entry {
|
struct babel_entry {
|
||||||
struct babel_route *selected_in;
|
struct babel_route *selected_in;
|
||||||
struct babel_route *selected_out;
|
struct babel_route *selected_out;
|
||||||
|
|
||||||
btime updated;
|
btime updated;
|
||||||
|
|
||||||
|
list requests;
|
||||||
list sources; /* Source entries for this prefix (struct babel_source). */
|
list sources; /* Source entries for this prefix (struct babel_source). */
|
||||||
list routes; /* Routes for this prefix (struct babel_route) */
|
list routes; /* Routes for this prefix (struct babel_route) */
|
||||||
|
|
||||||
|
@ -244,13 +255,6 @@ struct babel_entry {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stores forwarded seqno requests for duplicate suppression. */
|
/* Stores forwarded seqno requests for duplicate suppression. */
|
||||||
struct babel_seqno_request {
|
|
||||||
node n;
|
|
||||||
net_addr net;
|
|
||||||
u64 router_id;
|
|
||||||
u16 seqno;
|
|
||||||
btime updated;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue