}
int
-ip4_pton(char *a, ip4_addr *o)
+ip4_pton(const char *a, ip4_addr *o)
{
int i;
unsigned long int l;
}
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 :: */
{
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
}
static u32
-ip4_pton_(char *s)
+ip4_pton_(const char *s)
{
ip4_addr ip;
- ip4_pton(s,&ip);
+ ip4_pton(s, &ip);
return ip.addr;
}
}
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);
--- /dev/null
+/*
+ * 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");
+}
/*
- * 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;
+};
-/* implemented in sysdep */
-void mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len);
+/* 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;
+};
-#endif
+/* 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(const struct proto *p, u16 type, u16 subtype, byte *buf, u32 len);
+#endif /* _MRTDUMP_H_ */
--- /dev/null
+/*
+ * 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();
+}
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 { \
struct fib_node *z, **ff = (fib)->hash_table; \
- uint count = (fib)->hash_size; \
+ uint count = (fib)->hash_size; \
while (count--) \
for(z = *ff++; z; z=z->next)
#define FIB_ITERATE_START(fib, it, z) do { \
struct fib_node *z = fit_get(fib, it); \
- uint count = (fib)->hash_size; \
- uint hpos = (it)->hash; \
+ uint count = (fib)->hash_size; \
+ uint hpos = (it)->hash; \
for(;;) { \
if (!z) \
- { \
+ { \
if (++hpos >= count) \
break; \
z = (fib)->hash_table[hpos]; \
}
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;
}
}
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;
}
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;
}
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);
#include "sysdep/config.h"
-#include "lib/event.c" /* REMOVE ME */
+#include "lib/event.c" /* REMOVE ME */
#include "lib/ip.c" /* REMOVE ME */
#include "lib/resource.c" /* REMOVE ME */
#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 bug(msg, ...) debug("BUG: " msg, ##__VA_ARGS__)
+#define log_msg(msg, ...) debug("LOG_MSG: " msg, ##__VA_ARGS__)
void
debug(const char *msg, ...)
{
bt_debug("This is io_log_event mockup. \n");
};
+
+#include "lib/slab.c" /* REMOVE ME */