]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BMP: Refactor route monitor message serialization
authorOndrej Zajicek <santiago@crfreenet.org>
Sun, 1 Dec 2024 23:00:36 +0000 (00:00 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 2 Dec 2024 02:38:17 +0000 (03:38 +0100)
Instead of several levels of functions, just have two functions
(one for routes, the other for end-of-rib), this allows to create
messages in a simple linear fashion.

Also reduce three duplicite functions to construct BGP header for
BMP messages to just one.

proto/bgp/packets.c
proto/bmp/bmp.c

index ec648231a1fcb75567760276ba06abc34e02933a..81f0d3c4e0266bd0c0d6db0c221cc7e792392233 100644 (file)
@@ -2522,23 +2522,11 @@ bgp_create_update_bmp(struct bgp_channel *c, byte *buf, byte *end, struct bgp_bu
   return res;
 }
 
-static byte *
-bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type)
-{
-  memset(buf + BGP_MSG_HDR_MARKER_POS, 0xff, BGP_MSG_HDR_MARKER_SIZE);
-  put_u16(buf + BGP_MSG_HDR_LENGTH_POS, msg_size);
-  put_u8(buf + BGP_MSG_HDR_TYPE_POS, msg_type);
-
-  return buf + BGP_MSG_HDR_TYPE_POS + BGP_MSG_HDR_TYPE_SIZE;
-}
-
 byte *
 bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, byte *end, const net_addr *n,
                   const struct rte *new, const struct rte_src *src)
 {
 //  struct bgp_proto *p = (void *) c->c.proto;
-  byte *pkt = buf + BGP_HEADER_LENGTH;
-
   ea_list *attrs = new ? new->attrs->eattrs : NULL;
   uint ea_size = new ? (sizeof(ea_list) + attrs->count * sizeof(eattr)) : 0;
   uint bucket_size = sizeof(struct bgp_bucket) + ea_size;
@@ -2559,12 +2547,7 @@ bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, byte *end, const net_addr *
   net_copy(px->net, n);
   add_tail(&b->prefixes, &px->buck_node);
 
-  end = bgp_create_update_bmp(c, pkt, end, b, !!new);
-
-  if (end)
-    bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE);
-
-  return end;
+  return bgp_create_update_bmp(c, buf, end, b, !!new);
 }
 
 #endif /* CONFIG_BMP */
index dc21ac090d18399e3f7fbf0a8f7c6e2824312bf0..9603c4e8a28513e3b57158154682e24c88158bf8 100644 (file)
@@ -297,8 +297,11 @@ bmp_init_msg_serialize(buffer *stream, const char *sys_descr, const char *sys_na
 }
 
 static void
-bmp_schedule_tx_packet(struct bmp_proto *p, const byte *payload, size_t size)
+bmp_schedule_tx_packet(struct bmp_proto *p, buffer *msg)
 {
+  const byte *payload = msg->start;
+  size_t size = msg->pos - msg->start;
+
   ASSERT(p->started);
 
   while (size)
@@ -473,28 +476,6 @@ bmp_put_per_peer_hdr(buffer *stream, const struct bmp_peer_hdr_info *peer)
   bmp_put_u32(stream, ts_usec);
 }
 
-/* [4.6] Route Monitoring */
-static byte *
-bmp_route_monitor_msg_serialize(struct bmp_proto *p, const struct bmp_peer_hdr_info *peer,
-                               byte *update_msg, size_t update_msg_length)
-{
-  ASSERT_DIE(update_msg < &p->msgbuf[sizeof p->msgbuf]);
-
-  buffer stream;
-  STACK_BUFFER_INIT(stream, BMP_PER_PEER_HDR_SIZE + BMP_COMMON_HDR_SIZE);
-
-  const size_t data_size = BMP_PER_PEER_HDR_SIZE + update_msg_length;
-  bmp_put_common_hdr(&stream, BMP_ROUTE_MONITOR, BMP_COMMON_HDR_SIZE + data_size);
-  bmp_put_per_peer_hdr(&stream, peer);
-
-  size_t hdr_sz = stream.pos - stream.start;
-  ASSERT_DIE(update_msg >= &p->msgbuf[hdr_sz]);
-
-  byte *begin = &update_msg[-hdr_sz];
-  memcpy(begin, stream.start, hdr_sz);
-  return begin;
-}
-
 static void
 bmp_peer_up_notif_msg_serialize(buffer *stream, const struct bmp_peer_hdr_info *peer,
                                const ip_addr local_addr, const u16 local_port, const u16 remote_port,
@@ -852,13 +833,17 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp,
   buffer payload = bmp_default_buffer(p);
   bmp_peer_up_notif_msg_serialize(&payload, &peer, sk->saddr, sk->sport, sk->dport,
                                  tx_data, tx_data_size, rx_data, rx_data_size);
-  bmp_schedule_tx_packet(p, payload.start, payload.pos - payload.start);
+  bmp_schedule_tx_packet(p, &payload);
 }
 
 static void
