]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
MRT Table Dump: draft-petrie-grow-mrt-add-paths
authorPavel Tvrdík <pawel.tvrdik@gmail.com>
Tue, 5 Jan 2016 18:48:35 +0000 (19:48 +0100)
committerPavel Tvrdík <pawel.tvrdik@gmail.com>
Wed, 6 Jan 2016 13:51:52 +0000 (14:51 +0100)
Add support for MRT Table Dump draft-petrie-grow-mrt-add-paths

nest/mrtdump.c
nest/mrtdump.h
nest/mrtdump_test.c
proto/bgp/mrt.c
proto/bgp/packets.c

index 515a7c4dca60b17e4c299413da903ba86514e948..fa9bbbaf29f216b3bd1de8770e1356eb81701a20 100644 (file)
@@ -219,14 +219,14 @@ mrt_rib_table_alloc(struct mrt_rib_table *state)
 }
 
 void
-mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix)
+mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix, uint is_addpath)
 {
   mrt_rib_table_reset(state);
 
 #ifdef IPV6
-  state->subtype = MRT_RIB_IPV6_UNICAST;
+  state->subtype = (is_addpath == MRT_RIB_ADDPATH) ? MRT_RIB_IPV6_UNICAST_ADDPATH : MRT_RIB_IPV6_UNICAST;
 #else
-  state->subtype = MRT_RIB_IPV4_UNICAST;
+  state->subtype = (is_addpath == MRT_RIB_ADDPATH) ? MRT_RIB_IPV4_UNICAST_ADDPATH : MRT_RIB_IPV4_UNICAST;
 #endif
 
   struct mrt_buffer *msg = &state->msg;
@@ -257,6 +257,16 @@ mrt_rib_table_add_entry(struct mrt_rib_table *state, const struct mrt_rib_entry
 
   mrt_buffer_put_var_autosize(msg, entry->peer_index);
   mrt_buffer_put_var_autosize(msg, entry->originated_time);
+
+  switch (state->subtype)
+  {
+    case MRT_RIB_IPV4_UNICAST_ADDPATH:
+    case MRT_RIB_IPV6_UNICAST_ADDPATH:
+    case MRT_RIB_IPV4_MULTICAST_ADDPATH:
+    case MRT_RIB_IPV6_MULTICAST_ADDPATH:
+      mrt_buffer_put_var_autosize(msg, entry->path_id);
+  }
+
   mrt_buffer_put_var_autosize(msg, entry->attributes_length);
   mrt_buffer_put_raw(msg, entry->attributes, entry->attributes_length);
 
index 9ca9ca4bd04f828850501c36d79340ef7bac1ad2..6a7da79a156bc25f6db34cba502244ebe965e4ba 100644 (file)
 #define MRT_RIB_IPV6_UNICAST   4
 #define MRT_RIB_IPV6_MULTICAST         5
 #define MRT_RIB_GENERIC                6
+#define MRT_RIB_IPV4_UNICAST_ADDPATH   8       /* Experimental draft-petrie-grow-mrt-add-paths */
+#define MRT_RIB_IPV4_MULTICAST_ADDPATH 9       /* Experimental draft-petrie-grow-mrt-add-paths */
+#define MRT_RIB_IPV6_UNICAST_ADDPATH   10      /* Experimental draft-petrie-grow-mrt-add-paths */
+#define MRT_RIB_IPV6_MULTICAST_ADDPATH         11      /* Experimental draft-petrie-grow-mrt-add-paths */
+#define MRT_RIB_GENERIC_ADDPATH                12      /* Experimental draft-petrie-grow-mrt-add-paths */
+#define MRT_RIB_NO_ADDPATH     0
+#define MRT_RIB_ADDPATH                1
+
 
 /* MRT BGP4MP Subtypes */
 #define MRT_BGP4MP_MESSAGE     1
@@ -72,6 +80,7 @@ struct mrt_rib_entry
 {
   u16 peer_index;
   u32 originated_time;
+  u32 path_id;                 /* draft-petrie-grow-mrt-add-paths */
   u16 attributes_length;
   byte *attributes;            /* encoded BGP attributes */
 };
@@ -98,7 +107,7 @@ void mrt_peer_index_table_add_peer(struct mrt_peer_index_table *state, u32 peer_
 void mrt_peer_index_table_dump(struct mrt_peer_index_table *state, int file_descriptor);
 
 void mrt_rib_table_alloc(struct mrt_rib_table *state);
-void mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix);
+void mrt_rib_table_header(struct mrt_rib_table *state, u32 sequence_number, u8 prefix_length, ip_addr prefix, uint is_addpath);
 void mrt_rib_table_add_entry(struct mrt_rib_table *state, const struct mrt_rib_entry *entry);
 
 /* implemented in sysdep */
index f7071108873100865637da446ab16ec13fa015dc..d5a21e12acf3fc180ef8fe9bdce4df3ecda60cf9 100644 (file)
@@ -102,7 +102,7 @@ t_rib_table(void)
   ip4_pton("12.34.56.78", &prefix);
 #endif
   mrt_rib_table_alloc(&state);
-  mrt_rib_table_header(&state, sequence_number, prefix_len, prefix);
+  mrt_rib_table_header(&state, sequence_number, prefix_len, prefix, MRT_RIB_NO_ADDPATH);
 
   u32 i;
   for(i = 0; i < 5; i++)
index 713be83a6f36c3cba6f3d9e7e0d5afeb78af1320..ff0ca703228f48503f58959d69be3a4a0d8fbeb9 100644 (file)
@@ -52,6 +52,91 @@ bgp_mrt_rib_table_dump(struct mrt_table_dump_ctx *state)
   mrt_dump_message(fileno(state->rfile->f), MRT_TABLE_DUMP_V2, state->rib_table.subtype, msg, msg_length);
 }
 
+static void
+bgp_mrt_rib_table_entry(struct mrt_table_dump_ctx *state, net *n, uint is_addpath)
+{
+  u32 original_rib_sequence_number = state->rib_sequence_number;
+
+  mrt_rib_table_header(&state->rib_table, state->rib_sequence_number++, n->n.pxlen, n->n.prefix, is_addpath);
+
+  rte *e;
+  for (e = n->routes; e; e = e->next)
+  {
+    u32 path_id = 0;
+
+    if (is_addpath == MRT_RIB_ADDPATH)
+      if (e->attrs->src->private_id == 0)
+       continue;
+
+    if (is_addpath == MRT_RIB_NO_ADDPATH)
+      if (e->attrs->src->private_id != 0)
+       continue;
+
+    struct proto *P = e->attrs->src->proto;
+
+    if (!is_route_good_for_table_dump(state, e))
+      continue;
+
+    u16 peer_index = 0; /* have to correspond with fake zeroed-peer in peer index table */
+    uint attributes_length = 0;
+    static byte attributes_buffer[BGP_ATTR_BUFFER_SIZE]; /* static intends to do better performance */
+
+    if (P->proto == &proto_bgp)
+    {
+      struct bgp_proto *p = (struct bgp_proto *) P;
+
+      if (p->mrt_peer_index == 0)
+      {
+       log(L_INFO "%s: MRT Table Dump for %I/%u: Skipping not-indexed BPG RIB (local ASN: %u, remote ASN: %u)", p->p.name, n->n.prefix, n->n.pxlen, p->local_as, p->remote_as);
+       continue;
+      }
+
+      /* Set as4_session=1 to force build AS_PATH as 32bit AS in bgp_encode_attrs() */
+      struct bgp_proto bgp_proto_shallow_copy;
+      memcpy(&bgp_proto_shallow_copy, p, sizeof(bgp_proto_shallow_copy));
+      bgp_proto_shallow_copy.as4_session = 1;
+
+      attributes_length = bgp_encode_attrs(&bgp_proto_shallow_copy, attributes_buffer, e->attrs->eattrs, BGP_ATTR_BUFFER_SIZE);
+      if (attributes_length == -1)
+      {
+       log(L_WARN "%s: MRT Table Dump for %I/%u: Attribute list too long, let it blank", p->p.name, n->n.prefix, n->n.pxlen);
+       attributes_length = 0;
+      }
+      peer_index = p->mrt_peer_index;
+
+      if (is_addpath)
+        path_id = e->attrs->src->private_id;
+    }
+
+    struct mrt_rib_entry entry = {
+       .peer_index = peer_index,
+       .originated_time = (u32) bird_clock_to_unix_timestamp(e->lastmod),
+       .path_id = path_id,
+       .attributes_length = attributes_length,
+       .attributes = attributes_buffer
+    };
+
+    mrt_rib_table_add_entry(&state->rib_table, &entry);
+  }
+
+  if (state->rib_table.entry_count)
+    bgp_mrt_rib_table_dump(state);
+  else
+    state->rib_sequence_number = original_rib_sequence_number;
+}
+
+static void
+mrt_rib_table_without_addpath(struct mrt_table_dump_ctx *state, net *n)
+{
+  bgp_mrt_rib_table_entry(state, n, MRT_RIB_NO_ADDPATH);
+}
+
+static void
+mrt_rib_table_with_addpath(struct mrt_table_dump_ctx *state, net *n)
+{
+  bgp_mrt_rib_table_entry(state, n, MRT_RIB_ADDPATH);
+}
+
 /*
  * Usage:
  *     struct mrt_table_dump_ctx ctx;
@@ -66,7 +151,6 @@ bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
     return;
 
   uint max_work_size = 1;
-  u32 original_rib_sequence_number = state->rib_sequence_number;
 
   FIB_ITERATE_START(&state->rtable->fib, &state->fit, f)
   {
@@ -76,58 +160,8 @@ bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
       return;
     }
 
-    net *n = (net *) f;
-    mrt_rib_table_header(&state->rib_table, state->rib_sequence_number++, n->n.pxlen, n->n.prefix);
-
-    rte *e;
-    for (e = n->routes; e; e = e->next)
-    {
-      struct proto *P = e->attrs->src->proto;
-
-      if (!is_route_good_for_table_dump(state, e))
-       continue;
-
-      u16 peer_index = 0; /* have to correspond with fake zeroed-peer in peer index table */
-      uint attributes_length = 0;
-      static byte attributes_buffer[BGP_ATTR_BUFFER_SIZE]; /* static intends to do better performance */
-
-      if (P->proto == &proto_bgp)
-      {
-       struct bgp_proto *p = (struct bgp_proto *) P;
-
-       if (p->mrt_peer_index == 0)
-       {
-         log(L_INFO "%s: MRT Table Dump for %I/%u: Skipping not-indexed BPG RIB (local ASN: %u, remote ASN: %u)", p->p.name, n->n.prefix, n->n.pxlen, p->local_as, p->remote_as);
-         continue;
-       }
-
-       struct bgp_proto tmp_bgp_proto = {
-           .as4_session = 1, /* to force build AS_PATH as 32bit AS in bgp_encode_attrs() */
-       };
-
-       attributes_length = bgp_encode_attrs(&tmp_bgp_proto, attributes_buffer, e->attrs->eattrs, BGP_ATTR_BUFFER_SIZE);
-       if (attributes_length == -1)
-       {
-         log(L_WARN "%s: MRT Table Dump for %I/%u: Attribute list too long, let it blank", p->p.name, n->n.prefix, n->n.pxlen);
-         attributes_length = 0;
-       }
-       peer_index = p->mrt_peer_index;
-      }
-
-      struct mrt_rib_entry entry = {
-         .peer_index = peer_index,
-         .originated_time = (u32) bird_clock_to_unix_timestamp(e->lastmod),
-         .attributes_length = attributes_length,
-         .attributes = attributes_buffer
-      };
-
-      mrt_rib_table_add_entry(&state->rib_table, &entry);
-    }
-
-    if (state->rib_table.entry_count)
-      bgp_mrt_rib_table_dump(state);
-    else
-      state->rib_sequence_number = original_rib_sequence_number;
+    mrt_rib_table_without_addpath(state, (net *) f);
+    mrt_rib_table_with_addpath(state, (net *) f);
   } FIB_ITERATE_END(f);
 
   fit_get(&state->rtable->fib, &state->fit);
index f2169cdb4363e1eb2f235192d90701ff443ab9e6..30f4b3d88f2b21d5679d6dcc1e0660616bf09216 100644 (file)
@@ -100,7 +100,7 @@ mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
   memcpy(bp, pkt, len);
   bp += len;
 
-  mrt_dump_message(&conn->bgp->p, MRT_BGP4MP, subtype, buf, bp-buf);
+  mrt_dump_message_proto(&conn->bgp->p, MRT_BGP4MP, subtype, buf, bp-buf);
 }
 
 static inline u16