}
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;
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);
#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
{
u16 peer_index;
u32 originated_time;
+ u32 path_id; /* draft-petrie-grow-mrt-add-paths */
u16 attributes_length;
byte *attributes; /* encoded BGP attributes */
};
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 */
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;
return;
uint max_work_size = 1;
- u32 original_rib_sequence_number = state->rib_sequence_number;
FIB_ITERATE_START(&state->rtable->fib, &state->fit, f)
{
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);