summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proto/babel/babel.c82
-rw-r--r--proto/babel/packets.c4
2 files changed, 61 insertions, 25 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 8e104d60..8204838b 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1040,17 +1040,18 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
struct babel_proto *p = ifa->proto;
struct babel_msg_update *msg = &m->update;
- struct babel_neighbor *n;
+ struct babel_neighbor *nbr;
struct babel_entry *e;
struct babel_source *s;
struct babel_route *r;
+ 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);
- n = babel_find_neighbor(ifa, msg->sender);
- if (!n)
+ nbr = babel_find_neighbor(ifa, msg->sender);
+ if (!nbr)
{
DBG("Babel: Haven't heard from neighbor %I; ignoring update.\n", msg->sender);
return;
@@ -1095,55 +1096,88 @@ babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
* of the Interval value included in the update.
*/
+ /* Retraction */
if (msg->metric == BABEL_INFINITY)
- e = babel_find_entry(p, msg->prefix, msg->plen);
- else
- e = babel_get_entry(p, msg->prefix, msg->plen);
+ {
+ if (msg->ae == BABEL_AE_WILDCARD)
+ {
+ /*
+ * Special case: This is a retraction of all prefixes announced by this
+ * neighbour (see second-to-last paragraph of section 4.4.9 in the RFC).
+ */
+ WALK_LIST(n, nbr->routes)
+ {
+ r = SKIP_BACK(struct babel_route, neigh_route, n);
+ r->metric = BABEL_INFINITY;
+ babel_select_route(r->e);
+ }
+ }
+ else
+ {
+ e = babel_find_entry(p, msg->prefix, msg->plen);
- if (!e)
+ if (!e)
+ return;
+
+ /* The route entry indexed by neighbour */
+ r = babel_find_route(e, nbr);
+
+ if (!r)
+ return;
+
+ r->metric = BABEL_INFINITY;
+ babel_select_route(e);
+ }
+
+ /* Done with retractions */
return;
+ }
+ e = babel_get_entry(p, msg->prefix, msg->plen);
+ r = babel_find_route(e, nbr); /* the route entry indexed by neighbour */
s = babel_find_source(e, msg->router_id); /* for feasibility */
- r = babel_find_route(e, n); /* the route entry indexed by neighbour */
feasible = babel_is_feasible(s, msg->seqno, msg->metric);
if (!r)
{
- if (!feasible || (msg->metric == BABEL_INFINITY))
+ if (!feasible)
return;
- r = babel_get_route(e, n);
+ r = babel_get_route(e, nbr);
r->advert_metric = msg->metric;
r->router_id = msg->router_id;
- r->metric = babel_compute_metric(n, msg->metric);
+ r->metric = babel_compute_metric(nbr, msg->metric);
r->next_hop = msg->next_hop;
r->seqno = msg->seqno;
}
else if (r == r->e->selected_in && !feasible)
{
- /* Route is installed and update is infeasible - we may lose the route, so
- send a unicast seqno request (section 3.8.2.2 second paragraph). */
+ /*
+ * Route is installed and update is infeasible - we may lose the route,
+ * so send a unicast seqno request (section 3.8.2.2 second paragraph).
+ */
babel_unicast_seqno_request(r);
- if (msg->router_id == r->router_id) return;
- r->metric = BABEL_INFINITY; /* retraction */
+ if (msg->router_id == r->router_id)
+ return;
+
+ /* Treat as retraction */
+ r->metric = BABEL_INFINITY;
}
else
{
/* Last paragraph above - update the entry */
r->advert_metric = msg->metric;
- r->metric = babel_compute_metric(n, msg->metric);
- r->router_id = msg->router_id;
+ r->metric = babel_compute_metric(nbr, msg->metric);
r->next_hop = msg->next_hop;
+
+ r->router_id = msg->router_id;
r->seqno = msg->seqno;
- if (msg->metric != BABEL_INFINITY)
- {
- r->expiry_interval = BABEL_ROUTE_EXPIRY_FACTOR(msg->interval);
- r->expires = now + r->expiry_interval;
- if (r->expiry_interval > BABEL_ROUTE_REFRESH_INTERVAL)
- r->refresh_time = now + r->expiry_interval - BABEL_ROUTE_REFRESH_INTERVAL;
- }
+ r->expiry_interval = BABEL_ROUTE_EXPIRY_FACTOR(msg->interval);
+ r->expires = now + r->expiry_interval;
+ if (r->expiry_interval > BABEL_ROUTE_REFRESH_INTERVAL)
+ r->refresh_time = now + r->expiry_interval - BABEL_ROUTE_REFRESH_INTERVAL;
/* If the route is not feasible at this point, it means it is from another
neighbour than the one currently selected; so send a unicast seqno
diff --git a/proto/babel/packets.c b/proto/babel/packets.c
index be47aa75..d0cc613e 100644
--- a/proto/babel/packets.c
+++ b/proto/babel/packets.c
@@ -480,6 +480,7 @@ babel_read_update(struct babel_tlv *hdr, union babel_msg *m,
if (tlv->plen > 0)
return PARSE_ERROR;
+ msg->plen = 0;
msg->prefix = IPA_NONE;
break;
@@ -523,7 +524,8 @@ babel_read_update(struct babel_tlv *hdr, union babel_msg *m,
return PARSE_IGNORE;
}
- if (!state->router_id_seen)
+ /* Update must have Router ID, unless it is retraction */
+ if (!state->router_id_seen && (msg->metric != BABEL_INFINITY))
{
DBG("Babel: No router ID seen before update\n");
return PARSE_ERROR;