mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
BMP: Never touching the BGP directly
Dropped hopefully last remnants of BMP directly accessing BGP structures.
This commit is contained in:
parent
dc692ae06a
commit
cde582977f
@ -423,7 +423,7 @@ ea_set_attr_u32(ea_list **to, const struct ea_class *def, uint flags, u64 data)
|
||||
{ ea_set_attr(to, EA_LITERAL_EMBEDDED(def, flags, data)); }
|
||||
|
||||
static inline void
|
||||
ea_set_attr_ptr(ea_list **to, const struct ea_class *def, uint flags, const void *data)
|
||||
ea_set_attr_ptr(ea_list **to, const struct ea_class *def, uint flags, void *data)
|
||||
{ ea_set_attr(to, EA_LITERAL_STORE_PTR(def, flags, data)); }
|
||||
|
||||
static inline void
|
||||
|
@ -24,7 +24,7 @@ union bval {
|
||||
}; \
|
||||
const struct adata *ptr; /* Generic attribute data inherited from eattrs */ \
|
||||
const struct adata *ad; /* Generic attribute data inherited from filters */ \
|
||||
const void * v_ptr; /* Stored pointer */ \
|
||||
void * v_ptr; /* Stored pointer */ \
|
||||
|
||||
BVAL_ITEMS;
|
||||
};
|
||||
|
@ -2146,6 +2146,10 @@ protos_build(void)
|
||||
hmap_init(&ts->proto_id_map, p, ts->proto_len); /* for proto ids. Value of proto id is the same as index of that proto in ptoto_state_table->attrs */
|
||||
hmap_init(&ts->channel_id_map, p, ts->channels_len);
|
||||
|
||||
/* Zeros should be reserved for easier undef manipulation */
|
||||
hmap_set(&ts->proto_id_map, 0);
|
||||
hmap_set(&ts->channel_id_map, 0);
|
||||
|
||||
ts->pool = p;
|
||||
ts->proto_states = mb_allocz(p, sizeof(ea_list *) * ts->proto_len);
|
||||
ts->channel_states = mb_allocz(p, sizeof(ea_list *) * ts->channels_len * 2);
|
||||
@ -2992,7 +2996,7 @@ struct proto_announce_state_deferred {
|
||||
struct proto *p;
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
proto_announce_state_locked(struct proto_state_table_private* ts, struct proto *p, ea_list *new_state)
|
||||
{
|
||||
ASSERT_DIE(birdloop_inside(p->loop));
|
||||
|
@ -442,9 +442,7 @@ struct proto_pending_update {
|
||||
ea_list *new, *old;
|
||||
};
|
||||
|
||||
void proto_announce_state_locked(struct proto_state_table_private *ts, struct proto *p, ea_list *attr);
|
||||
void proto_announce_state(struct proto *p, ea_list *attr);
|
||||
|
||||
void proto_announce_state_later_internal(struct proto *p, ea_list *attr);
|
||||
#if 0
|
||||
#define proto_announce_state_later(p, a) ( log(L_INFO "proto_announce_state_later(%s (%p), %p) at %s:%d", (p)->name, (p), (a), __FILE__, __LINE__), proto_announce_state_later_internal((p), (a)) )
|
||||
|
@ -1318,6 +1318,16 @@ struct ea_class ea_bgp_as4_out_conn = {
|
||||
.type = T_INT,
|
||||
};
|
||||
|
||||
struct ea_class ea_bgp_extended_next_hop = {
|
||||
.name = "bgp_extended_next_hop",
|
||||
.type = T_INT,
|
||||
};
|
||||
|
||||
struct ea_class ea_bgp_add_path_rx = {
|
||||
.name = "bgp_add_path_rx",
|
||||
.type = T_INT,
|
||||
};
|
||||
|
||||
void
|
||||
bgp_register_attrs(void)
|
||||
{
|
||||
@ -1340,6 +1350,7 @@ bgp_register_attrs(void)
|
||||
|
||||
EA_REGISTER_ALL(
|
||||
&ea_bgp_rem_id, &ea_bgp_rem_as, &ea_bgp_loc_as, &ea_bgp_rem_ip, &ea_bgp_peer_type, &ea_bgp_afi,
|
||||
&ea_bgp_extended_next_hop, &ea_bgp_add_path_rx,
|
||||
&ea_bgp_in_conn_local_open_msg, &ea_bgp_out_conn_local_open_msg, &ea_bgp_in_conn_remote_open_msg,
|
||||
&ea_bgp_out_conn_remote_open_msg, &ea_bgp_close_bmp, &ea_bgp_as4_session,
|
||||
&ea_bgp_state_startup, &ea_bgp_in_conn_state, &ea_bgp_out_conn_state,
|
||||
|
@ -801,6 +801,24 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
|
||||
c->c.ra_mode = RA_ACCEPTED;
|
||||
else
|
||||
c->c.ra_mode = RA_OPTIMAL;
|
||||
|
||||
ea_list *state = NULL;
|
||||
if (c->ext_next_hop)
|
||||
ea_set_attr_u32(&state, &ea_bgp_extended_next_hop, 0, 1);
|
||||
if (c->add_path_rx)
|
||||
ea_set_attr_u32(&state, &ea_bgp_add_path_rx, 0, 1);
|
||||
|
||||
if (state)
|
||||
{
|
||||
ea_list *sb = state;
|
||||
while (sb->next)
|
||||
sb = sb->next;
|
||||
|
||||
PST_LOCKED(ts) {
|
||||
sb->next = ea_free_later(ts->channel_states[c->c.id]);
|
||||
ts->channel_states[c->c.id] = ea_lookup_slow(state, 0, EALS_IN_TABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->afi_map = mb_alloc(p->p.pool, num * sizeof(u32));
|
||||
|
@ -508,7 +508,6 @@ struct bgp_export_state {
|
||||
};
|
||||
|
||||
struct bgp_write_state {
|
||||
struct bgp_proto *proto;
|
||||
struct bgp_ptx_private *ptx;
|
||||
struct linpool *pool;
|
||||
|
||||
@ -703,7 +702,7 @@ static inline struct bgp_proto *bgp_rte_proto(const rte *rte)
|
||||
SKIP_BACK(struct bgp_proto, p.sources, rte->src->owner) : NULL;
|
||||
}
|
||||
|
||||
byte * bgp_bmp_encode_rte(ea_list *c, struct bgp_proto *bgp_p, byte *buf, byte *end, const struct rte *new);
|
||||
byte * bgp_bmp_encode_rte(ea_list *channel_state, byte *buf, byte *end, const struct rte *new);
|
||||
|
||||
#define BGP_AIGP_METRIC 1
|
||||
#define BGP_AIGP_MAX U64(0xffffffffffffffff)
|
||||
@ -722,6 +721,7 @@ bgp_total_aigp_metric(const rte *e)
|
||||
extern struct ea_class ea_bgp_rem_id, ea_bgp_rem_as, ea_bgp_loc_as, ea_bgp_rem_ip, ea_bgp_peer_type, ea_bgp_afi,
|
||||
ea_bgp_in_conn_local_open_msg, ea_bgp_out_conn_local_open_msg, ea_bgp_in_conn_remote_open_msg,
|
||||
ea_bgp_out_conn_remote_open_msg, ea_bgp_close_bmp, ea_bgp_close_bmp_set, ea_bgp_as4_session,
|
||||
ea_bgp_extended_next_hop, ea_bgp_add_path_rx,
|
||||
ea_bgp_state_startup, ea_bgp_in_conn_state, ea_bgp_out_conn_state,
|
||||
ea_bgp_in_conn_sk, ea_bgp_out_conn_sk, ea_bgp_as4_out_conn, ea_bgp_as4_in_conn;
|
||||
|
||||
|
@ -2480,32 +2480,27 @@ bgp_create_mp_unreach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *
|
||||
#ifdef CONFIG_BMP
|
||||
|
||||
static byte *
|
||||
bgp_create_update_bmp(ea_list *channel_ea, struct bgp_proto *bgp_p, byte *buf, byte *end, struct bgp_bucket *buck, bool update)
|
||||
bgp_create_update_bmp(ea_list *channel_ea, byte *buf, byte *end, struct bgp_bucket *buck, bool update)
|
||||
{
|
||||
struct bgp_channel *c;
|
||||
u32 c_id = ea_get_int(channel_ea, &ea_channel_id, 0);
|
||||
BGP_WALK_CHANNELS(bgp_p, c)
|
||||
if (c->c.id == c_id)
|
||||
break;
|
||||
|
||||
byte *res = NULL;
|
||||
|
||||
struct bgp_caps *peer = bgp_p->conn->remote_caps;
|
||||
const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi);
|
||||
|
||||
struct bgp_ptx_private ptx = {
|
||||
.bmp = 1,
|
||||
.c = c,
|
||||
};
|
||||
|
||||
u32 afi = ea_get_int(channel_ea, &ea_bgp_afi, 0);
|
||||
ASSERT_DIE(afi);
|
||||
|
||||
const struct bgp_af_desc *desc = bgp_get_af_desc(afi);
|
||||
ASSERT_DIE(desc);
|
||||
|
||||
struct bgp_write_state s = {
|
||||
.proto = bgp_p,
|
||||
.ptx = &ptx,
|
||||
.pool = tmp_linpool,
|
||||
.mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop,
|
||||
.mp_reach = (afi != BGP_AF_IPV4) || ea_get_int(channel_ea, &ea_bgp_extended_next_hop, 0),
|
||||
.as4_session = 1,
|
||||
.add_path = c->add_path_rx,
|
||||
.mpls = c->desc->mpls,
|
||||
.add_path = ea_get_int(channel_ea, &ea_bgp_add_path_rx, 0),
|
||||
.mpls = desc->mpls,
|
||||
.ignore_non_bgp_attrs = 1,
|
||||
};
|
||||
|
||||
@ -2526,7 +2521,7 @@ bgp_create_update_bmp(ea_list *channel_ea, struct bgp_proto *bgp_p, byte *buf, b
|
||||
}
|
||||
|
||||
byte *
|
||||
bgp_bmp_encode_rte(ea_list *c, struct bgp_proto *bgp_p, byte *buf, byte *end, const struct rte *new)
|
||||
bgp_bmp_encode_rte(ea_list *c, byte *buf, byte *end, const struct rte *new)
|
||||
{
|
||||
uint ea_size = new->attrs ? (sizeof(ea_list) + new->attrs->count * sizeof(eattr)) : 0;
|
||||
uint prefix_size = sizeof(struct bgp_prefix) + new->net->length;
|
||||
@ -2548,7 +2543,7 @@ bgp_bmp_encode_rte(ea_list *c, struct bgp_proto *bgp_p, byte *buf, byte *end, co
|
||||
px->ni = NET_TO_INDEX(new->net);
|
||||
add_tail(&b->prefixes, &px->buck_node);
|
||||
|
||||
end = bgp_create_update_bmp(c, bgp_p, buf, end, b, !!new->attrs);
|
||||
end = bgp_create_update_bmp(c, buf, end, b, !!new->attrs);
|
||||
|
||||
lp_restore(tmp_linpool, tmpp);
|
||||
|
||||
@ -2577,7 +2572,6 @@ again:
|
||||
|
||||
/* Initialize write state */
|
||||
struct bgp_write_state s = {
|
||||
.proto = p,
|
||||
.ptx = ptx,
|
||||
.pool = tmp_linpool,
|
||||
.mp_reach = (c->afi != BGP_AF_IPV4) || c->ext_next_hop,
|
||||
|
@ -1,4 +1,4 @@
|
||||
src := bmp.c map.c
|
||||
src := bmp.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
$(cf-local)
|
||||
|
311
proto/bmp/bmp.c
311
proto/bmp/bmp.c
@ -29,7 +29,6 @@
|
||||
*/
|
||||
|
||||
#include "proto/bmp/bmp.h"
|
||||
#include "proto/bmp/map.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
@ -57,17 +56,15 @@
|
||||
#include "nest/iface.h"
|
||||
#include "nest/route.h"
|
||||
|
||||
#define HASH_PEER_KEY(n) n->bgp
|
||||
#define HASH_PEER_KEY(n) n->info.proto_id
|
||||
#define HASH_PEER_NEXT(n) n->next
|
||||
#define HASH_PEER_EQ(b1,b2) b1 == b2
|
||||
#define HASH_PEER_FN(b) ptr_hash(b)
|
||||
#define HASH_PEER_FN(b) u32_hash(b)
|
||||
|
||||
#define BMP_STREAM_KEY_POLICY 0x100
|
||||
|
||||
#define HASH_STREAM_KEY(n) n->bgp, n->key
|
||||
#define HASH_STREAM_KEY(n) &n->info
|
||||
#define HASH_STREAM_NEXT(n) n->next
|
||||
#define HASH_STREAM_EQ(b1,k1,b2,k2) b1 == b2 && k1 == k2
|
||||
#define HASH_STREAM_FN(b,k) ptr_hash(b) ^ u32_hash(k)
|
||||
#define HASH_STREAM_EQ(k1,k2) ((k1)->channel_id == (k2)->channel_id) && ((k1)->afi == (k2)->afi) && ((k1)->mode == (k2)->mode)
|
||||
#define HASH_STREAM_FN(k) u32_hash((k)->channel_id) ^ u32_hash((k)->afi) ^ u32_hash((k)->mode)
|
||||
|
||||
#define HASH_TABLE_KEY(n) n->table
|
||||
#define HASH_TABLE_NEXT(n) n->next
|
||||
@ -107,7 +104,7 @@ struct bmp_peer_hdr_info {
|
||||
u32 as;
|
||||
u32 id;
|
||||
bool global;
|
||||
bool policy;
|
||||
enum bmp_stream_policy policy;
|
||||
bool no_as4;
|
||||
btime timestamp;
|
||||
};
|
||||
@ -220,8 +217,6 @@ static void
|
||||
bmp_send_peer_up_notif_msg(struct bmp_proto *p, ea_list *bgp,
|
||||
const adata *tx_data, const adata *rx_data, struct bgp_conn_sk_ad *sk);
|
||||
|
||||
static void bmp_route_monitor_end_of_rib(struct bmp_proto *p, struct bmp_stream *bs);
|
||||
|
||||
// Stores TX data
|
||||
struct bmp_tx_buffer {
|
||||
struct bmp_tx_buffer *next;
|
||||
@ -463,7 +458,7 @@ bmp_put_per_peer_hdr(buffer *stream, const struct bmp_peer_hdr_info *peer)
|
||||
|
||||
u8 peer_flags =
|
||||
(ipa_is_ip6(peer->address) ? BMP_PEER_FLAG_V_IPV6 : 0) |
|
||||
(peer->policy ? BMP_PEER_FLAG_L_POLICY : 0) |
|
||||
((peer->policy == BMP_STREAM_POST_POLICY) ? BMP_PEER_FLAG_L_POLICY : 0) |
|
||||
(peer->no_as4 ? BMP_PEER_FLAG_A_NO_AS4 : 0);
|
||||
|
||||
u32 ts_sec = peer->timestamp TO_S;
|
||||
@ -601,21 +596,13 @@ bmp_get_table(struct bmp_proto *p, rtable *tab)
|
||||
* BMP streams
|
||||
*/
|
||||
|
||||
static inline u32 bmp_stream_key(u32 afi, bool policy)
|
||||
{ return afi ^ (policy ? BMP_STREAM_KEY_POLICY : 0); }
|
||||
|
||||
static inline bool bmp_stream_policy(struct bmp_stream *bs)
|
||||
{ return !!(bs->key & BMP_STREAM_KEY_POLICY); }
|
||||
|
||||
static struct bmp_stream *
|
||||
bmp_find_stream(struct bmp_proto *p, const struct bgp_proto *bgp, u32 afi, bool policy)
|
||||
bmp_find_stream(struct bmp_proto *p, struct bmp_stream_info *bsi)
|
||||
{
|
||||
ea_list *bgp_attr = proto_get_state(bgp->p.id);
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
/* Is there a stream? */
|
||||
struct bmp_stream *s = HASH_FIND(p->stream_map, HASH_STREAM, bgp_attr, bmp_stream_key(afi, policy));
|
||||
struct bmp_stream *s = HASH_FIND(p->stream_map, HASH_STREAM, bsi);
|
||||
if (s)
|
||||
return s;
|
||||
|
||||
@ -632,22 +619,15 @@ bmp_find_stream(struct bmp_proto *p, const struct bgp_proto *bgp, u32 afi, bool
|
||||
}
|
||||
|
||||
static struct bmp_stream *
|
||||
bmp_add_stream(struct bmp_proto *p, struct bmp_peer *bp, u32 afi, bool policy, rtable *tab, ea_list *sender, int in_pre_policy)
|
||||
bmp_add_stream(struct bmp_proto *p, struct bmp_peer *bp, struct bmp_table *bt, const struct bmp_stream_info *bsi)
|
||||
{
|
||||
struct bmp_stream *bs = mb_allocz(p->p.pool, sizeof(struct bmp_stream));
|
||||
bs->bgp = bp->bgp;
|
||||
bs->key = bmp_stream_key(afi, policy);
|
||||
bs->info = *bsi;
|
||||
|
||||
bmp_table_stream_add_tail(&bt->streams, bs);
|
||||
bmp_peer_stream_add_tail(&bp->streams, bs);
|
||||
HASH_INSERT(p->stream_map, HASH_STREAM, bs);
|
||||
|
||||
struct bmp_table *bt = bmp_get_table(p, tab);
|
||||
bmp_table_stream_add_tail(&bt->streams, bs);
|
||||
|
||||
bs->sender = sender;
|
||||
bs->sync = false;
|
||||
bs->in_pre_policy = in_pre_policy;
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@ -671,58 +651,63 @@ bmp_remove_stream(struct bmp_proto *p, struct bmp_stream *bs)
|
||||
*/
|
||||
|
||||
static struct bmp_peer *
|
||||
bmp_find_peer(struct bmp_proto *p, ea_list *bgp_attr)
|
||||
bmp_find_peer(struct bmp_proto *p, const struct bmp_peer_info *bpi)
|
||||
{
|
||||
return HASH_FIND(p->peer_map, HASH_PEER, bgp_attr);
|
||||
return HASH_FIND(p->peer_map, HASH_PEER, bpi->proto_id);
|
||||
}
|
||||
|
||||
static struct bmp_peer *
|
||||
bmp_add_peer(struct bmp_proto *p, ea_list *bgp_attr)
|
||||
bmp_add_peer(struct bmp_proto *p, struct bmp_peer_info *bpi, ea_list **cached_channels)
|
||||
{
|
||||
struct bmp_peer *bp;
|
||||
if (DG_IS_LOCKED(p->p.pool->domain))
|
||||
bp = mb_allocz(p->p.pool, sizeof(struct bmp_peer));
|
||||
else
|
||||
{
|
||||
DG_LOCK(p->p.pool->domain);
|
||||
bp = mb_allocz(p->p.pool, sizeof(struct bmp_peer));
|
||||
DG_UNLOCK(p->p.pool->domain);
|
||||
}
|
||||
bp->bgp = bgp_attr;
|
||||
|
||||
bp->streams = (TLIST_LIST(bmp_peer_stream)) {};
|
||||
|
||||
struct bmp_peer *bp = mb_allocz(p->p.pool, sizeof(struct bmp_peer));
|
||||
bp->info = *bpi;
|
||||
ea_ref(bpi->proto_state);
|
||||
HASH_INSERT(p->peer_map, HASH_PEER, bp);
|
||||
|
||||
const adata *channels_adata = ea_get_adata(bgp_attr, &ea_proto_channel_list);
|
||||
int id_count = channels_adata->length / sizeof(u32);
|
||||
u32 *chann_ids = (u32 *) channels_adata->data;
|
||||
const adata *channels_adata = ea_get_adata(bpi->proto_state, &ea_proto_channel_list);
|
||||
|
||||
for (int i = 0; i < id_count; i++)
|
||||
if (!cached_channels)
|
||||
{
|
||||
ea_list *chan_attr;
|
||||
PST_LOCKED(ts)
|
||||
chan_attr = ts->channel_states[chann_ids[i]];
|
||||
u32 max_channel_id;
|
||||
ASSERT_DIE(int_set_max(channels_adata, &max_channel_id));
|
||||
cached_channels = tmp_alloc((max_channel_id + 1) * sizeof(ea_list *));
|
||||
|
||||
if (chan_attr == NULL)
|
||||
PST_LOCKED(ts)
|
||||
for (u32 pos = 0, val; int_set_walk(channels_adata, &pos, &val); )
|
||||
{
|
||||
ASSERT_DIE(val < ts->channels_len);
|
||||
cached_channels[val] = ts->channel_states[val] ? ea_ref_tmp(ts->channel_states[val]) : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct bmp_stream_info bsi;
|
||||
for (u32 pos = 0; int_set_walk(channels_adata, &pos, &bsi.channel_id); )
|
||||
{
|
||||
if (!(bsi.channel_state = cached_channels[bsi.channel_id]))
|
||||
continue;
|
||||
|
||||
rtable *ch_table = (rtable *) ea_get_ptr(chan_attr, &ea_rtable, 0);
|
||||
int in_keep = ea_get_int(chan_attr, &ea_in_keep, 0);
|
||||
bsi.afi = ea_get_int(bsi.channel_state, &ea_bgp_afi, 0);
|
||||
bsi.channel_name = ea_get_adata(bsi.channel_state, &ea_name)->data;
|
||||
|
||||
if (p->monitoring_rib.in_pre_policy && ch_table)
|
||||
struct bmp_table *bt = bmp_get_table(p, ea_get_ptr(bsi.channel_state, &ea_rtable, NULL));
|
||||
|
||||
if (p->monitoring_rib.in_pre_policy)
|
||||
{
|
||||
if (in_keep == RIK_PREFILTER)
|
||||
bmp_add_stream(p, bp, ea_get_int(chan_attr, &ea_bgp_afi, 0), false, ch_table, chan_attr, 1);
|
||||
bsi.mode = BMP_STREAM_PRE_POLICY;
|
||||
if ((ea_get_int(bsi.channel_state, &ea_in_keep, 0) & RIK_PREFILTER) == RIK_PREFILTER)
|
||||
bmp_add_stream(p, bp, bt, &bsi);
|
||||
else
|
||||
log(L_WARN "%s: Failed to request pre-policy for %s.%s, import table disabled",
|
||||
p->p.name,
|
||||
ea_get_adata(bgp_attr, &ea_name)->data,
|
||||
ea_get_adata(chan_attr, &ea_name)->data);
|
||||
bpi->proto_name,
|
||||
bsi.channel_name);
|
||||
}
|
||||
|
||||
if (p->monitoring_rib.in_post_policy && ch_table)
|
||||
bmp_add_stream(p, bp, ea_get_int(chan_attr, &ea_bgp_afi, 0), true, ch_table, chan_attr, 0);
|
||||
if (p->monitoring_rib.in_post_policy)
|
||||
{
|
||||
bsi.mode = BMP_STREAM_POST_POLICY;
|
||||
bmp_add_stream(p, bp, bt, &bsi);
|
||||
}
|
||||
}
|
||||
|
||||
return bp;
|
||||
@ -735,57 +720,62 @@ bmp_remove_peer(struct bmp_proto *p, struct bmp_peer *bp)
|
||||
bmp_remove_stream(p, bs);
|
||||
|
||||
HASH_REMOVE(p->peer_map, HASH_PEER, bp);
|
||||
ea_free_later(bp->info.proto_state);
|
||||
|
||||
mb_free(bp);
|
||||
}
|
||||
|
||||
static struct bmp_peer *
|
||||
bmp_peer_up_(struct bmp_proto *p, ea_list *bgp_attr,
|
||||
bmp_peer_up_(struct bmp_proto *p, struct bmp_peer_info *bpi, ea_list **cached_channels,
|
||||
const adata *tx_open_msg, const adata *rx_open_msg,
|
||||
struct bgp_conn_sk_ad *sk)
|
||||
{
|
||||
if (!p->started)
|
||||
return NULL;
|
||||
|
||||
struct bmp_peer *bp = bmp_find_peer(p, bgp_attr);
|
||||
struct bmp_peer *bp = bmp_find_peer(p, bpi);
|
||||
if (bp)
|
||||
{
|
||||
/* Update the locally cached proto_state */
|
||||
ea_free_later(bp->info.proto_state);
|
||||
bp->info.proto_state = ea_ref(bpi->proto_state);
|
||||
return bp;
|
||||
}
|
||||
|
||||
const char *name = ea_get_adata(bgp_attr, &ea_name)->data;
|
||||
TRACE(D_STATES, "Peer up for %s", name);
|
||||
TRACE(D_STATES, "Peer up for %s", bpi->proto_name);
|
||||
|
||||
bp = bmp_add_peer(p, bgp_attr);
|
||||
bp = bmp_add_peer(p, bpi, cached_channels);
|
||||
|
||||
bmp_send_peer_up_notif_msg(p, bgp_attr, tx_open_msg, rx_open_msg, sk);
|
||||
bmp_send_peer_up_notif_msg(p, bpi->proto_state, tx_open_msg, rx_open_msg, sk);
|
||||
return bp;
|
||||
}
|
||||
|
||||
static struct bmp_peer *
|
||||
bmp_peer_up_inout(struct bmp_proto *p, ea_list *bgp_attr)
|
||||
bmp_peer_up_inout(struct bmp_proto *p, struct bmp_peer_info *bpi, ea_list **cached_channels)
|
||||
{
|
||||
int in_state = ea_get_int(bgp_attr, &ea_bgp_in_conn_state, 0);
|
||||
int out_state = ea_get_int(bgp_attr, &ea_bgp_out_conn_state, 0);
|
||||
int in_state = ea_get_int(bpi->proto_state, &ea_bgp_in_conn_state, 0);
|
||||
int out_state = ea_get_int(bpi->proto_state, &ea_bgp_out_conn_state, 0);
|
||||
|
||||
if (in_state == BS_ESTABLISHED)
|
||||
{
|
||||
ASSERT_DIE(out_state != BS_ESTABLISHED);
|
||||
|
||||
const adata *loc_open = ea_get_adata(bgp_attr, &ea_bgp_in_conn_local_open_msg);
|
||||
const adata *rem_open = ea_get_adata(bgp_attr, &ea_bgp_in_conn_remote_open_msg);
|
||||
SKIP_BACK_DECLARE(struct bgp_conn_sk_ad, sk, ad, ea_get_adata(bgp_attr, &ea_bgp_in_conn_sk));
|
||||
const adata *loc_open = ea_get_adata(bpi->proto_state, &ea_bgp_in_conn_local_open_msg);
|
||||
const adata *rem_open = ea_get_adata(bpi->proto_state, &ea_bgp_in_conn_remote_open_msg);
|
||||
SKIP_BACK_DECLARE(struct bgp_conn_sk_ad, sk, ad, ea_get_adata(bpi->proto_state, &ea_bgp_in_conn_sk));
|
||||
|
||||
ASSERT_DIE(loc_open && rem_open);
|
||||
return bmp_peer_up_(p, bgp_attr, loc_open, rem_open, sk);
|
||||
return bmp_peer_up_(p, bpi, cached_channels, loc_open, rem_open, sk);
|
||||
}
|
||||
|
||||
if (out_state == BS_ESTABLISHED)
|
||||
{
|
||||
const adata *loc_open = ea_get_adata(bgp_attr, &ea_bgp_out_conn_local_open_msg);
|
||||
const adata *rem_open = ea_get_adata(bgp_attr, &ea_bgp_out_conn_remote_open_msg);
|
||||
SKIP_BACK_DECLARE(struct bgp_conn_sk_ad, sk, ad, ea_get_adata(bgp_attr, &ea_bgp_out_conn_sk));
|
||||
const adata *loc_open = ea_get_adata(bpi->proto_state, &ea_bgp_out_conn_local_open_msg);
|
||||
const adata *rem_open = ea_get_adata(bpi->proto_state, &ea_bgp_out_conn_remote_open_msg);
|
||||
SKIP_BACK_DECLARE(struct bgp_conn_sk_ad, sk, ad, ea_get_adata(bpi->proto_state, &ea_bgp_out_conn_sk));
|
||||
|
||||
ASSERT_DIE(loc_open && rem_open);
|
||||
return bmp_peer_up_(p, bgp_attr, loc_open, rem_open, sk);
|
||||
return bmp_peer_up_(p, bpi, cached_channels, loc_open, rem_open, sk);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -825,19 +815,14 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, ea_list *bgp,
|
||||
}
|
||||
|
||||
static void
|
||||
bmp_route_monitor_notify(struct bmp_proto *p, struct bgp_proto *bgp_p, u32 afi, bool policy, const rte *new, ea_list *old)
|
||||
bmp_route_monitor_notify(struct bmp_proto *p, struct bmp_peer *bp, struct bmp_stream *bs, const rte *new, ea_list *old)
|
||||
{
|
||||
/* Idempotent update */
|
||||
if ((old == new->attrs) || old && new->attrs && ea_same(old, new->attrs))
|
||||
return;
|
||||
|
||||
/* No stream, probably flushed already */
|
||||
struct bmp_stream *bs = bmp_find_stream(p, bgp_p, afi, policy);
|
||||
if (!bs)
|
||||
return;
|
||||
|
||||
ea_list *bgp = bs->bgp;
|
||||
ea_list *c = bs->sender;
|
||||
ea_list *bgp = bp->info.proto_state;
|
||||
ea_list *c = bs->info.channel_state;
|
||||
|
||||
btime delta_t = new ? current_time() - new->lastmod : 0;
|
||||
|
||||
@ -846,7 +831,7 @@ bmp_route_monitor_notify(struct bmp_proto *p, struct bgp_proto *bgp_p, u32 afi,
|
||||
.as = ea_get_int(bgp, &ea_bgp_rem_as, 0),
|
||||
.id = ea_get_int(bgp, &ea_bgp_rem_id, 0),
|
||||
.global = bmp_is_peer_global_instance(bgp),
|
||||
.policy = bmp_stream_policy(bs),
|
||||
.policy = bs->info.mode,
|
||||
.timestamp = current_real_time() - delta_t,
|
||||
};
|
||||
|
||||
@ -855,7 +840,7 @@ bmp_route_monitor_notify(struct bmp_proto *p, struct bgp_proto *bgp_p, u32 afi,
|
||||
bmp_put_per_peer_hdr(&msg, &peer);
|
||||
|
||||
bmp_buffer_need(&msg, BGP_MAX_EXT_MSG_LENGTH);
|
||||
byte *pos = bgp_bmp_encode_rte(c, bgp_p, msg.pos + BGP_HEADER_LENGTH, msg.end, new);
|
||||
byte *pos = bgp_bmp_encode_rte(c, msg.pos + BGP_HEADER_LENGTH, msg.end, new);
|
||||
if (!pos)
|
||||
{
|
||||
log(L_WARN "%s: Cannot encode update for %N", p->p.name, new->net);
|
||||
@ -869,17 +854,17 @@ bmp_route_monitor_notify(struct bmp_proto *p, struct bgp_proto *bgp_p, u32 afi,
|
||||
}
|
||||
|
||||
static void
|
||||
bmp_route_monitor_end_of_rib(struct bmp_proto *p, struct bmp_stream *bs)
|
||||
bmp_route_monitor_end_of_rib(struct bmp_proto *p, struct bmp_peer *bp, struct bmp_stream *bs)
|
||||
{
|
||||
ea_list *bgp = bs->bgp;
|
||||
ea_list *c = bs->sender;
|
||||
ea_list *bgp = bp->info.proto_state;
|
||||
ea_list *c = bs->info.channel_state;
|
||||
|
||||
struct bmp_peer_hdr_info peer = {
|
||||
.address = ea_get_ip(bgp, &ea_bgp_rem_ip, IPA_NONE),
|
||||
.as = ea_get_int(bgp, &ea_bgp_rem_as, 0),
|
||||
.id = ea_get_int(bgp, &ea_bgp_rem_id, 0),
|
||||
.global = bmp_is_peer_global_instance(bgp),
|
||||
.policy = bmp_stream_policy(bs),
|
||||
.policy = bs->info.mode,
|
||||
.timestamp = current_real_time(),
|
||||
};
|
||||
|
||||
@ -920,7 +905,7 @@ bmp_send_peer_down_notif_msg(struct bmp_proto *p, ea_list *bgp,
|
||||
.as = ea_get_int(bgp, &ea_bgp_rem_as, 0),
|
||||
.id = ea_get_int(bgp, &ea_bgp_rem_id, 0),
|
||||
.global = bmp_is_peer_global_instance(bgp),
|
||||
.policy = false, // Hardcoded pre-policy Adj-RIB-In
|
||||
.policy = BMP_STREAM_PRE_POLICY, // Hardcoded pre-policy Adj-RIB-In
|
||||
.no_as4 = !as4_session,
|
||||
.timestamp = 0, // No timestamp provided
|
||||
};
|
||||
@ -931,16 +916,16 @@ bmp_send_peer_down_notif_msg(struct bmp_proto *p, ea_list *bgp,
|
||||
}
|
||||
|
||||
static void
|
||||
bmp_peer_down_(struct bmp_proto *p, ea_list *bgp, struct bgp_session_close_ad *bscad)
|
||||
bmp_peer_down_(struct bmp_proto *p, struct bmp_peer_info *bpi, struct bgp_session_close_ad *bscad)
|
||||
{
|
||||
if (!p->started)
|
||||
return;
|
||||
|
||||
struct bmp_peer *bp = bmp_find_peer(p, bgp);
|
||||
struct bmp_peer *bp = bmp_find_peer(p, bpi);
|
||||
if (!bp)
|
||||
return;
|
||||
|
||||
TRACE(D_STATES, "Peer down for %s", ea_find(bgp, &ea_name)->u.ad->data);
|
||||
TRACE(D_STATES, "Peer down for %s", bpi->proto_name);
|
||||
|
||||
struct bmp_peer_down_info info = {
|
||||
.err_code = bscad->notify_code,
|
||||
@ -967,7 +952,7 @@ bmp_peer_down_(struct bmp_proto *p, ea_list *bgp, struct bgp_session_close_ad *b
|
||||
break;
|
||||
}
|
||||
|
||||
bmp_send_peer_down_notif_msg(p, bgp, &info);
|
||||
bmp_send_peer_down_notif_msg(p, bpi->proto_state, &info);
|
||||
|
||||
bmp_remove_peer(p, bp);
|
||||
}
|
||||
@ -999,26 +984,39 @@ bmp_split_policy(struct bmp_proto *p, const rte *new, const rte *old)
|
||||
{
|
||||
rte loc = *(new ?: old);
|
||||
|
||||
struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, loc.src->owner);
|
||||
struct bgp_proto *bgp = (struct bgp_proto *) rte_proto;
|
||||
struct bgp_channel *src_ch = SKIP_BACK(struct bgp_channel, c.in_req, loc.sender->req);
|
||||
|
||||
/* Ignore piped routes */
|
||||
if (src_ch->c.proto != rte_proto)
|
||||
if (loc.generation)
|
||||
return;
|
||||
|
||||
/* Ignore non-BGP routes */
|
||||
if (rte_proto->proto != &proto_bgp)
|
||||
if (rt_get_source_attr(&loc) != RTS_BGP)
|
||||
return;
|
||||
|
||||
/* Get the protocol and channel information. Here we _can_ access
|
||||
* the protocol and channel structures but only to read the ID. */
|
||||
SKIP_BACK_DECLARE(struct channel, c, in_req, loc.sender->req);
|
||||
struct bmp_peer_info bpi = {
|
||||
.proto_id = c->proto->id,
|
||||
};
|
||||
struct bmp_peer *bp = bmp_find_peer(p, &bpi);
|
||||
|
||||
struct bmp_stream_info bsi = {
|
||||
.channel_id = c->id,
|
||||
};
|
||||
|
||||
/* Checking the pre policy */
|
||||
if (p->monitoring_rib.in_pre_policy)
|
||||
{
|
||||
/* Compute the pre policy attributes */
|
||||
/* Compute the pre policy route attributes */
|
||||
loc.attrs = new ? ea_strip_to(new->attrs, BIT32_ALL(EALS_PREIMPORT)) : NULL;
|
||||
ea_list *old_attrs = old ? ea_strip_to(old->attrs, BIT32_ALL(EALS_PREIMPORT)) : NULL;
|
||||
|
||||
bmp_route_monitor_notify(p, bgp, src_ch->afi, false, &loc, old_attrs);
|
||||
bsi.mode = BMP_STREAM_PRE_POLICY;
|
||||
struct bmp_stream *bs = bmp_find_stream(p, &bsi);
|
||||
if (!bs)
|
||||
return;
|
||||
|
||||
bmp_route_monitor_notify(p, bp, bs, &loc, old_attrs);
|
||||
}
|
||||
|
||||
/* Checking the post policy */
|
||||
@ -1028,7 +1026,12 @@ bmp_split_policy(struct bmp_proto *p, const rte *new, const rte *old)
|
||||
loc.attrs = new ? ea_normalize(new->attrs, 0) : NULL;
|
||||
ea_list *old_attrs = old ? ea_normalize(old->attrs, 0) : NULL;
|
||||
|
||||
bmp_route_monitor_notify(p, bgp, src_ch->afi, true, &loc, old_attrs);
|
||||
bsi.mode = BMP_STREAM_POST_POLICY;
|
||||
struct bmp_stream *bs = bmp_find_stream(p, &bsi);
|
||||
if (!bs)
|
||||
return;
|
||||
|
||||
bmp_route_monitor_notify(p, bp, bs, &loc, old_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1075,19 +1078,17 @@ bmp_feed_end(struct rt_export_request *req)
|
||||
* Unsynced streams are added in one moment during BMP session establishment,
|
||||
* therefore we can assume that all unsynced streams (for given channel)
|
||||
* already received full feed now and are synced.
|
||||
*
|
||||
* TODO: Use more efficent way to find bmp_stream from bmp_table
|
||||
*/
|
||||
|
||||
HASH_WALK(p->stream_map, next, bs)
|
||||
WALK_TLIST(bmp_table_stream, bs, &bt->streams)
|
||||
{
|
||||
if ((bmp_table_stream_enlisted(bs) == &bt->streams) && !bs->sync)
|
||||
if (!bs->sync)
|
||||
{
|
||||
bmp_route_monitor_end_of_rib(p, bs);
|
||||
SKIP_BACK_DECLARE(struct bmp_peer, bp, streams, bmp_peer_stream_enlisted(bs));
|
||||
bmp_route_monitor_end_of_rib(p, bp, bs);
|
||||
bs->sync = true;
|
||||
}
|
||||
}
|
||||
HASH_WALK_END;
|
||||
}
|
||||
|
||||
|
||||
@ -1114,11 +1115,6 @@ bmp_startup(struct bmp_proto *p)
|
||||
bmp_init_msg_serialize(&payload, p->sys_descr, p->sys_name);
|
||||
bmp_schedule_tx_packet(p, &payload);
|
||||
|
||||
/* Send Peer Up messages */
|
||||
u32 length;
|
||||
PST_LOCKED(ts) /* The size of protos field will never decrease, the inconsistency caused by growing is not important */
|
||||
length = ts->proto_len;
|
||||
|
||||
/* Subscribe to protocol state changes */
|
||||
p->proto_state_reader = (struct lfjour_recipient) {
|
||||
.event = &p->proto_state_changed,
|
||||
@ -1133,19 +1129,55 @@ bmp_startup(struct bmp_proto *p)
|
||||
proto_states_subscribe(&p->proto_state_reader);
|
||||
|
||||
/* Load protocol states */
|
||||
for (u32 i = 0; i < length; i++)
|
||||
u32 max_proto_id, max_channel_id;
|
||||
PST_LOCKED(tp)
|
||||
{
|
||||
ea_list *proto_attr = proto_get_state(i);
|
||||
if (proto_attr == NULL)
|
||||
continue;
|
||||
max_proto_id = tp->proto_len;
|
||||
max_channel_id = tp->channels_len;
|
||||
}
|
||||
|
||||
struct protocol *proto = (struct protocol *) ea_get_ptr(proto_attr, &ea_protocol_type, 0);
|
||||
const int state = ea_get_int(proto_attr, &ea_state, 0);
|
||||
/* We can unlock here as the states array never shrinks
|
||||
* and growing will be resolved by reading the journal. */
|
||||
|
||||
if (proto != &proto_bgp || state != PS_UP)
|
||||
continue;
|
||||
u32 *protos_picked = tmp_allocz(BIRD_ALIGN(max_proto_id, 32) * sizeof *protos_picked);
|
||||
|
||||
bmp_peer_up_inout(p, proto_attr);
|
||||
/* Copy relevant protocol states */
|
||||
ea_list **pst = tmp_alloc(max_proto_id * sizeof *pst);
|
||||
uint *proto_ids = tmp_alloc(max_proto_id * sizeof *proto_ids);
|
||||
u32 pst_count = 0;
|
||||
|
||||
ea_list **cst = tmp_alloc(max_channel_id * sizeof *cst);
|
||||
|
||||
PST_LOCKED(ts)
|
||||
{
|
||||
for (u32 i = 0; i < max_proto_id; i++)
|
||||
if (ea_get_ptr(ts->proto_states[i], &ea_protocol_type, NULL) == &proto_bgp)
|
||||
{
|
||||
BIT32_SET(protos_picked, i);
|
||||
pst[pst_count] = ea_ref_tmp(ts->proto_states[i]);
|
||||
proto_ids[pst_count] = i;
|
||||
pst_count++;
|
||||
}
|
||||
for (u32 i = 0; i < max_channel_id; i++)
|
||||
{
|
||||
u32 proto_id = ea_get_int(ts->channel_states[i], &ea_proto_id, 0);
|
||||
if (BIT32_TEST(protos_picked, proto_id))
|
||||
cst[i] = ea_ref_tmp(ts->channel_states[i]);
|
||||
else
|
||||
cst[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send Peer Up messages */
|
||||
for (u32 i = 0; i < pst_count; i++)
|
||||
{
|
||||
struct bmp_peer_info bpi = {
|
||||
.proto_state = pst[i],
|
||||
.proto_id = proto_ids[i],
|
||||
.proto_name = ea_get_adata(pst[i], &ea_name)->data,
|
||||
};
|
||||
|
||||
bmp_peer_up_inout(p, &bpi, cst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1331,11 +1363,18 @@ bmp_postconfig(struct proto_config *CF)
|
||||
static void
|
||||
bmp_process_proto_state_change(struct bmp_proto *p, struct lfjour_item *last_up)
|
||||
{
|
||||
struct proto_pending_update *ppu = SKIP_BACK(struct proto_pending_update, li, last_up);
|
||||
if (!ppu)
|
||||
if (!last_up)
|
||||
return;
|
||||
|
||||
struct bmp_peer *bp = bmp_peer_up_inout(p, ppu->new);
|
||||
SKIP_BACK_DECLARE(struct proto_pending_update, ppu, li, last_up);
|
||||
|
||||
struct bmp_peer_info bpi = {
|
||||
.proto_state = ppu->new,
|
||||
.proto_id = ea_get_int(ppu->new, &ea_proto_id, 0),
|
||||
.proto_name = ea_get_adata(ppu->new, &ea_name)->data,
|
||||
};
|
||||
|
||||
struct bmp_peer *bp = bmp_peer_up_inout(p, &bpi, NULL);
|
||||
if (bp)
|
||||
{
|
||||
/*
|
||||
@ -1345,7 +1384,7 @@ bmp_process_proto_state_change(struct bmp_proto *p, struct lfjour_item *last_up)
|
||||
*/
|
||||
WALK_TLIST(bmp_peer_stream, bs, &bp->streams)
|
||||
{
|
||||
bmp_route_monitor_end_of_rib(p, bs);
|
||||
bmp_route_monitor_end_of_rib(p, bp, bs);
|
||||
bs->sync = true;
|
||||
}
|
||||
|
||||
@ -1355,7 +1394,7 @@ bmp_process_proto_state_change(struct bmp_proto *p, struct lfjour_item *last_up)
|
||||
/* This was not a peer-up notification. It may be peer down tho. */
|
||||
const adata *bscad = ea_get_adata(ppu->new, &ea_bgp_close_bmp);
|
||||
if (bscad)
|
||||
bmp_peer_down_(p, ppu->new, SKIP_BACK(struct bgp_session_close_ad, ad, bscad));
|
||||
bmp_peer_down_(p, &bpi, SKIP_BACK(struct bgp_session_close_ad, ad, bscad));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "lib/hash.h"
|
||||
#include "lib/socket.h"
|
||||
#include "proto/bgp/bgp.h"
|
||||
#include "proto/bmp/map.h"
|
||||
|
||||
// Max length of MIB-II description object
|
||||
#define MIB_II_STR_LEN 255
|
||||
@ -53,10 +52,6 @@ struct bmp_config {
|
||||
uint tx_pending_limit; // Maximum on pending TX buffer count
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
struct bgp_proto;
|
||||
struct bmp_proto;
|
||||
|
||||
struct bmp_proto {
|
||||
struct proto p; // Parent proto
|
||||
const struct bmp_config *cf; // Shortcut to BMP configuration
|
||||
@ -75,7 +70,6 @@ struct bmp_proto {
|
||||
u16 station_port; // Monitoring station TCP port
|
||||
struct monitoring_rib monitoring_rib;
|
||||
// Below fields are for internal use
|
||||
// struct bmp_peer_map bgp_peers; // Stores 'bgp_proto' structure per BGP peer
|
||||
struct bmp_tx_buffer *tx_pending;// This buffer waits for socket to flush
|
||||
struct bmp_tx_buffer *tx_last; // This buffer is the last to flush
|
||||
uint tx_pending_count; // How many buffers waiting for flush
|
||||
@ -95,13 +89,19 @@ struct bmp_proto {
|
||||
struct bmp_stream {
|
||||
TLIST_NODE(bmp_peer_stream, struct bmp_stream) peer_node;
|
||||
TLIST_NODE(bmp_table_stream, struct bmp_stream) table_node;
|
||||
ea_list *bgp;
|
||||
u32 key;
|
||||
bool sync;
|
||||
bool shutting_down;
|
||||
struct bmp_stream *next;
|
||||
ea_list *sender;
|
||||
int in_pre_policy;
|
||||
struct bmp_stream_info {
|
||||
u32 channel_id;
|
||||
ea_list *channel_state;
|
||||
const char *channel_name;
|
||||
u32 afi;
|
||||
enum bmp_stream_policy {
|
||||
BMP_STREAM_PRE_POLICY = 1,
|
||||
BMP_STREAM_POST_POLICY,
|
||||
} mode;
|
||||
} info;
|
||||
};
|
||||
|
||||
#define TLIST_PREFIX bmp_peer_stream
|
||||
@ -119,8 +119,12 @@ struct bmp_stream {
|
||||
#include "lib/tlists.h"
|
||||
|
||||
struct bmp_peer {
|
||||
ea_list *bgp;
|
||||
struct bmp_peer *next;
|
||||
struct bmp_peer_info {
|
||||
u32 proto_id;
|
||||
ea_list *proto_state;
|
||||
const char *proto_name;
|
||||
} info;
|
||||
TLIST_LIST(bmp_peer_stream) streams;
|
||||
};
|
||||
|
||||
@ -134,30 +138,4 @@ struct bmp_table {
|
||||
TLIST_LIST(bmp_table_stream) streams;
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_BMP
|
||||
|
||||
/**
|
||||
* bmp_peer_up - send notification that BGP peer connection is established
|
||||
*/
|
||||
void
|
||||
bmp_peer_up(struct ea_list *bgp,
|
||||
const byte *tx_open_msg, uint tx_open_length,
|
||||
const byte *rx_open_msg, uint rx_open_length);
|
||||
|
||||
/**
|
||||
* bmp_peer_down - send notification that BGP peer connection is not in
|
||||
* established state
|
||||
*/
|
||||
void
|
||||
bmp_peer_down(const struct bgp_proto *bgp, int err_class, int code, int subcode, const byte *data, int length);
|
||||
|
||||
|
||||
#else /* BMP build disabled */
|
||||
|
||||
static inline void bmp_peer_up(struct bgp_proto *bgp UNUSED, const byte *tx_open_msg UNUSED, uint tx_open_length UNUSED, const byte *rx_open_msg UNUSED, uint rx_open_length UNUSED) { }
|
||||
static inline void bmp_peer_down(const struct bgp_proto *bgp UNUSED, const int err_class UNUSED, int code UNUSED, int subcode UNUSED, const byte *data UNUSED, int length UNUSED) { }
|
||||
|
||||
#endif /* CONFIG_BMP */
|
||||
|
||||
#endif /* _BIRD_BMP_H_ */
|
||||
|
119
proto/bmp/map.c
119
proto/bmp/map.c
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* BIRD -- The BGP Monitoring Protocol (BMP)
|
||||
*
|
||||
* (c) 2020 Akamai Technologies, Inc. (Pawel Maslanka, pmaslank@akamai.com)
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#include "proto/bmp/map.h"
|
||||
|
||||
/* Peer Index Table */
|
||||
#define PEER_KEY(n) (n)->peer_as, (n)->peer_ip
|
||||
#define PEER_NEXT(n) (n)->next
|
||||
#define PEER_EQ(as1,ip1,as2,ip2) \
|
||||
(as1) == (as2) && ipa_equal(ip1, ip2)
|
||||
#define PEER_FN(as,ip) ipa_hash(ip)
|
||||
|
||||
#define PEER_REHASH bmp_peer_rehash
|
||||
#define PEER_PARAMS /8, *2, 2, 2, 6, 20
|
||||
|
||||
HASH_DEFINE_REHASH_FN(PEER, struct bmp_peer_map_key)
|
||||
|
||||
#define PEER_INIT_ORDER 6
|
||||
|
||||
void
|
||||
bmp_peer_map_init(struct bmp_peer_map *map, pool *mpool)
|
||||
{
|
||||
map->mpool = mpool;
|
||||
HASH_INIT(map->peer_hash, map->mpool, PEER_INIT_ORDER);
|
||||
}
|
||||
|
||||
struct bmp_peer_map_key
|
||||
bmp_peer_map_key_create(const ip_addr peer_ip, const u32 peer_as)
|
||||
{
|
||||
struct bmp_peer_map_key key;
|
||||
key.next = NULL;
|
||||
key.peer_ip = peer_ip;
|
||||
key.peer_as = peer_as;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void
|
||||
bmp_peer_map_flush(struct bmp_peer_map *map)
|
||||
{
|
||||
struct bmp_peer_map_entry *entry;
|
||||
HASH_WALK_DELSAFE(map->peer_hash, next, e)
|
||||
{
|
||||
entry = (struct bmp_peer_map_entry *) e;
|
||||
mb_free(entry->data.buf);
|
||||
HASH_DELETE(map->peer_hash, PEER, PEER_KEY(&entry->key));
|
||||
mb_free(entry);
|
||||
}
|
||||
HASH_WALK_DELSAFE_END;
|
||||
|
||||
HASH_MAY_RESIZE_DOWN(map->peer_hash, PEER, map->mpool);
|
||||
}
|
||||
|
||||
void
|
||||
bmp_peer_map_free(struct bmp_peer_map *map)
|
||||
{
|
||||
bmp_peer_map_flush(map);
|
||||
HASH_FREE(map->peer_hash);
|
||||
}
|
||||
|
||||
void
|
||||
bmp_peer_map_insert(struct bmp_peer_map *map, const struct bmp_peer_map_key key,
|
||||
const byte *data, const size_t data_size)
|
||||
{
|
||||
struct bmp_peer_map_entry *entry
|
||||
= (void *) HASH_FIND(map->peer_hash, PEER, PEER_KEY(&key));
|
||||
|
||||
if (entry)
|
||||
{
|
||||
mb_free(entry->data.buf);
|
||||
entry->data.buf = mb_alloc(map->mpool, data_size);
|
||||
memcpy(entry->data.buf, data, data_size);
|
||||
entry->data.buf_size = data_size;
|
||||
return;
|
||||
}
|
||||
|
||||
entry = mb_alloc(map->mpool, sizeof (struct bmp_peer_map_entry));
|
||||
entry->data.buf = mb_alloc(map->mpool, data_size);
|
||||
memcpy(entry->data.buf, data, data_size);
|
||||
entry->data.buf_size = data_size;
|
||||
entry->key = key;
|
||||
HASH_INSERT2(map->peer_hash, PEER, map->mpool, &entry->key);
|
||||
}
|
||||
|
||||
void
|
||||
bmp_peer_map_remove(struct bmp_peer_map *map, const struct bmp_peer_map_key key)
|
||||
{
|
||||
struct bmp_peer_map_entry *entry
|
||||
= (void *) HASH_DELETE(map->peer_hash, PEER, PEER_KEY(&key));
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
mb_free(entry->data.buf);
|
||||
mb_free(entry);
|
||||
}
|
||||
|
||||
const struct bmp_peer_map_entry *
|
||||
bmp_peer_map_get(struct bmp_peer_map *map, const struct bmp_peer_map_key key)
|
||||
{
|
||||
return (struct bmp_peer_map_entry *) HASH_FIND(map->peer_hash, PEER, PEER_KEY(&key));
|
||||
}
|
||||
|
||||
void
|
||||
bmp_peer_map_walk(const struct bmp_peer_map *map, bmp_peer_map_walk_action action, void *arg)
|
||||
{
|
||||
struct bmp_peer_map_entry *entry;
|
||||
HASH_WALK_FILTER(map->peer_hash, next, e, _)
|
||||
{
|
||||
entry = (struct bmp_peer_map_entry *) e;
|
||||
action(entry->key, entry->data.buf, entry->data.buf_size, arg);
|
||||
}
|
||||
HASH_WALK_FILTER_END;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* BIRD -- The BGP Monitoring Protocol (BMP)
|
||||
*
|
||||
* (c) 2020 Akamai Technologies, Inc. (Pawel Maslanka, pmaslank@akamai.com)
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This map implementation binds peer IP address as container key with custom data.
|
||||
*/
|
||||
#ifndef _BIRD_BMP_MAP_H_
|
||||
#define _BIRD_BMP_MAP_H_
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/hash.h"
|
||||
#include "lib/resource.h"
|
||||
|
||||
struct bmp_peer_map_key {
|
||||
struct bmp_peer_map_key *next;
|
||||
ip_addr peer_ip;
|
||||
u32 peer_as;
|
||||
};
|
||||
|
||||
struct bmp_peer_map_data {
|
||||
void *buf;
|
||||
size_t buf_size;
|
||||
};
|
||||
|
||||
struct bmp_peer_map_entry {
|
||||
struct bmp_peer_map_key key;
|
||||
struct bmp_peer_map_data data;
|
||||
};
|
||||
|
||||
struct bmp_peer_map {
|
||||
pool *mpool; // Memory pool for peer entries in peer_hash
|
||||
HASH(struct bmp_peer_map_key) peer_hash; // Hash for peers to find the index
|
||||
};
|
||||
|
||||
void
|
||||
bmp_peer_map_init(struct bmp_peer_map *map, pool *mpool);
|
||||
|
||||
struct bmp_peer_map_key
|
||||
bmp_peer_map_key_create(const ip_addr peer_ip, const u32 peer_as);
|
||||
|
||||
void
|
||||
bmp_peer_map_free(struct bmp_peer_map *map);
|
||||
|
||||
void
|
||||
bmp_peer_map_flush(struct bmp_peer_map *map);
|
||||
|
||||
void
|
||||
bmp_peer_map_insert(struct bmp_peer_map *map, const struct bmp_peer_map_key key,
|
||||
const byte *data, const size_t data_size);
|
||||
|
||||
void
|
||||
bmp_peer_map_remove(struct bmp_peer_map *map, const struct bmp_peer_map_key key);
|
||||
|
||||
const struct bmp_peer_map_entry *
|
||||
bmp_peer_map_get(struct bmp_peer_map *map, const struct bmp_peer_map_key key);
|
||||
|
||||
typedef void (*bmp_peer_map_walk_action)(const struct bmp_peer_map_key key,
|
||||
const byte *data, const size_t data_size, void *arg);
|
||||
|
||||
void
|
||||
bmp_peer_map_walk(const struct bmp_peer_map *map, bmp_peer_map_walk_action action, void *arg);
|
||||
|
||||
#endif /* _BIRD_BMP_MAP_H_ */
|
Loading…
Reference in New Issue
Block a user