mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 18:21:54 +00:00
MRT Table Dump: draft-petrie-grow-mrt-add-paths
Add support for MRT Table Dump draft-petrie-grow-mrt-add-paths
This commit is contained in:
parent
696acee0c7
commit
71299a594d
@ -219,14 +219,14 @@ mrt_rib_table_alloc(struct mrt_rib_table *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
mrt_rib_table_reset(state);
|
||||||
|
|
||||||
#ifdef IPV6
|
#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
|
#else
|
||||||
state->subtype = MRT_RIB_IPV4_UNICAST;
|
state->subtype = (is_addpath == MRT_RIB_ADDPATH) ? MRT_RIB_IPV4_UNICAST_ADDPATH : MRT_RIB_IPV4_UNICAST;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct mrt_buffer *msg = &state->msg;
|
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->peer_index);
|
||||||
mrt_buffer_put_var_autosize(msg, entry->originated_time);
|
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_var_autosize(msg, entry->attributes_length);
|
||||||
mrt_buffer_put_raw(msg, entry->attributes, entry->attributes_length);
|
mrt_buffer_put_raw(msg, entry->attributes, entry->attributes_length);
|
||||||
|
|
||||||
|
@ -37,6 +37,13 @@
|
|||||||
#define MRT_RIB_IPV6_UNICAST 4
|
#define MRT_RIB_IPV6_UNICAST 4
|
||||||
#define MRT_RIB_IPV6_MULTICAST 5
|
#define MRT_RIB_IPV6_MULTICAST 5
|
||||||
#define MRT_RIB_GENERIC 6
|
#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 */
|
/* MRT BGP4MP Subtypes */
|
||||||
#define MRT_BGP4MP_MESSAGE 1
|
#define MRT_BGP4MP_MESSAGE 1
|
||||||
@ -72,6 +79,7 @@ struct mrt_rib_entry
|
|||||||
{
|
{
|
||||||
u16 peer_index;
|
u16 peer_index;
|
||||||
u32 originated_time;
|
u32 originated_time;
|
||||||
|
u32 path_id; /* draft-petrie-grow-mrt-add-paths */
|
||||||
u16 attributes_length;
|
u16 attributes_length;
|
||||||
byte *attributes; /* encoded BGP attributes */
|
byte *attributes; /* encoded BGP attributes */
|
||||||
};
|
};
|
||||||
@ -98,7 +106,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_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_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);
|
void mrt_rib_table_add_entry(struct mrt_rib_table *state, const struct mrt_rib_entry *entry);
|
||||||
|
|
||||||
/* implemented in sysdep */
|
/* implemented in sysdep */
|
||||||
|
140
proto/bgp/mrt.c
140
proto/bgp/mrt.c
@ -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);
|
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:
|
* Usage:
|
||||||
* struct mrt_table_dump_ctx ctx;
|
* struct mrt_table_dump_ctx ctx;
|
||||||
@ -66,7 +151,6 @@ bgp_mrt_table_dump_step(struct mrt_table_dump_ctx *state)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
uint max_work_size = 1;
|
uint max_work_size = 1;
|
||||||
u32 original_rib_sequence_number = state->rib_sequence_number;
|
|
||||||
|
|
||||||
FIB_ITERATE_START(&state->rtable->fib, &state->fit, f)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
net *n = (net *) f;
|
mrt_rib_table_without_addpath(state, (net *) f);
|
||||||
mrt_rib_table_header(&state->rib_table, state->rib_sequence_number++, n->n.pxlen, n->n.prefix);
|
mrt_rib_table_with_addpath(state, (net *) f);
|
||||||
|
|
||||||
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;
|
|
||||||
} FIB_ITERATE_END(f);
|
} FIB_ITERATE_END(f);
|
||||||
|
|
||||||
fit_get(&state->rtable->fib, &state->fit);
|
fit_get(&state->rtable->fib, &state->fit);
|
||||||
|
Loading…
Reference in New Issue
Block a user