From a47704a53db4f088e52e43f8b24785e5777ce147 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 2 Dec 2024 00:00:36 +0100 Subject: [PATCH] BMP: Refactor route monitor message serialization 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 | 19 +------- proto/bmp/bmp.c | 103 +++++++++++++++++++++----------------------- 2 files changed, 51 insertions(+), 71 deletions(-) diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ec648231..81f0d3c4 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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 */ diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index dc21ac09..9603c4e8 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -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); -} + buffer msg = bmp_default_buffer(p); + bmp_put_common_hdr(&msg, BMP_ROUTE_MONITOR, 0); + bmp_put_per_peer_hdr(&msg, &peer); -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; - - 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; - 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); + 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(), + }; - bmp_route_monitor_put_update(p, bs, rx_end_payload, pos - rx_end_payload, 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); + + 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_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;