]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BMP: Never touching the BGP directly
authorMaria Matejka <mq@ucw.cz>
Mon, 9 Dec 2024 10:21:01 +0000 (11:21 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 10 Dec 2024 22:41:48 +0000 (23:41 +0100)
Dropped hopefully last remnants of BMP directly accessing BGP structures.

13 files changed:
lib/route.h
lib/type.h
nest/proto.c
nest/protocol.h
proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c
proto/bmp/Makefile
proto/bmp/bmp.c
proto/bmp/bmp.h
proto/bmp/map.c [deleted file]
proto/bmp/map.h [deleted file]

index b9bbd2ae0a9ad457bdfdb9cafde922e9e3e692d9..783ef34ad1d03b2bace22951b8b108024253d68a 100644 (file)
@@ -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
index e42c6728374a95e466a7edec745778a371fe6d81..9244ea401c62baea51c5b40f0323e93bac5a5d4c 100644 (file)
@@ -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;
 };
index 670ee50639b30f0ab0500fd0e9b7a85ae0216456..5a46514b68508f61d1173de6c16834bbae115401 100644 (file)
@@ -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));
index 5526d48f3396cc6c6ffc75147ff804bb6f2739f3..171a0a5b1f69fe7beb1f70639d755637e8edd22c 100644 (file)
@@ -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)) )
index 0e843b50d5f049ad062c0e3718e8ca7b84fdd380..957fe108e0cab467c9ffc1d49923f66e5df90cb2 100644 (file)
@@ -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,
index e87ec2879b00befe0ab95cf966311ce69bf6ba82..ea9392ff4071bba64f5640f7f10273ae3b510010 100644 (file)
@@ -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));
index 05aae612b91e215d6ed1bcdc8043ecd46263eb33..c12942ec1374c0643edeae2a0183e2ff6f1c382b 100644 (file)
@@ -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;
 
index 157843a629b6aceb9647d92fdf8a6ff268636636..f236eeaba0a8682078f6e8c1f9bf989720497f6a 100644 (file)
@@ -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,
index e34f382280c816ed10250c7e4105d8080be08577..1fb0ce43abe02ae9092c4b071b30a7434aba09ae 100644 (file)
@@ -1,4 +1,4 @@
-src := bmp.c map.c
+src := bmp.c
 obj := $(src-o-files)
 $(all-daemon)
 $(cf-local)
index e38b976495042eb3eb547729d671586f5c05135d..d5e546d20b991cce2dbb15d2c2f08c3dee6aa68d 100644 (file)
@@ -29,7 +29,6 @@
  */
 
 #include "proto/bmp/bmp.h"
-#include "proto/bmp/map.h"
 
 #include <sys/socket.h>
 #include <sys/time.h>
 #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;
+    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 *));
+
     PST_LOCKED(ts)
-      chan_attr = ts->channel_states[chann_ids[i]];
+      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;
+      }
+  }
 
-    if (chan_attr == 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);
+
+  /* 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);
 
-    bmp_peer_up_inout(p, proto_attr);
+  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
index 283c74d08d97e0fc2309ba50ebd46b7b00d4ccba..63ece5722f3e3d8294723e995c8dd2367ad3b9ee 100644 (file)
@@ -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_ */
diff --git a/proto/bmp/map.c b/proto/bmp/map.c
deleted file mode 100644 (file)
index 16e714f..0000000
+++ /dev/null
@@ -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;
-}
diff --git a/proto/bmp/map.h b/proto/bmp/map.h
deleted file mode 100644 (file)
index 8e7ea69..0000000
+++ /dev/null
@@ -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_ */