-bmp_route_monitor_put_update(struct bmp_proto *p, struct bmp_stream *bs, byte *data, size_t length, btime timestamp)
+bmp_route_monitor_notify(struct bmp_proto *p, struct bmp_stream *bs,
+                        const net_addr *n, const struct rte *new, const struct rte_src *src)
 {
   struct bgp_proto *bgp = bs->bgp;
+  struct bgp_channel *c = bs->sender;
+
+  btime delta_t = new ? current_time() - new->lastmod : 0;
 
   struct bmp_peer_hdr_info peer = {
     .address = bgp->remote_ip,
@@ -866,43 +851,55 @@ bmp_route_monitor_put_update(struct bmp_proto *p, struct bmp_stream *bs, byte *d
     .id = bgp->remote_id,
     .global = bmp_is_peer_global_instance(bgp),
     .policy = bmp_stream_policy(bs),
-    .timestamp = timestamp,
+    .timestamp = current_real_time() - delta_t,
   };
 
-  const byte *start = bmp_route_monitor_msg_serialize(p, &peer, data, length);
-  bmp_schedule_tx_packet(p, start, (data - start) + length);
-}
-
-static void
-bmp_route_monitor_notify(struct bmp_proto *p, struct bmp_stream *bs,
-                        const net_addr *n, const struct rte *new, const struct rte_src *src)
-{
-  byte *bufend = &p->msgbuf[sizeof p->msgbuf];
-  byte *begin = bufend - BGP_MAX_EXT_MSG_LENGTH;
-  byte *end = bgp_bmp_encode_rte(bs->sender, begin, bufend, n, new, src);
-
-  btime delta_t = new ? current_time() - new->lastmod : 0;
-  btime timestamp = current_real_time() - delta_t;
+  buffer msg = bmp_default_buffer(p);
+  bmp_put_common_hdr(&msg, BMP_ROUTE_MONITOR, 0);
+  bmp_put_per_peer_hdr(&msg, &peer);
 
-  if (end)
-    bmp_route_monitor_put_update(p, bs, begin, end - begin, timestamp);
-  else
+  bmp_buffer_need(&msg, BGP_MAX_EXT_MSG_LENGTH);
+  byte *pos = bgp_bmp_encode_rte(c, msg.pos + BGP_HEADER_LENGTH, msg.end, n, new, src);
+  if (!pos)
+  {
     log(L_WARN "%s: Cannot encode update for %N", p->p.name, n);
+    return;
+  }
+  bmp_put_bgp_hdr(&msg, PKT_UPDATE, pos - msg.pos);
+  msg.pos = pos;
+
+  bmp_fix_common_hdr(&msg);
+  bmp_schedule_tx_packet(p, &msg);
 }
 
 static void
 bmp_route_monitor_end_of_rib(struct bmp_proto *p, struct bmp_stream *bs)
 {
-  TRACE(D_PACKETS, "Sending END-OF-RIB for %s.%s", bs->bgp->p.name, bs->sender->c.name);
+  struct bgp_proto *bgp = bs->bgp;
+  struct bgp_channel *c = bs->sender;
+
+  struct bmp_peer_hdr_info peer = {
+    .address = bgp->remote_ip,
+    .as = bgp->remote_as,
+    .id = bgp->remote_id,
+    .global = bmp_is_peer_global_instance(bgp),
+    .policy = bmp_stream_policy(bs),
+    .timestamp = current_real_time(),
+  };
+
+  TRACE(D_PACKETS, "Sending END-OF-RIB for %s.%s", bgp->p.name, c->c.name);
+
+  buffer msg = bmp_default_buffer(p);
+  bmp_put_common_hdr(&msg, BMP_ROUTE_MONITOR, 0);
+  bmp_put_per_peer_hdr(&msg, &peer);
 
-  byte *rx_end_payload = p->msgbuf + BMP_PER_PEER_HDR_SIZE + BMP_COMMON_HDR_SIZE;
-  byte *pos = bgp_create_end_mark_(bs->sender, rx_end_payload + BGP_HEADER_LENGTH);
-  memset(rx_end_payload + BGP_MSG_HDR_MARKER_POS, 0xff,
-        BGP_MSG_HDR_MARKER_SIZE); // BGP UPDATE MSG marker
-  put_u16(rx_end_payload + BGP_MSG_HDR_LENGTH_POS, pos - rx_end_payload);
-  put_u8(rx_end_payload + BGP_MSG_HDR_TYPE_POS, PKT_UPDATE);
+  bmp_buffer_need(&msg, BGP_MAX_EXT_MSG_LENGTH);
+  byte *pos = bgp_create_end_mark_(c, msg.pos + BGP_HEADER_LENGTH);
+  bmp_put_bgp_hdr(&msg, PKT_UPDATE, pos - msg.pos);
+  msg.pos = pos;
 
-  bmp_route_monitor_put_update(p, bs, rx_end_payload, pos - rx_end_payload, current_real_time());
+  bmp_fix_common_hdr(&msg);
+  bmp_schedule_tx_packet(p, &msg);
 }
 
 static void
@@ -925,7 +922,7 @@ bmp_send_peer_down_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp,
 
   buffer payload = bmp_default_buffer(p);
   bmp_peer_down_notif_msg_serialize(&payload, &peer, info);
-  bmp_schedule_tx_packet(p, payload.start, payload.pos - payload.start);
+  bmp_schedule_tx_packet(p, &payload);
 }
 
 static void
@@ -1089,7 +1086,7 @@ bmp_startup(struct bmp_proto *p)
   /* Send initiation message */
   buffer payload = bmp_default_buffer(p);
   bmp_init_msg_serialize(&payload, p->sys_descr, p->sys_name);
-  bmp_schedule_tx_packet(p, payload.start, payload.pos - payload.start);
+  bmp_schedule_tx_packet(p, &payload);
 
   /* Send Peer Up messages */
   struct proto *peer;