]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'a47704a53db4f088e52e43f8b24785e5777ce147' into thread-next
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 3 Dec 2024 18:40:21 +0000 (19:40 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 3 Dec 2024 18:40:21 +0000 (19:40 +0100)
1  2 
proto/bgp/packets.c
proto/bmp/bmp.c

index 33f46a8fd31d39c39307e3afe462c8259e2631e1,81f0d3c4e0266bd0c0d6db0c221cc7e792392233..157843a629b6aceb9647d92fdf8a6ff268636636
@@@ -2525,49 -2520,34 +2525,34 @@@ bgp_create_update_bmp(ea_list *channel_
    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;
 -  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;
 -  uint prefix_size = sizeof(struct bgp_prefix) + n->length;
 -
 -  /* Sham bucket */
 -  struct bgp_bucket *b = alloca(bucket_size);
 -  *b = (struct bgp_bucket) { };
 +bgp_bmp_encode_rte(ea_list *c, struct bgp_proto *bgp_p, byte *buf, byte *end, const struct rte *new)
 +{
-   byte *pkt = buf + BGP_HEADER_LENGTH;
 +  uint ea_size = new->attrs ? (sizeof(ea_list) + new->attrs->count * sizeof(eattr)) : 0;
 +  uint prefix_size = sizeof(struct bgp_prefix) + new->net->length;
 +
 +  struct lp_state *tmpp = lp_save(tmp_linpool);
 +
 +  /* Temporary bucket */
 +  struct bgp_bucket *b = tmp_allocz(sizeof(struct bgp_bucket) + ea_size);
 +  b->bmp = 1;
    init_list(&b->prefixes);
  
 -  if (attrs)
 -    memcpy(b->eattrs, attrs, ea_size);
 +  if (new->attrs)
 +    memcpy(b->eattrs, new->attrs, ea_size);
  
 -  /* Sham prefix */
 -  struct bgp_prefix *px = alloca(prefix_size);
 -  *px = (struct bgp_prefix) { };
 -  px->path_id = (u32) src->private_id;
 -  net_copy(px->net, n);
 +  /* Temporary prefix */
 +  struct bgp_prefix *px = tmp_allocz(prefix_size);
 +  px->src = tmp_allocz(sizeof(struct rte_src));
 +  memcpy(px->src, new->src, sizeof(struct rte_src));
 +  px->ni = NET_TO_INDEX(new->net);
    add_tail(&b->prefixes, &px->buck_node);
  
-   end = bgp_create_update_bmp(c, bgp_p, pkt, end, b, !!new->attrs);
-   if (end)
-     bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE);
 -  return bgp_create_update_bmp(c, buf, end, b, !!new);
++  end = bgp_create_update_bmp(c, bgp_p, buf, end, b, !!new->attrs);
 +
 +  lp_restore(tmp_linpool, tmpp);
 +
 +  return end;
  }
  
  #endif /* CONFIG_BMP */
diff --cc proto/bmp/bmp.c
index 19c187ed20f24bbc717225e5bf5c592512fe5a7e,9603c4e8a28513e3b57158154682e24c88158bf8..aefb195d46e3aafe29d97fd2b146e60ba2cfb7ca
@@@ -885,66 -831,75 +866,82 @@@ bmp_send_peer_up_notif_msg(struct bmp_p
    };
  
    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_peer_up_notif_msg_serialize(&payload, &peer, sk->saddr, sk->sport, sk->dport, tx_data, rx_data);
-   bmp_schedule_tx_packet(p, payload.start, payload.pos - payload.start);
- }
- static void
- bmp_route_monitor_put_update(struct bmp_proto *p, struct bmp_stream *bs, byte *data, size_t length, btime timestamp)
- {
-   ea_list *bgp = bs->bgp;
-   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),
-     .timestamp = timestamp,
-   };
-   const byte *start = bmp_route_monitor_msg_serialize(p, &peer, data, length);
-   bmp_schedule_tx_packet(p, start, (data - start) + length);
+   bmp_schedule_tx_packet(p, &payload);
  }
  
  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)
 +bmp_route_monitor_notify(struct bmp_proto *p, struct bgp_proto *bgp_p, u32 afi, bool policy, const rte *new, ea_list *old)
  {
 -  struct bgp_proto *bgp = bs->bgp;
 -  struct bgp_channel *c = bs->sender;
 +  /* 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;
 +
-   byte *bufend = &p->msgbuf[sizeof p->msgbuf];
-   byte *begin = bufend - BGP_MAX_EXT_MSG_LENGTH;
-   byte *end = bgp_bmp_encode_rte(bs->sender, bgp_p, begin, bufend, new);
++  ea_list *bgp = bs->bgp;
++  ea_list *c = bs->sender;
  
-   btime delta_t = new->attrs ? current_time() - new->lastmod : 0;
-   btime timestamp = current_real_time() - delta_t;
+   btime delta_t = new ? current_time() - new->lastmod : 0;
  
-   if (end)
-     bmp_route_monitor_put_update(p, bs, begin, end - begin, timestamp);
-   else
+   struct bmp_peer_hdr_info peer = {
 -    .address = bgp->remote_ip,
 -    .as = bgp->remote_as,
 -    .id = bgp->remote_id,
++    .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),
+     .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);
+   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);
++  byte *pos = bgp_bmp_encode_rte(c, bgp_p, msg.pos + BGP_HEADER_LENGTH, msg.end, new);
+   if (!pos)
+   {
 -    log(L_WARN "%s: Cannot encode update for %N", p->p.name, n);
 +    log(L_WARN "%s: Cannot encode update for %N", p->p.name, new->net);
+     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", ea_get_adata(bs->bgp, &ea_name)->data, ea_get_adata(bs->sender, &ea_name)->data);
 -  struct bgp_proto *bgp = bs->bgp;
 -  struct bgp_channel *c = bs->sender;
++  ea_list *bgp = bs->bgp;
++  ea_list *c = bs->sender;
+   struct bmp_peer_hdr_info peer = {
 -    .address = bgp->remote_ip,
 -    .as = bgp->remote_as,
 -    .id = bgp->remote_id,
++    .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),
+     .timestamp = current_real_time(),
+   };
 -  TRACE(D_PACKETS, "Sending END-OF-RIB for %s.%s", bgp->p.name, c->c.name);
++  TRACE(D_PACKETS, "Sending END-OF-RIB for %s.%s", ea_get_adata(bgp, &ea_name)->data, ea_get_adata(c, &ea_name)->data);
+   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_ea_(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);
++  byte *pos = bgp_create_end_mark_ea_(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
@@@ -1161,41 -1086,13 +1158,41 @@@ 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;
 -  WALK_LIST(peer, proto_list)
 -    if ((peer->proto->class == PROTOCOL_BGP) && (peer->proto_state == PS_UP))
 -      bmp_peer_init(p, (struct bgp_proto *) peer);
 +  u32 length;
 +  PST_LOCKED(ts) /* The size of protos field will never decrease, the inconsistency caused by growing is not important */
 +    length = ts->length_states;
 +
 +  /* Subscribe to protocol state changes */
 +  p->proto_state_reader = (struct lfjour_recipient) {
 +    .event = &p->proto_state_changed,
 +    .target = proto_event_list(&p->p),
 +  };
 +
 +  p->proto_state_changed = (event) {
 +    .hook = bmp_proto_state_changed,
 +    .data = p,
 +  };
 +
 +  proto_states_subscribe(&p->proto_state_reader);
 +
 +  /* Load protocol states */
 +  for (u32 i = 0; i < length; i++)
 +  {
 +    ea_list *proto_attr = proto_get_state(i);
 +    if (proto_attr == NULL)
 +      continue;
 +
 +    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);
 +
 +    if (proto != &proto_bgp || state != PS_UP)
 +      continue;
 +
 +    bmp_peer_up_inout(p, proto_attr, false);
 +  }
  }
  
  /**