[PATCH 5/7] Babel: Send wildcard retractions on shutdown and startup.

Toke Høiland-Jørgensen toke at toke.dk
Mon May 2 19:07:53 CEST 2016


This makes Bird send a wildcard retraction on all interfaces before
shutting down and right after starting up. This helps ensure that
neighbours will discard the announced routes as soon as possible, rather
than only after the normal timeout procedures.

Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
---
 proto/babel/babel.c   | 47 ++++++++++++++++++++++++++++++++++++++++-------
 proto/babel/babel.h   |  1 +
 proto/babel/packets.c | 20 ++++++++++++++++----
 3 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index e982abb..399d5f4 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -829,21 +829,29 @@ 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, ip_addr prefix, int plen, u8 wildcard)
 {
   struct babel_proto *p = ifa->proto;
   union babel_msg msg = {};
 
-  TRACE(D_PACKETS, "Sending retraction for %I/%d router-id %lR seqno %d",
-	prefix, plen, p->router_id, 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.router_id = p->router_id;
+  if (wildcard)
+  {
+    TRACE(D_PACKETS, "Sending wildcard retraction on %s", ifa->ifname);
+    msg.update.wildcard = 1;
+  }
+  else
+  {
+    TRACE(D_PACKETS, "Sending retraction for %I/%d router-id %lR seqno %d",
+	  prefix, plen, p->router_id, p->update_seqno);
+    msg.update.prefix = prefix;
+    msg.update.plen = plen;
+    msg.update.router_id = p->router_id;
+  }
 
   babel_enqueue(&msg, ifa);
 }
@@ -1204,7 +1212,7 @@ babel_handle_route_request(union babel_msg *m, struct babel_iface *ifa)
   struct babel_entry *e = babel_find_entry(p, msg->prefix, msg->plen);
   if (!e)
   {
-    babel_send_retraction(ifa, msg->prefix, msg->plen);
+    babel_send_retraction(ifa, msg->prefix, msg->plen, 0);
   }
   else
   {
@@ -1339,6 +1347,7 @@ babel_iface_start(struct babel_iface *ifa)
   ifa->up = 1;
 
   babel_send_hello(ifa, 0);
+  babel_send_retraction(ifa, IPA_NONE, 0, 1);
   babel_send_wildcard_request(ifa);
   babel_send_update(ifa, 0);	/* Full update */
 }
@@ -2051,6 +2060,29 @@ babel_start(struct proto *P)
   return PS_UP;
 }
 
+static inline void
+babel_iface_shutdown(struct babel_iface *ifa)
+{
+  if(ifa->sk)
+  {
+    babel_send_retraction(ifa, IPA_NONE, 0, 1);
+    babel_send_queue(ifa);
+  }
+}
+
+static int
+babel_shutdown(struct proto *P)
+{
+  struct babel_proto *p = (void *) P;
+  struct babel_iface *ifa;
+  TRACE(D_EVENTS, "Shutting down interfaces");
+
+  WALK_LIST(ifa, p->interfaces)
+    babel_iface_shutdown(ifa);
+
+  return PS_DOWN;
+}
+
 static int
 babel_reconfigure(struct proto *P, struct proto_config *c)
 {
@@ -2078,6 +2110,7 @@ struct protocol proto_babel = {
   .init =		babel_init,
   .dump =		babel_dump,
   .start =		babel_start,
+  .shutdown =		babel_shutdown,
   .reconfigure =	babel_reconfigure,
   .get_route_info =	babel_get_route_info,
   .get_attr =		babel_get_attr
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index 67d32ad..b871edd 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -270,6 +270,7 @@ struct babel_msg_update {
   u8 type;
   u8 ae;
   u8 plen;
+  u8 wildcard;
   u16 interval;
   u16 seqno;
   u16 metric;
diff --git a/proto/babel/packets.c b/proto/babel/packets.c
index 60b9cd3..b92ad9c 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->wildcard = 1;
     msg->prefix = IPA_NONE;
     break;
 
@@ -558,8 +559,12 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
    * When needed, we write Router-ID TLV before Update TLV and return size of
    * both of them. There is enough space for the Router-ID TLV, because
    * sizeof(struct babel_tlv_router_id) == sizeof(struct babel_tlv_update).
+   *
+   * Router ID is not used for retractions (section 4.4.9), so don't bother with
+   * it in this case.
    */
-  if (!state->router_id_seen || (msg->router_id != state->router_id))
+  if ((!state->router_id_seen || (msg->router_id != state->router_id))
+      && msg->metric < BABEL_INFINITY)
   {
     len0 = babel_write_router_id(hdr, msg->router_id, state, max_len);
     tlv = (struct babel_tlv_update *) NEXT_TLV(tlv);
@@ -572,12 +577,19 @@ babel_write_update(struct babel_tlv *hdr, union babel_msg *m,
 
   memset(tlv, 0, sizeof(struct babel_tlv_update));
   TLV_HDR(tlv, BABEL_TLV_UPDATE, len);
-  tlv->ae = BABEL_AE_IP6;
-  tlv->plen = msg->plen;
+  if(msg->wildcard)
+  {
+    tlv->ae = BABEL_AE_WILDCARD;
+  }
+  else
+  {
+    tlv->ae = BABEL_AE_IP6;
+    tlv->plen = msg->plen;
+    put_ip6_px(tlv->addr, msg->prefix, msg->plen);
+  }
   put_time16(&tlv->interval, msg->interval);
   put_u16(&tlv->seqno, msg->seqno);
   put_u16(&tlv->metric, msg->metric);
-  put_ip6_px(tlv->addr, msg->prefix, msg->plen);
 
   return len0 + len;
 }
-- 
2.8.0



More information about the Bird-users mailing list