0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 15:41:54 +00:00

Add core support for MRT Table Dump (RFC 6396)

This commit is contained in:
Pavel Tvrdík 2015-05-19 10:47:14 +02:00
parent 700cf1c203
commit de77e5cdd0
10 changed files with 370 additions and 33 deletions

View File

@ -233,7 +233,7 @@ ip6_ntop(ip6_addr a, char *b)
}
int
ip4_pton(char *a, ip4_addr *o)
ip4_pton(const char *a, ip4_addr *o)
{
int i;
unsigned long int l;
@ -258,11 +258,11 @@ ip4_pton(char *a, ip4_addr *o)
}
int
ip6_pton(char *a, ip6_addr *o)
ip6_pton(const char *a, ip6_addr *o)
{
u16 words[8];
int i, j, k, l, hfil;
char *start;
const char *start;
if (a[0] == ':') /* Leading :: */
{

View File

@ -446,8 +446,8 @@ static inline char * ip4_ntox(ip4_addr a, char *b)
static inline char * ip6_ntox(ip6_addr a, char *b)
{ return b + bsprintf(b, "%08x.%08x.%08x.%08x", _I0(a), _I1(a), _I2(a), _I3(a)); }
int ip4_pton(char *a, ip4_addr *o);
int ip6_pton(char *a, ip6_addr *o);
int ip4_pton(const char *a, ip4_addr *o);
int ip6_pton(const char *a, ip6_addr *o);
// XXXX these functions must be redesigned or removed
#ifdef IPV6

View File

@ -20,7 +20,7 @@ build_ip4(u8 a, u8 b, u8 c, u8 d)
}
static u32
ip4_pton_(char *s)
ip4_pton_(const char *s)
{
ip4_addr ip;
ip4_pton(s, &ip);
@ -54,7 +54,7 @@ t_ip4_pton(void)
}
static void
ip6_pton_(char *s, u32 (*addr)[4])
ip6_pton_(const char *s, u32 (*addr)[4])
{
static ip6_addr ip;
ip6_pton(s, &ip);

159
nest/mrtdump.c Normal file
View File

@ -0,0 +1,159 @@
/*
* BIRD -- Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "nest/mrtdump.h"
void
mrt_msg_init(struct mrt_msg *msg, pool *mem_pool)
{
msg->mem_pool = mem_pool;
msg->msg_capacity = MRT_MSG_DEFAULT_CAPACITY;
msg->msg_length = 0;
msg->msg = mb_alloc(msg->mem_pool, msg->msg_capacity);
}
void
mrt_msg_free(struct mrt_msg *msg)
{
mb_free(msg->msg);
}
static byte *
mrt_peer_index_table_get_peer_count(struct mrt_peer_index_table *pit_msg)
{
struct mrt_msg * msg = pit_msg->msg;
uint collector_bgp_id_size = 4;
uint name_length_size = 2;
uint name_size = pit_msg->name_length;
uint peer_count_offset = collector_bgp_id_size + name_length_size + name_size;
return &(msg->msg[peer_count_offset]);
}
static void
mrt_grow_msg_buffer(struct mrt_msg * msg, size_t min_required_capacity)
{
msg->msg_capacity *= 2;
if (min_required_capacity > msg->msg_capacity)
msg->msg_capacity = min_required_capacity;
msg->msg = mb_realloc(msg->msg, msg->msg_capacity);
}
static void
mrt_write_to_msg(struct mrt_msg * msg, const void *data, size_t data_size)
{
if (data_size == 0)
return;
u32 i;
for (i = 0; i < data_size; i++)
debug("%02X ", ((byte*)data)[i]);
debug("| ");
size_t required_size = data_size + msg->msg_length;
if (msg->msg_capacity < required_size)
mrt_grow_msg_buffer(msg, required_size);
memcpy(&msg->msg[msg->msg_length], data, data_size);
msg->msg_length += data_size;
}
#define mrt_write_to_msg_(msg, data) mrt_write_to_msg(msg, &data, sizeof(data))
void
mrt_peer_index_table_init(struct mrt_peer_index_table *pit_msg, u32 collector_bgp_id, const char *name)
{
struct mrt_msg * msg = pit_msg->msg;
pit_msg->peer_count = 0;
pit_msg->name_length = strlen(name);
mrt_write_to_msg_(msg, collector_bgp_id);
mrt_write_to_msg_(msg, pit_msg->name_length);
mrt_write_to_msg(msg, name, pit_msg->name_length);
mrt_write_to_msg_(msg, pit_msg->peer_count);
debug("\n");
}
static void
mrt_peer_index_table_inc_peer_count(struct mrt_peer_index_table *pit_msg)
{
pit_msg->peer_count++;
byte *peer_count = mrt_peer_index_table_get_peer_count(pit_msg);
put_u16(peer_count, pit_msg->peer_count);
}
void
mrt_peer_index_table_add_peer(struct mrt_peer_index_table *pit_msg, u32 peer_bgp_id, ip_addr *peer_ip_addr, u32 peer_as)
{
struct mrt_msg * msg = pit_msg->msg;
u8 peer_type = PEER_TYPE_AS_32BIT;
if (sizeof(*peer_ip_addr) > sizeof(ip4_addr))
peer_type |= PEER_TYPE_IPV6;
mrt_write_to_msg_(msg, peer_type);
mrt_write_to_msg_(msg, peer_bgp_id);
mrt_write_to_msg_(msg, *peer_ip_addr);
mrt_write_to_msg_(msg, peer_as);
mrt_peer_index_table_inc_peer_count(pit_msg);
debug("\n");
}
void
mrt_rib_table_init(struct mrt_rib_table *rt_msg, u32 sequence_number, u8 prefix_length, ip_addr *prefix)
{
struct mrt_msg *msg = rt_msg->msg;
rt_msg->entry_count = 0;
mrt_write_to_msg_(msg, sequence_number);
mrt_write_to_msg_(msg, prefix_length);
mrt_write_to_msg_(msg, *prefix);
mrt_write_to_msg_(msg, rt_msg->entry_count);
debug("\n");
}
static byte *
mrt_rib_table_get_entry_count(struct mrt_rib_table *rt_msg)
{
struct mrt_msg *msg = rt_msg->msg;
u32 sequence_number_size = 4;
u32 prefix_length_size = 1;
u32 prefix_size = 4;
if (rt_msg->type == RIB_IPV4_UNICAST)
prefix_size = 4;
else if (rt_msg->type == RIB_IPV6_UNICAST)
prefix_size = 16;
else
bug("mrt_rib_table_get_entry_count: unknown RIB type!");
u32 offset = sequence_number_size + prefix_length_size + prefix_size;
return &msg->msg[offset];
}
static void
mrt_rib_table_inc_entry_count(struct mrt_rib_table *rt_msg)
{
rt_msg->entry_count++;
byte *entry_count = mrt_rib_table_get_entry_count(rt_msg);
put_u16(entry_count, rt_msg->entry_count);
}
void
mrt_rib_table_add_entry(struct mrt_rib_table *rt_msg, const struct mrt_rib_entry *rib)
{
struct mrt_msg *msg = rt_msg->msg;
mrt_write_to_msg_(msg, rib->peer_index);
mrt_write_to_msg_(msg, rib->originated_time);
mrt_write_to_msg_(msg, rib->attributes_length);
mrt_write_to_msg(msg, rib->attributes, rib->attributes_length);
mrt_rib_table_inc_entry_count(rt_msg);
debug("\n");
}

View File

@ -1,31 +1,90 @@
/*
* BIRD -- MRTdump handling
* BIRD -- Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef MRTDUMP_H
#define MRTDUMP_H
#ifndef _MRTDUMP_H_
#define _MRTDUMP_H_
#include "nest/protocol.h"
/* MRTDump values */
#define MRTDUMP_HDR_LENGTH 12
#define PEER_TYPE_AS_32BIT 0b00000010 /* MRT TABLE_DUMP_V2: PEER_INDEX_TABLE: Peer Type: Use 32bit ASN */
#define PEER_TYPE_IPV6 0b00000001 /* MRT TABLE_DUMP_V2: PEER_INDEX_TABLE: Peer Type: Use IPv6 IP Address */
/* MRTdump types */
/* MRT Types */
enum mrt_type
{
TABLE_DUMP_V2 = 13,
BGP4MP = 16,
};
#define BGP4MP 16
/* MRT TABLE_DUMP_V2 Sub-Types */
enum table_dump_v2_type
{
PEER_INDEX_TABLE = 1,
RIB_IPV4_UNICAST = 2,
RIB_IPV4_MULTICAST = 3,
RIB_IPV6_UNICAST = 4,
RIB_IPV6_MULTICAST = 5,
RIB_GENERIC = 6,
};
/* MRTdump subtypes */
/* MRT BGP4MP Sub-Types */
enum bgp4mp_subtype
{
BGP4MP_MESSAGE = 1,
BGP4MP_MESSAGE_AS4 = 4,
BGP4MP_STATE_CHANGE_AS4 = 5,
};
#define BGP4MP_MESSAGE 1
#define BGP4MP_MESSAGE_AS4 4
#define BGP4MP_STATE_CHANGE_AS4 5
struct mrt_msg
{
byte *msg; /* Buffer with final formatted data */
size_t msg_length; /* Size of used buffer */
size_t msg_capacity; /* Number of allocated bytes in msg */
#define MRT_MSG_DEFAULT_CAPACITY 64 /* in bytes */
pool *mem_pool;
};
/* TABLE_DUMP_V2 -> PEER_INDEX_TABLE */
struct mrt_peer_index_table
{
struct mrt_msg *msg;
u16 peer_count;
u16 name_length;
};
/* TABLE_DUMP_V2 -> RIB_IPV4_UNICAST or RIB_IPV6_UNICAST */
struct mrt_rib_table
{
struct mrt_msg *msg;
enum table_dump_v2_type type; /* RIB_IPV4_UNICAST or RIB_IPV6_UNICAST */
u16 entry_count; /* Number of RIB Entries */
struct bgp_proto *bgp_proto;
};
/* TABLE_DUMP_V2 -> RIB Entry */
struct mrt_rib_entry
{
u16 peer_index;
u32 originated_time;
u16 attributes_length;
byte *attributes;
};
void mrt_msg_init(struct mrt_msg *msg, pool *mem_pool);
void mrt_msg_free(struct mrt_msg *msg);
void mrt_peer_index_table_init(struct mrt_peer_index_table *pit_msg, u32 collector_bgp_id, const char *name);
void mrt_peer_index_table_add_peer(struct mrt_peer_index_table *pit_msg, u32 peer_bgp_id, ip_addr *peer_ip_addr, u32 peer_as);
void mrt_rib_table_init(struct mrt_rib_table *rt_msg, u32 sequence_number, u8 prefix_length, ip_addr *prefix);
void mrt_rib_table_add_entry(struct mrt_rib_table *rt_msg, const struct mrt_rib_entry *rib);
/* implemented in sysdep */
void mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len);
#endif
void mrt_dump_message(const struct proto *p, u16 type, u16 subtype, byte *buf, u32 len);
#endif /* _MRTDUMP_H_ */

115
nest/mrtdump_test.c Normal file
View File

@ -0,0 +1,115 @@
/*
* BIRD -- Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format Tests
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "test/birdtest.h"
#include "test/birdtest_support.h" /* REMOVE ME */
#include "nest/mrtdump.h"
#include "nest/mrtdump.c" /* REMOVE ME */
static void
show_mrt_msg(struct mrt_msg *msg)
{
uint i;
bt_debug("show_mrt_msg: \n ");
for(i = 0; i < msg->msg_length; i++)
{
if (i && (i % 16) == 0)
bt_debug("\n ");
bt_debug("%02X ", msg->msg[i]);
}
bt_debug("\n");
}
static int
t_peer_index_table(void)
{
resource_init();
struct mrt_msg msg;
mrt_msg_init(&msg, &root_pool);
struct mrt_peer_index_table pit_msg = {
.msg = &msg,
};
u32 collector_bgp_id = 0x12345678;
const char *collector_name = "test";
mrt_peer_index_table_init(&pit_msg, collector_bgp_id, collector_name);
u32 i;
for(i = 0; i < 50; i++)
{
ip_addr addr;
#ifdef IPV6
ip6_pton("1234:5678::9abc:def0", &addr);
#else
ip4_pton("12.34.56.78", &addr);
#endif
mrt_peer_index_table_add_peer(&pit_msg, i | 0x30303030, &addr, i | 0x08080808);
}
show_mrt_msg(&msg);
mrt_msg_free(&msg);
return BT_SUCCESS;
}
static int
t_rib_table(void)
{
resource_init();
struct mrt_msg msg;
mrt_msg_init(&msg, &root_pool);
struct mrt_rib_table rt_msg = {
.bgp_proto = NULL,
.msg = &msg,
};
u32 sequence_number = 0x12345678;
u8 prefix_len = 24;
ip_addr prefix;
#ifdef IPV6
rt_msg.type = RIB_IPV6_UNICAST;
ip6_pton("1234:5678::9abc:def0", &prefix);
#else
rt_msg.type = RIB_IPV4_UNICAST;
ip4_pton("12.34.56.78", &prefix);
#endif
mrt_rib_table_init(&rt_msg, sequence_number, prefix_len, &prefix);
u32 i;
for(i = 0; i < 50; i++)
{
struct mrt_rib_entry entry = {
.peer_index = i,
.originated_time = i | 0x08080808,
.attributes_length = 7,
.attributes = "abcdefg",
};
mrt_rib_table_add_entry(&rt_msg, &entry);
}
show_mrt_msg(&msg);
mrt_msg_free(&msg);
return BT_SUCCESS;
}
int
main(int argc, char *argv[])
{
bt_init(argc, argv);
bt_test_suite(t_peer_index_table, "TABLE_DUMP_V2: Peer index table");
bt_test_suite(t_rib_table, "TABLE_DUMP_V2: RIB table");
return bt_end();
}

View File

@ -72,8 +72,8 @@ void fib_delete(struct fib *, void *); /* Remove fib entry */
void fib_free(struct fib *); /* Destroy the fib */
void fib_check(struct fib *); /* Consistency check for debugging */
void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */
struct fib_node *fit_get(struct fib *, struct fib_iterator *);
void fit_init(struct fib_iterator *, const struct fib *); /* Internal functions, don't call */
struct fib_node *fit_get(const struct fib *, struct fib_iterator *);
void fit_put(struct fib_iterator *, struct fib_node *);
#define FIB_WALK(fib, z) do { \

View File

@ -73,7 +73,7 @@ fib_ht_free(struct fib_node **h)
}
static inline unsigned
fib_hash(struct fib *f, ip_addr *a)
fib_hash(const struct fib *f, ip_addr *a)
{
return ipa_hash(*a) >> f->hash_shift;
}
@ -368,7 +368,7 @@ fib_free(struct fib *f)
}
void
fit_init(struct fib_iterator *i, struct fib *f)
fit_init(struct fib_iterator *i, const struct fib *f)
{
unsigned h;
struct fib_node *n;
@ -390,7 +390,7 @@ fit_init(struct fib_iterator *i, struct fib *f)
}
struct fib_node *
fit_get(struct fib *f, struct fib_iterator *i)
fit_get(const struct fib *f, struct fib_iterator *i)
{
struct fib_node *n;
struct fib_iterator *j, *k;

View File

@ -316,7 +316,7 @@ log_init_debug(char *f)
}
void
mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
mrt_dump_message(const struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
{
/* Prepare header */
put_u32(buf+0, now_real);

View File

@ -5,8 +5,10 @@
#include "lib/printf.c" /* REMOVE ME */
#include "lib/xmalloc.c" /* REMOVE ME */
#include "lib/bitops.c" /* REMOVE ME */
#include "lib/mempool.c" /* REMOVE ME */
#define bug(msg, ...) debug("BUG: " msg, ##__VA_ARGS__)
#define log_msg(msg, ...) debug("LOG_MSG: " msg, ##__VA_ARGS__)
void
debug(const char *msg, ...)
@ -32,3 +34,5 @@ io_log_event(void *hook, void *data)
{
bt_debug("This is io_log_event mockup. \n");
};
#include "lib/slab.c" /* REMOVE ME */