From 1be0be1b71f0127740a4aa6f35d4a256d6c34fb9 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 28 Apr 2023 19:13:56 +0200 Subject: BGP: Save sent and received OPEN messages These are necessary for BMP Peer UP message and it is better to keep them in BGP than in BMP (so BMP could be restarted or added later). --- proto/bgp/packets.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'proto/bgp/packets.c') diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index b9537169..c6c12cf2 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -772,6 +772,14 @@ err: return -1; } +static byte * +bgp_copy_open(struct bgp_proto *p, const byte *pkt, uint len) +{ + char *buf = mb_alloc(p->p.pool, len - BGP_HEADER_LENGTH); + memcpy(buf, pkt + BGP_HEADER_LENGTH, len - BGP_HEADER_LENGTH); + return buf; +} + static byte * bgp_create_open(struct bgp_conn *conn, byte *buf) { @@ -846,6 +854,9 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) id = get_u32(pkt+24); BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%R)", asn, hold, id); + conn->remote_open_msg = bgp_copy_open(p, pkt, len); + conn->remote_open_length = len - BGP_HEADER_LENGTH; + if (bgp_read_options(conn, pkt+29, pkt[28], len-29) < 0) return; @@ -2984,7 +2995,7 @@ bgp_send(struct bgp_conn *conn, uint type, uint len) conn->bgp->stats.tx_messages++; conn->bgp->stats.tx_bytes += len; - memset(buf, 0xff, 16); /* Marker */ + memset(buf, 0xff, BGP_HDR_MARKER_LENGTH); put_u16(buf+16, len); buf[18] = type; @@ -3032,6 +3043,10 @@ bgp_fire_tx(struct bgp_conn *conn) { conn->packets_to_send &= ~(1 << PKT_OPEN); end = bgp_create_open(conn, pkt); + + conn->local_open_msg = bgp_copy_open(p, buf, end - buf); + conn->local_open_length = end - buf - BGP_HEADER_LENGTH; + int rv = bgp_send(conn, PKT_OPEN, end - buf); if (rv >= 0) { -- cgit v1.2.3 From aa3c35498d3c5ae7ec7fd34bf8758652fc2748f1 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 1 May 2023 03:35:21 +0200 Subject: BMP: Use OPEN messages stored in BGP The BMP protocol needs OPEN messages of established BGP sessions to construct appropriate Peer Up messages. Instead of saving them internally we use OPEN messages stored in BGP instances. This allows BMP instances to be restarted or enabled later. Because of this change, we can simplify BMP data structures. No need to keep track of BGP sessions when we are not started. We have to iterate over all (established) BGP sessions when the BMP session is established. This is just a scaffolding now, but some kind of iteration would be necessary anyway. Also, the commit cleans up handling of msg/msg_length arguments to be body/body_length consistently in both rx/tx and peer_up/peer_down calls. --- proto/bgp/bgp.c | 2 + proto/bgp/packets.c | 12 +--- proto/bmp/bmp.c | 203 ++++++++++++++++------------------------------------ proto/bmp/bmp.h | 32 ++------- 4 files changed, 72 insertions(+), 177 deletions(-) (limited to 'proto/bgp/packets.c') diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 373b0392..17c503c4 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -689,6 +689,8 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) bgp_conn_set_state(conn, BS_ESTABLISHED); proto_notify_state(&p->p, PS_UP); + bmp_peer_up(p, conn->local_open_msg, conn->local_open_length, + conn->remote_open_msg, conn->remote_open_length); } static void diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index c6c12cf2..3138095a 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -167,7 +167,6 @@ bgp_create_notification(struct bgp_conn *conn, byte *buf) buf[0] = conn->notify_code; buf[1] = conn->notify_subcode; memcpy(buf+2, conn->notify_data, conn->notify_size); - bmp_peer_down(p, BE_NONE, buf, conn->notify_size + 2); return buf + 2 + conn->notify_size; } @@ -988,7 +987,6 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE); bgp_start_timer(conn->hold_timer, conn->hold_time); bgp_conn_enter_openconfirm_state(conn); - bmp_put_recv_bgp_open_msg(p, pkt, len); } @@ -3037,6 +3035,7 @@ bgp_fire_tx(struct bgp_conn *conn) { conn->packets_to_send = 1 << PKT_SCHEDULE_CLOSE; end = bgp_create_notification(conn, pkt); + bmp_peer_down(p, BE_BGP_TX, pkt, end - pkt); return bgp_send(conn, PKT_NOTIFICATION, end - buf); } else if (s & (1 << PKT_OPEN)) @@ -3047,12 +3046,7 @@ bgp_fire_tx(struct bgp_conn *conn) conn->local_open_msg = bgp_copy_open(p, buf, end - buf); conn->local_open_length = end - buf - BGP_HEADER_LENGTH; - int rv = bgp_send(conn, PKT_OPEN, end - buf); - if (rv >= 0) - { - bmp_put_sent_bgp_open_msg(p, pkt, end - buf); - } - return rv; + return bgp_send(conn, PKT_OPEN, end - buf); } else if (s & (1 << PKT_KEEPALIVE)) { @@ -3352,7 +3346,7 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len) } } - bmp_peer_down(p, BE_NONE, pkt, len); + bmp_peer_down(p, BE_BGP_RX, pkt + BGP_HEADER_LENGTH, len - BGP_HEADER_LENGTH); } static void diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index f04b59b8..acfcae34 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -214,7 +214,7 @@ struct bmp_data_node { }; static void -bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C); +bmp_route_monitor_pre_policy_table_in_snapshot(struct bgp_channel *c); static void bmp_common_hdr_serialize(buffer *stream, const enum bmp_message_type type, const u32 data_size) @@ -336,12 +336,14 @@ bmp_put_ipa(buffer *stream, const ip_addr addr) } static void -bmp_set_initial_bgp_hdr(buffer *stream, const u16 msg_size, const u8 msg_type) +bmp_put_bgp_hdr(buffer *stream, const u8 msg_type, const u16 msg_length) { - byte marker[BGP_MSG_HDR_MARKER_SIZE]; - memset(marker, 0xff, BGP_MSG_HDR_MARKER_SIZE); - bmp_put_data(stream, marker, BGP_MSG_HDR_MARKER_SIZE); - bmp_put_u16(stream, msg_size); + bmp_buffer_need(stream, BGP_HEADER_LENGTH); + + memset(stream->pos, 0xff, BGP_HDR_MARKER_LENGTH); + stream->pos += BGP_HDR_MARKER_LENGTH; + + bmp_put_u16(stream, msg_length); bmp_put_u8(stream, msg_type); } @@ -413,8 +415,10 @@ bmp_peer_up_notif_msg_serialize(buffer *stream, const bool is_peer_global, const u16 remote_port, const byte *sent_msg, const size_t sent_msg_size, const byte *recv_msg, const size_t recv_msg_size) { - const size_t data_size = BMP_PER_PEER_HDR_SIZE + BMP_PEER_UP_NOTIF_MSG_FIX_SIZE - + sent_msg_size + recv_msg_size; + const size_t data_size = + BMP_PER_PEER_HDR_SIZE + BMP_PEER_UP_NOTIF_MSG_FIX_SIZE + + BGP_HEADER_LENGTH + sent_msg_size + BGP_HEADER_LENGTH + recv_msg_size; + bmp_buffer_need(stream, BMP_COMMON_HDR_SIZE + data_size); bmp_common_hdr_serialize(stream, BMP_PEER_UP_NOTIF, data_size); bmp_per_peer_hdr_serialize(stream, is_peer_global, @@ -423,11 +427,9 @@ bmp_peer_up_notif_msg_serialize(buffer *stream, const bool is_peer_global, bmp_put_ipa(stream, local_addr); bmp_put_u16(stream, local_port); bmp_put_u16(stream, remote_port); - bmp_set_initial_bgp_hdr(stream, sent_msg_size, PKT_OPEN); - const size_t missing_bgp_hdr_size = BGP_MSG_HDR_MARKER_SIZE - + BGP_MSG_HDR_LENGTH_SIZE - + BGP_MSG_HDR_TYPE_SIZE; - bmp_put_data(stream, sent_msg, sent_msg_size - missing_bgp_hdr_size); + bmp_put_bgp_hdr(stream, PKT_OPEN, BGP_HEADER_LENGTH + sent_msg_size); + bmp_put_data(stream, sent_msg, sent_msg_size); + bmp_put_bgp_hdr(stream, PKT_OPEN, BGP_HEADER_LENGTH + recv_msg_size); bmp_put_data(stream, recv_msg, recv_msg_size); } @@ -445,43 +447,37 @@ bmp_peer_down_notif_msg_serialize(buffer *stream, const bool is_peer_global, bmp_put_data(stream, data, data_size); } -static void -bmp_peer_map_walk_tx_open_msg_and_send_peer_up_notif( - const struct bmp_peer_map_key key, const byte *tx_msg, - const size_t tx_msg_size, void *bmp_) +void +bmp_peer_up(const struct bgp_proto *bgp, + const byte *tx_open_msg, uint tx_open_length, + const byte *rx_open_msg, uint rx_open_length) { - struct bmp_proto *p = bmp_; - ASSERT(p->started); + struct bmp_proto *p = g_bmp; - const struct bmp_peer_map_entry *map_rx_msg = bmp_peer_map_get(&p->peer_open_msg.rx_msg, key); - IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL( - map_rx_msg, - "Processing TX BGP OPEN MSG but there is not corresponding received MSG" - ); + if (!p || !p->started) + return; - const struct bmp_peer_map_entry *map_bgp_proto = bmp_peer_map_get(&p->bgp_peers, key); - IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL( - map_bgp_proto, - "There is not BGP proto related with stored TX/RX OPEN MSG" - ); + // struct bmp_peer_map_key key = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); + // bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp)); - const struct bgp_proto *bgp; - memcpy(&bgp, map_bgp_proto->data.buf, sizeof (bgp)); - if (bgp->p.proto_state == PS_UP) - { - bmp_send_peer_up_notif_msg(p, bgp, tx_msg, tx_msg_size, - map_rx_msg->data.buf, map_rx_msg->data.buf_size); - } + bmp_send_peer_up_notif_msg(p, bgp, tx_open_msg, tx_open_length, rx_open_msg, rx_open_length); + + struct bgp_channel *c; + BGP_WALK_CHANNELS(bgp, c) + bmp_route_monitor_pre_policy_table_in_snapshot(c); } static void -bmp_peer_up(const struct bgp_proto *bgp) +bmp_peer_init(const struct bgp_proto *bgp) { - struct bgp_channel *c; - WALK_LIST(c, bgp->p.channels) - { - bmp_route_monitor_pre_policy_table_in_snapshot((struct channel *) c); - } + struct bgp_conn *conn = bgp->conn; + + if (!conn || (conn->state != BS_ESTABLISHED) || + !conn->local_open_msg || !conn->remote_open_msg) + return; + + bmp_peer_up(bgp, conn->local_open_msg, conn->local_open_length, + conn->remote_open_msg, conn->remote_open_length); } static const struct birdsock * @@ -579,60 +575,6 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, rx_data, rx_data_size); bmp_schedule_tx_packet(p, bmp_buffer_data(&payload), bmp_buffer_pos(&payload)); bmp_buffer_free(&payload); - - bmp_peer_up(bgp); -} - -void -bmp_put_sent_bgp_open_msg(const struct bgp_proto *bgp, const byte* pkt, - const size_t pkt_size) -{ - struct bmp_proto *p = g_bmp; - - if (!p) - { - return; - } - - struct bmp_peer_map_key key - = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); - const struct bmp_peer_map_entry *rx_msg - = bmp_peer_map_get(&p->peer_open_msg.rx_msg, key); - - bmp_peer_map_insert(&p->peer_open_msg.tx_msg, key, pkt, pkt_size); - - if (!rx_msg) - bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp)); - - if (rx_msg && p->started) - bmp_send_peer_up_notif_msg(p, bgp, pkt, pkt_size, rx_msg->data.buf, - rx_msg->data.buf_size); -} - -void -bmp_put_recv_bgp_open_msg(const struct bgp_proto *bgp, const byte* pkt, - const size_t pkt_size) -{ - struct bmp_proto *p = g_bmp; - - if (!p) - { - return; - } - - struct bmp_peer_map_key key - = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); - const struct bmp_peer_map_entry *tx_msg - = bmp_peer_map_get(&p->peer_open_msg.tx_msg, key); - - bmp_peer_map_insert(&p->peer_open_msg.rx_msg, key, pkt, pkt_size); - - if (!tx_msg) - bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp)); - - if (tx_msg && p->started) - bmp_send_peer_up_notif_msg(p, bgp, tx_msg->data.buf, tx_msg->data.buf_size, - pkt, pkt_size); } void @@ -775,7 +717,7 @@ bmp_route_monitor_update_in_pre_end() } static void -bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C) +bmp_route_monitor_pre_policy_table_in_snapshot(struct bgp_channel *c) { struct bmp_proto *p = g_bmp; @@ -784,7 +726,7 @@ bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C) return; } - struct rtable *tab = C->in_table; + struct rtable *tab = c->c.in_table; if (!tab) { return; @@ -808,7 +750,7 @@ bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C) rte *e; for (e = n->routes; e; e = e->next) { - bgp_rte_update_in_notify(C, n->n.addr, e, e->src); + bgp_rte_update_in_notify(&c->c, n->n.addr, e, e->src); } bmp_route_monitor_update_in_pre_commit((struct bgp_proto *) P); @@ -821,15 +763,13 @@ bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C) { bmp_route_monitor_update_in_pre_begin(); byte rx_end_payload[DEFAULT_MEM_BLOCK_SIZE]; - byte *pos - = bgp_create_end_mark((struct bgp_channel *) C, rx_end_payload - + BGP_HEADER_LENGTH); + byte *pos = bgp_create_end_mark(c, 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_route_monitor_put_update_in_pre_msg(rx_end_payload, pos - rx_end_payload); - bmp_route_monitor_update_in_pre_commit((struct bgp_proto *) C->proto); + bmp_route_monitor_update_in_pre_commit((struct bgp_proto *) c->c.proto); bmp_route_monitor_update_in_pre_end(); } } @@ -854,49 +794,28 @@ bmp_send_peer_down_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, } void -bmp_peer_down(const struct bgp_proto *bgp, const int err_class, const byte *pkt, - size_t pkt_size) +bmp_peer_down(const struct bgp_proto *bgp, const int err_class, + const byte *msg, size_t msg_length) { struct bmp_proto *p = g_bmp; - if (!p) - { + if (!p || !p->started) return; - } - struct bmp_peer_map_key key - = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); + // struct bmp_peer_map_key key = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); + // bmp_peer_map_remove(&p->bgp_peers, key); - bmp_peer_map_remove(&p->peer_open_msg.tx_msg, key); - bmp_peer_map_remove(&p->peer_open_msg.rx_msg, key); - bmp_peer_map_remove(&p->bgp_peers, key); - const size_t missing_bgp_hdr_size = BGP_MSG_HDR_MARKER_SIZE - + BGP_MSG_HDR_LENGTH_SIZE - + BGP_MSG_HDR_TYPE_SIZE; + buffer payload = bmp_buffer_alloc(p->buffer_mpool, 1 + BGP_HEADER_LENGTH + msg_length); - if (!p->started) - return; - - buffer payload - = bmp_buffer_alloc(p->buffer_mpool, pkt_size + missing_bgp_hdr_size + 1); - if (pkt != NULL && pkt_size > 0) + if (msg) { - byte marker[BGP_MSG_HDR_MARKER_SIZE]; - memset(marker, 0xff, BGP_MSG_HDR_MARKER_SIZE); // NOTIF MSG marker - if (!memcmp(pkt, marker, BGP_MSG_HDR_MARKER_SIZE)) - { - // So it is received BGP PDU - bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION); - bmp_put_data(&payload, pkt, pkt_size); - } - else - { + if (err_class == BE_BGP_TX) bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION); - bmp_put_data(&payload, marker, BGP_MSG_HDR_MARKER_SIZE); - bmp_put_u16(&payload, pkt_size); - bmp_put_u8(&payload, PKT_NOTIFICATION); - bmp_put_data(&payload, pkt, pkt_size); - } + else + bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION); + + bmp_put_bgp_hdr(&payload, BGP_HEADER_LENGTH + msg_length, PKT_NOTIFICATION); + bmp_put_data(&payload, msg, msg_length); } else { @@ -962,8 +881,10 @@ bmp_startup(struct bmp_proto *p) bmp_buffer_free(&payload); /* Send Peer Up messages */ - bmp_peer_map_walk(&p->peer_open_msg.tx_msg, - bmp_peer_map_walk_tx_open_msg_and_send_peer_up_notif, p); + struct proto *peer; + WALK_LIST(peer, proto_list) + if ((peer->proto->class == PROTOCOL_BGP) && (peer->proto_state == PS_UP)) + bmp_peer_init((struct bgp_proto *) peer); proto_notify_state(&p->p, PS_UP); } @@ -1105,9 +1026,7 @@ bmp_start(struct proto *P) p->connect_retry_timer = tm_new_init(p->p.pool, bmp_connection_retry, p, 0, 0); p->sk = NULL; - bmp_peer_map_init(&p->peer_open_msg.tx_msg, p->map_mem_pool); - bmp_peer_map_init(&p->peer_open_msg.rx_msg, p->map_mem_pool); - bmp_peer_map_init(&p->bgp_peers, p->map_mem_pool); + // bmp_peer_map_init(&p->bgp_peers, p->map_mem_pool); init_list(&p->tx_queue); init_list(&p->rt_table_in_pre_policy.update_msg_queue); diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index 19623e33..51a8e636 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -46,12 +46,6 @@ struct bmp_config { struct bgp_proto; struct bmp_proto; -// Stores sent and received BGP OPEN MSGs -struct bmp_peer_open_msg { - struct bmp_peer_map tx_msg; - struct bmp_peer_map rx_msg; -}; - // Keeps necessary information during composing BGP UPDATE MSG which is going // to be sent to the BMP collector struct rt_table_info { @@ -72,8 +66,7 @@ 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_peer_open_msg peer_open_msg; // Stores sent and received BGP OPEN MSG per BGP peer + // struct bmp_peer_map bgp_peers; // Stores 'bgp_proto' structure per BGP peer pool *buffer_mpool; // Memory pool used for BMP buffer allocations pool *map_mem_pool; // Memory pool used for BMP map allocations pool *tx_mem_pool; // Memory pool used for packet allocations designated to BMP collector @@ -88,24 +81,12 @@ struct bmp_proto { #ifdef CONFIG_BMP /** - * bmp_put_sent_bgp_open_msg - save sent BGP OPEN msg packet in BMP implementation. - * NOTE: If there has been passed sent and received BGP OPEN MSGs to the BMP - * implementation, then there is going to be send BMP Peer Up Notification - * message to the BMP collector. - */ -void -bmp_put_sent_bgp_open_msg(const struct bgp_proto *bgp, const byte* pkt, - const size_t pkt_size); - -/** - * bmp_put_recv_bgp_open_msg - save received BGP OPEN msg packet in BMP implementation. - * NOTE: If there has been passed sent and received BGP OPEN MSGs to the BMP - * implementation, then there is going to be send BMP Peer Up Notification - * message to the BMP collector. + * bmp_peer_up - send notification that BGP peer connection is established */ void -bmp_put_recv_bgp_open_msg(const struct bgp_proto *bgp, const byte* pkt, - const size_t pkt_size); +bmp_peer_up(const struct bgp_proto *bgp, + const byte *tx_open_msg, uint tx_open_length, + const byte *rx_open_msg, uint rx_open_length); /** * The following 4 functions create BMP Route Monitoring message based on @@ -140,8 +121,7 @@ bmp_peer_down(const struct bgp_proto *bgp, const int err_class, const byte *pkt, #else /* BMP build disabled */ -static inline void bmp_put_sent_bgp_open_msg(const struct bgp_proto *bgp UNUSED, const byte* pkt UNUSED, const size_t pkt_size UNUSED) { } -static inline void bmp_put_recv_bgp_open_msg(const struct bgp_proto *bgp UNUSED, const byte* pkt UNUSED, const size_t pkt_size UNUSED) { } +static inline void bmp_peer_up(const struct bgp_proto *bgp, const byte *tx_open_msg, uint tx_open_length, const byte *rx_open_msg, uint rx_open_length) { } static inline void bmp_route_monitor_update_in_pre_begin(void) { } static inline void bmp_route_monitor_put_update_in_pre_msg(const byte *data UNUSED, const size_t data_size UNUSED) { } static inline void bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp UNUSED) { } -- cgit v1.2.3 From c1821a9aba3c7fbdb48cee7d86e4661317900a0a Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 30 May 2023 15:37:52 +0200 Subject: BGP: Improve bgp_create_update_bmp() Fix issue with missing AF cap (e.g. IPv4 unicast when no capabilities are announced). Add Linpool save/restore action similar to bgp_create_update(). Based on patch from Michal Zagorski co-authored with Pawel Maslanka . Thanks! --- proto/bgp/packets.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'proto/bgp/packets.c') diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 3138095a..63ff955b 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -2424,15 +2424,20 @@ bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, { struct bgp_proto *p = (void *) c->c.proto; byte *end = buf + (BGP_MAX_EXT_MSG_LENGTH - BGP_HEADER_LENGTH); + byte *res = NULL; /* FIXME: must be a bit shorter */ + struct lp_state tmpp; + lp_save(tmp_linpool, &tmpp); + struct bgp_caps *peer = p->conn->remote_caps; const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi); + struct bgp_write_state s = { .proto = p, .channel = c, .pool = tmp_linpool, - .mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop, + .mp_reach = (c->afi != BGP_AF_IPV4) || (rem && rem->ext_next_hop), .as4_session = 1, .add_path = c->add_path_rx, .mpls = c->desc->mpls, @@ -2441,16 +2446,20 @@ bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, if (!update) { - return !s.mp_reach ? + res = !s.mp_reach ? bgp_create_ip_unreach(&s, buck, buf, end): bgp_create_mp_unreach(&s, buck, buf, end); } else { - return !s.mp_reach ? + res = !s.mp_reach ? bgp_create_ip_reach(&s, buck, buf, end): bgp_create_mp_reach(&s, buck, buf, end); } + + lp_restore(tmp_linpool, &tmpp); + + return res; } static byte * -- cgit v1.2.3 From e8838d930cd5c875f32aa2b7da5d84995b14ccac Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 8 Jun 2023 04:56:41 +0200 Subject: BMP: Support multiple instances of BMP protocol Add internal BMP functions with plicit bmp_proto *p as first argument, which allows using TRACE() macro. Keep list of BMP instances and call internal functions. Old BMP functions are wrappers that call internal functions for all enabled BMP instances. Extract End-of-RIB mark into separate function. Based on patch from Michal Zagorski . Thanks! --- proto/bgp/bgp.c | 2 +- proto/bgp/bgp.h | 6 +- proto/bgp/packets.c | 21 ++++--- proto/bmp/bmp.c | 168 ++++++++++++++++++++++++++++++++++------------------ proto/bmp/bmp.h | 17 ++++-- 5 files changed, 139 insertions(+), 75 deletions(-) (limited to 'proto/bgp/packets.c') diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 17c503c4..54da2253 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1715,7 +1715,7 @@ bgp_init(struct proto_config *CF) P->rte_igp_metric = bgp_rte_igp_metric; #ifdef CONFIG_BMP - P->rte_update_in_notify = bgp_rte_update_in_notify; + P->rte_update_in_notify = bmp_route_monitor_update_in_notify; #endif p->cf = cf; diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 5f8f183d..861f831a 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -631,11 +631,13 @@ struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool); u32 bgp_rte_igp_metric(struct rte *); void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old); int bgp_preexport(struct channel *, struct rte *); -void bgp_rte_update_in_notify(struct channel *C, const net_addr *n, const struct rte *new, const struct rte_src *src); int bgp_get_attr(const struct eattr *e, byte *buf, int buflen); void bgp_get_route_info(struct rte *, byte *buf); int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad); +struct bmp_proto; +void bgp_bmp_encode_rte(struct bgp_channel *c, struct bmp_proto *bmp, const net_addr *n, const struct rte *new, const struct rte_src *src); + #define BGP_AIGP_METRIC 1 #define BGP_AIGP_MAX U64(0xffffffffffffffff) @@ -664,8 +666,8 @@ const char * bgp_error_dsc(unsigned code, unsigned subcode); void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len); void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to); +byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf); -byte * bgp_create_end_mark(struct bgp_channel *c, byte *buf); /* Packet types */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 63ff955b..0338a887 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -2473,11 +2473,10 @@ bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type) } void -bgp_rte_update_in_notify(struct channel *C, const net_addr *n, - const struct rte *new, const struct rte_src *src) +bgp_bmp_encode_rte(struct bgp_channel *c, struct bmp_proto *bmp, const net_addr *n, + const struct rte *new, const struct rte_src *src) { -// struct bgp_proto *p = (void *) C->proto; - struct bgp_channel *c = (void *) C; +// struct bgp_proto *p = (void *) c->c.proto; byte buf[BGP_MAX_EXT_MSG_LENGTH]; byte *pkt = buf + BGP_HEADER_LENGTH; @@ -2507,7 +2506,7 @@ bgp_rte_update_in_notify(struct channel *C, const net_addr *n, return; bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE); - bmp_route_monitor_put_update_in_pre_msg(buf, end - buf); + bmp_route_monitor_put_update_in_pre_msg(bmp, buf, end - buf); } #endif /* CONFIG_BMP */ @@ -2614,6 +2613,14 @@ bgp_create_mp_end_mark(struct bgp_channel *c, byte *buf) } byte * +bgp_create_end_mark_(struct bgp_channel *c, byte *buf) +{ + return (c->afi == BGP_AF_IPV4) ? + bgp_create_ip_end_mark(c, buf): + bgp_create_mp_end_mark(c, buf); +} + +static byte * bgp_create_end_mark(struct bgp_channel *c, byte *buf) { struct bgp_proto *p = (void *) c->c.proto; @@ -2621,9 +2628,7 @@ bgp_create_end_mark(struct bgp_channel *c, byte *buf) BGP_TRACE(D_PACKETS, "Sending END-OF-RIB"); p->stats.tx_updates++; - return (c->afi == BGP_AF_IPV4) ? - bgp_create_ip_end_mark(c, buf): - bgp_create_mp_end_mark(c, buf); + return bgp_create_end_mark_(c, buf); } static inline void diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index 5c261584..aed9d9d6 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -56,8 +56,8 @@ #include "nest/iface.h" #include "nest/route.h" -// We allow for single instance of BMP protocol -static struct bmp_proto *g_bmp; +// List of BMP instances +static list STATIC_LIST_INIT(bmp_proto_list); /* BMP Common Header [RFC 7854 - Section 4.1] */ enum bmp_version { @@ -214,7 +214,7 @@ struct bmp_data_node { }; static void -bmp_route_monitor_pre_policy_table_in_snapshot(struct bgp_channel *c); +bmp_route_monitor_pre_policy_table_in_snapshot(struct bmp_proto *p, struct bgp_channel *c); static void bmp_common_hdr_serialize(buffer *stream, const enum bmp_message_type type, const u32 data_size) @@ -447,16 +447,16 @@ bmp_peer_down_notif_msg_serialize(buffer *stream, const bool is_peer_global, bmp_put_data(stream, data, data_size); } -void -bmp_peer_up(const struct bgp_proto *bgp, +static void +bmp_peer_up_(struct bmp_proto *p, const struct bgp_proto *bgp, const byte *tx_open_msg, uint tx_open_length, const byte *rx_open_msg, uint rx_open_length) { - struct bmp_proto *p = g_bmp; - - if (!p || !p->started) + if (!p->started) return; + TRACE(D_STATES, "Peer up for %s", bgp->p.name); + // struct bmp_peer_map_key key = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); // bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp)); @@ -464,11 +464,21 @@ bmp_peer_up(const struct bgp_proto *bgp, struct bgp_channel *c; BGP_WALK_CHANNELS(bgp, c) - bmp_route_monitor_pre_policy_table_in_snapshot(c); + bmp_route_monitor_pre_policy_table_in_snapshot(p, c); +} + +void +bmp_peer_up(const struct bgp_proto *bgp, + const byte *tx_open_msg, uint tx_open_length, + const byte *rx_open_msg, uint rx_open_length) +{ + struct bmp_proto *p; node *n; + WALK_LIST2(p, n, bmp_proto_list, bmp_node) + bmp_peer_up_(p, bgp, tx_open_msg, tx_open_length, rx_open_msg, rx_open_length); } static void -bmp_peer_init(const struct bgp_proto *bgp) +bmp_peer_init(struct bmp_proto *p, const struct bgp_proto *bgp) { struct bgp_conn *conn = bgp->conn; @@ -476,8 +486,8 @@ bmp_peer_init(const struct bgp_proto *bgp) !conn->local_open_msg || !conn->remote_open_msg) return; - bmp_peer_up(bgp, conn->local_open_msg, conn->local_open_length, - conn->remote_open_msg, conn->remote_open_length); + bmp_peer_up_(p, bgp, conn->local_open_msg, conn->local_open_length, + conn->remote_open_msg, conn->remote_open_length); } static const struct birdsock * @@ -569,12 +579,10 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, } -void -bmp_route_monitor_update_in_pre_begin(void) +static void +bmp_route_monitor_update_in_pre_begin_(struct bmp_proto *p) { - struct bmp_proto *p = g_bmp; - - if (!p || !p->started) + if (!p->started) return; if (p->monitoring_rib.in_pre_policy == false) @@ -592,11 +600,17 @@ bmp_route_monitor_update_in_pre_begin(void) } void -bmp_route_monitor_put_update_in_pre_msg(const byte *data, const size_t data_size) +bmp_route_monitor_update_in_pre_begin(void) { - struct bmp_proto *p = g_bmp; + struct bmp_proto *p; node *n; + WALK_LIST2(p, n, bmp_proto_list, bmp_node) + bmp_route_monitor_update_in_pre_begin_(p); +} - if (!p || !p->started) +void +bmp_route_monitor_put_update_in_pre_msg(struct bmp_proto *p, const byte *data, const size_t data_size) +{ + if (!p->started) return; if (p->monitoring_rib.in_pre_policy == false) @@ -617,11 +631,20 @@ bmp_route_monitor_put_update_in_pre_msg(const byte *data, const size_t data_size } void -bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp) +bmp_route_monitor_update_in_notify(struct channel *C, const net_addr *n, + const struct rte *new, const struct rte_src *src) { - struct bmp_proto *p = g_bmp; + struct bgp_channel *c = (void *) C; + + struct bmp_proto *p; node *nx; + WALK_LIST2(p, nx, bmp_proto_list, bmp_node) + bgp_bmp_encode_rte(c, p, n, new, src); +} - if (!p || !p->started) +static void +bmp_route_monitor_update_in_pre_commit_(struct bmp_proto *p, const struct bgp_proto *bgp) +{ + if (!p->started) return; if (p->monitoring_rib.in_pre_policy == false) @@ -670,11 +693,17 @@ bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp) } void -bmp_route_monitor_update_in_pre_end(void) +bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp) { - struct bmp_proto *p = g_bmp; + struct bmp_proto *p; node *n; + WALK_LIST2(p, n, bmp_proto_list, bmp_node) + bmp_route_monitor_update_in_pre_commit_(p, bgp); +} - if (!p || !p->started) +static void +bmp_route_monitor_update_in_pre_end_(struct bmp_proto *p) +{ + if (!p->started) return; if (p->monitoring_rib.in_pre_policy == false) @@ -692,11 +721,37 @@ bmp_route_monitor_update_in_pre_end(void) p->rt_table_in_pre_policy.update_in_progress = false; } +void +bmp_route_monitor_update_in_pre_end(void) +{ + struct bmp_proto *p; node *n; + WALK_LIST2(p, n, bmp_proto_list, bmp_node) + bmp_route_monitor_update_in_pre_end_(p); +} + static void -bmp_route_monitor_pre_policy_table_in_snapshot(struct bgp_channel *c) +bmp_route_monitor_end_of_rib_msg(struct bmp_proto *p, struct bgp_channel *c) { - struct bmp_proto *p = g_bmp; + struct bgp_proto *bgp = (void *) c->c.proto; + + TRACE(D_PACKETS, "Sending END-OF-RIB for %s.%s", bgp->p.name, c->c.name); + + byte rx_end_payload[DEFAULT_MEM_BLOCK_SIZE]; + byte *pos = bgp_create_end_mark_(c, 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_route_monitor_update_in_pre_begin_(p); + bmp_route_monitor_put_update_in_pre_msg(p, rx_end_payload, pos - rx_end_payload); + bmp_route_monitor_update_in_pre_commit_(p, bgp); + bmp_route_monitor_update_in_pre_end_(p); +} +static void +bmp_route_monitor_pre_policy_table_in_snapshot(struct bmp_proto *p, struct bgp_channel *c) +{ if (p->monitoring_rib.in_pre_policy == false) return; @@ -713,37 +768,22 @@ bmp_route_monitor_pre_policy_table_in_snapshot(struct bgp_channel *c) { P = n->routes->sender->proto; if (P->proto->class != PROTOCOL_BGP) - { continue; - } - bmp_route_monitor_update_in_pre_begin(); + bmp_route_monitor_update_in_pre_begin_(p); rte *e; for (e = n->routes; e; e = e->next) - { - bgp_rte_update_in_notify(&c->c, n->n.addr, e, e->src); - } + bgp_bmp_encode_rte(c, p, n->n.addr, e, e->src); - bmp_route_monitor_update_in_pre_commit((struct bgp_proto *) P); - bmp_route_monitor_update_in_pre_end(); + bmp_route_monitor_update_in_pre_commit_(p, (struct bgp_proto *) P); + bmp_route_monitor_update_in_pre_end_(p); ++cnt; } FIB_ITERATE_END; if (cnt > 0) - { - bmp_route_monitor_update_in_pre_begin(); - byte rx_end_payload[DEFAULT_MEM_BLOCK_SIZE]; - byte *pos = bgp_create_end_mark(c, 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_route_monitor_put_update_in_pre_msg(rx_end_payload, pos - rx_end_payload); - bmp_route_monitor_update_in_pre_commit((struct bgp_proto *) c->c.proto); - bmp_route_monitor_update_in_pre_end(); - } + bmp_route_monitor_end_of_rib_msg(p, c); } static void @@ -765,15 +805,15 @@ bmp_send_peer_down_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, bmp_buffer_free(&payload); } -void -bmp_peer_down(const struct bgp_proto *bgp, const int err_class, - const byte *msg, size_t msg_length) +static void +bmp_peer_down_(struct bmp_proto *p, const struct bgp_proto *bgp, + const int err_class, const byte *msg, size_t msg_length) { - struct bmp_proto *p = g_bmp; - - if (!p || !p->started) + if (!p->started) return; + TRACE(D_STATES, "Peer down for %s", bgp->p.name); + // struct bmp_peer_map_key key = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as); // bmp_peer_map_remove(&p->bgp_peers, key); @@ -809,6 +849,15 @@ bmp_peer_down(const struct bgp_proto *bgp, const int err_class, bmp_buffer_free(&payload); } +void +bmp_peer_down(const struct bgp_proto *bgp, const int err_class, + const byte *msg, size_t msg_length) +{ + struct bmp_proto *p; node *n; + WALK_LIST2(p, n, bmp_proto_list, bmp_node) + bmp_peer_down_(p, bgp, err_class, msg, msg_length); +} + static void bmp_send_termination_msg(struct bmp_proto *p, const enum bmp_term_reason reason) @@ -857,7 +906,7 @@ bmp_startup(struct bmp_proto *p) struct proto *peer; WALK_LIST(peer, proto_list) if ((peer->proto->class == PROTOCOL_BGP) && (peer->proto_state == PS_UP)) - bmp_peer_init((struct bgp_proto *) peer); + bmp_peer_init(p, (struct bgp_proto *) peer); proto_notify_state(&p->p, PS_UP); } @@ -905,6 +954,8 @@ bmp_connect(struct bmp_proto *p) p->sk = sk; sk->data = p; + TRACE(D_EVENTS, "Connecting to %I port %u", sk->daddr, sk->dport); + int rc = sk_open(sk); if (rc < 0) @@ -919,6 +970,8 @@ bmp_connected(struct birdsock *sk) { struct bmp_proto *p = (void *) sk->data; + TRACE(D_EVENTS, "Connected"); + sk->rx_hook = bmp_rx; sk->tx_hook = bmp_tx; tm_stop(p->connect_retry_timer); @@ -1025,11 +1078,10 @@ bmp_start(struct proto *P) init_list(&p->rt_table_in_pre_policy.update_msg_queue); p->started = false; p->sock_err = 0; + add_tail(&bmp_proto_list, &p->bmp_node); tm_start(p->connect_retry_timer, CONNECT_INIT_TIME); - g_bmp = p; - return PS_START; } @@ -1045,7 +1097,7 @@ bmp_shutdown(struct proto *P) } p->sock_err = 0; - g_bmp = NULL; + rem_node(&p->bmp_node); return PS_DOWN; } diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index be28468c..258a5089 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -57,6 +57,7 @@ struct rt_table_info { struct bmp_proto { struct proto p; // Parent proto const struct bmp_config *cf; // Shortcut to BMP configuration + node bmp_node; // Node in bmp_proto_list sock *sk; // TCP connection event *tx_ev; // TX event char sys_descr[MIB_II_STR_LEN]; // sysDescr MIB-II [RFC1213] object @@ -90,20 +91,22 @@ bmp_peer_up(const struct bgp_proto *bgp, const byte *rx_open_msg, uint rx_open_length); /** - * The following 4 functions create BMP Route Monitoring message based on + * The following 5 functions create BMP Route Monitoring message based on * pre-policy Adj-RIB-In. Composing Route Monitoring message consist of few * stages. First of all call bmp_route_monitor_update_in_pre_begin() in order * to start composing message. As a second step, call - * bmp_route_monitor_put_update_in_pre_msg() in order to save BGP UPDATE msg. - * As a third step call bmp_route_monitor_update_in_pre_commit() in order to - * send BMP Route Monitoring message to the BMP collector. As a last step, + * bmp_route_monitor_update_in_notify() to announce each rte, which internally + * calls bmp_route_monitor_put_update_in_pre_msg() in order to save BGP UPDATE + * msg. As a third step call bmp_route_monitor_update_in_pre_commit() in order + * to send BMP Route Monitoring message to the BMP collector. As a last step, * call bmp_route_monitor_update_in_pre_end() in order to release resources. */ void bmp_route_monitor_update_in_pre_begin(void); void -bmp_route_monitor_put_update_in_pre_msg(const byte *data, const size_t data_size); +bmp_route_monitor_update_in_notify(struct channel *C, const net_addr *n, + const struct rte *new, const struct rte_src *src); void bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp); @@ -111,6 +114,9 @@ bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp); void bmp_route_monitor_update_in_pre_end(void); +void +bmp_route_monitor_put_update_in_pre_msg(struct bmp_proto *p, const byte *data, const size_t data_size); + /** * bmp_peer_down - send notification that BGP peer connection is not in * established state @@ -124,7 +130,6 @@ bmp_peer_down(const struct bgp_proto *bgp, const int err_class, const byte *pkt, static inline void bmp_peer_up(const 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_route_monitor_update_in_pre_begin(void) { } -static inline void bmp_route_monitor_put_update_in_pre_msg(const byte *data UNUSED, const size_t data_size UNUSED) { } static inline void bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp UNUSED) { } static inline void bmp_route_monitor_update_in_pre_end(void) { } static inline void bmp_peer_down(const struct bgp_proto *bgp UNUSED, const int err_class UNUSED, const byte *pkt UNUSED, size_t pkt_size UNUSED) { } -- cgit v1.2.3 From 8ded8baba2a95cec81f20b10160c81d229f8fae8 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 1 Aug 2023 17:56:56 +0200 Subject: BMP: Simplify route monitoring hooks No need for *_begin(), *_commit(), and *_end() hooks. The hook *_notify() is sufficient for everything. --- proto/bgp/bgp.h | 3 +- proto/bgp/packets.c | 19 ++---- proto/bmp/bmp.c | 169 +++++++++++++++++----------------------------------- proto/bmp/bmp.h | 37 +----------- 4 files changed, 66 insertions(+), 162 deletions(-) (limited to 'proto/bgp/packets.c') diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 861f831a..324df43c 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -635,8 +635,7 @@ int bgp_get_attr(const struct eattr *e, byte *buf, int buflen); void bgp_get_route_info(struct rte *, byte *buf); int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad); -struct bmp_proto; -void bgp_bmp_encode_rte(struct bgp_channel *c, struct bmp_proto *bmp, const net_addr *n, const struct rte *new, const struct rte_src *src); +byte * bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, const net_addr *n, const struct rte *new, const struct rte_src *src); #define BGP_AIGP_METRIC 1 #define BGP_AIGP_MAX U64(0xffffffffffffffff) diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 0338a887..2f1ff659 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -2472,13 +2472,11 @@ bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type) return buf + BGP_MSG_HDR_TYPE_POS + BGP_MSG_HDR_TYPE_SIZE; } -void -bgp_bmp_encode_rte(struct bgp_channel *c, struct bmp_proto *bmp, const net_addr *n, +byte * +bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, const net_addr *n, const struct rte *new, const struct rte_src *src) { // struct bgp_proto *p = (void *) c->c.proto; - - byte buf[BGP_MAX_EXT_MSG_LENGTH]; byte *pkt = buf + BGP_HEADER_LENGTH; ea_list *attrs = new ? new->attrs->eattrs : NULL; @@ -2502,11 +2500,11 @@ bgp_bmp_encode_rte(struct bgp_channel *c, struct bmp_proto *bmp, const net_addr add_tail(&b->prefixes, &px->buck_node); byte *end = bgp_create_update_bmp(c, pkt, b, !!new); - if (!end) - return; - bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE); - bmp_route_monitor_put_update_in_pre_msg(bmp, buf, end - buf); + if (end) + bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE); + + return end; } #endif /* CONFIG_BMP */ @@ -2769,8 +2767,6 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) s.ip_reach_len = len - pos; s.ip_reach_nlri = pkt + pos; - bmp_route_monitor_update_in_pre_begin(); - if (s.attr_len) ea = bgp_decode_attrs(&s, s.attrs, s.attr_len); else @@ -2801,9 +2797,6 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) bgp_decode_nlri(&s, s.mp_reach_af, s.mp_reach_nlri, s.mp_reach_len, ea, s.mp_next_hop_data, s.mp_next_hop_len); - bmp_route_monitor_update_in_pre_commit(p); - bmp_route_monitor_update_in_pre_end(); - done: rta_free(s.cached_rta); lp_restore(tmp_linpool, &tmpp); diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index c530b3d4..1916563a 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -211,6 +211,12 @@ struct bmp_data_node { node n; byte *data; size_t data_size; + + u32 remote_as; + u32 remote_id; + ip_addr remote_ip; + btime timestamp; + bool global_peer; }; static void @@ -401,9 +407,12 @@ static void bmp_route_monitor_msg_serialize(buffer *stream, const bool is_peer_global, const bool table_in_pre_policy, const u32 peer_as, const u32 peer_bgp_id, const bool as4_support, const ip_addr remote_addr, const byte *update_msg, - const size_t update_msg_size, u32 ts_sec, u32 ts_usec) + const size_t update_msg_size, btime timestamp) { const size_t data_size = BMP_PER_PEER_HDR_SIZE + update_msg_size; + u32 ts_sec = timestamp TO_S; + u32 ts_usec = timestamp - (ts_sec S); + bmp_buffer_need(stream, BMP_COMMON_HDR_SIZE + data_size); bmp_common_hdr_serialize(stream, BMP_ROUTE_MONITOR, data_size); bmp_per_peer_hdr_serialize(stream, is_peer_global, table_in_pre_policy, @@ -581,56 +590,43 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, bmp_buffer_free(&payload); } - static void -bmp_route_monitor_update_in_pre_begin_(struct bmp_proto *p) +bmp_route_monitor_put_update(struct bmp_proto *p, const byte *data, size_t length, struct bgp_proto *bgp) { - if (!p->started) - return; - - if (p->monitoring_rib.in_pre_policy == false) - return; - - IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL( - !EMPTY_LIST(p->rt_table_in_pre_policy.update_msg_queue), - "Previous BMP route monitoring update not finished yet" - ); - - gettimeofday(&p->rt_table_in_pre_policy.update_begin_time,NULL); - init_list(&p->rt_table_in_pre_policy.update_msg_queue); - p->rt_table_in_pre_policy.update_msg_size = 0; - p->rt_table_in_pre_policy.update_in_progress = true; + struct bmp_data_node *upd_msg = mb_alloc(p->update_msg_mem_pool, + sizeof (struct bmp_data_node)); + upd_msg->data = mb_alloc(p->update_msg_mem_pool, length); + memcpy(upd_msg->data, data, length); + upd_msg->data_size = length; + add_tail(&p->update_msg_queue, &upd_msg->n); + + /* Save some metadata */ + upd_msg->remote_as = bgp->remote_as; + upd_msg->remote_id = bgp->remote_id; + upd_msg->remote_ip = bgp->remote_ip; + upd_msg->timestamp = current_time(); + upd_msg->global_peer = bmp_is_peer_global_instance(bgp); + + /* Kick the commit */ + if (!ev_active(p->update_ev)) + ev_schedule(p->update_ev); } -void -bmp_route_monitor_update_in_pre_begin(void) +static void +bmp_route_monitor_update_in_notify_(struct bmp_proto *p, struct bgp_channel *c, + const net_addr *n, const struct rte *new, const struct rte_src *src) { - struct bmp_proto *p; node *n; - WALK_LIST2(p, n, bmp_proto_list, bmp_node) - bmp_route_monitor_update_in_pre_begin_(p); -} + struct bgp_proto *bgp = (void *) c->c.proto; -void -bmp_route_monitor_put_update_in_pre_msg(struct bmp_proto *p, const byte *data, const size_t data_size) -{ if (!p->started) return; if (p->monitoring_rib.in_pre_policy == false) return; - IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL( - !p->rt_table_in_pre_policy.update_in_progress, - "BMP route monitoring update not started yet" - ); - - struct bmp_data_node *upd_msg = mb_alloc(p->update_msg_mem_pool, - sizeof (struct bmp_data_node)); - upd_msg->data = mb_alloc(p->update_msg_mem_pool, data_size); - memcpy(upd_msg->data, data, data_size); - upd_msg->data_size = data_size; - p->rt_table_in_pre_policy.update_msg_size += data_size; - add_tail(&p->rt_table_in_pre_policy.update_msg_queue, &upd_msg->n); + byte buf[BGP_MAX_EXT_MSG_LENGTH]; + byte *end = bgp_bmp_encode_rte(c, buf, n, new, src); + bmp_route_monitor_put_update(p, buf, end - buf, bgp); } void @@ -641,97 +637,50 @@ bmp_route_monitor_update_in_notify(struct channel *C, const net_addr *n, struct bmp_proto *p; node *nx; WALK_LIST2(p, nx, bmp_proto_list, bmp_node) - bgp_bmp_encode_rte(c, p, n, new, src); + bmp_route_monitor_update_in_notify_(p, c, n, new, src); } static void -bmp_route_monitor_update_in_pre_commit_(struct bmp_proto *p, const struct bgp_proto *bgp) +bmp_route_monitor_commit(void *p_) { + struct bmp_proto *p = p_; + if (!p->started) return; if (p->monitoring_rib.in_pre_policy == false) return; - const struct birdsock *sk = bmp_get_birdsock(bgp); - IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL( - sk, - "Failed to get bird socket from BGP proto" - ); - - const struct bgp_caps *remote_caps = bmp_get_bgp_remote_caps(bgp); - IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL( - remote_caps, - "Failed to get remote capabilities from BGP proto" - ); - - bool is_global_instance_peer = bmp_is_peer_global_instance(bgp); buffer payload - = bmp_buffer_alloc(p->buffer_mpool, - p->rt_table_in_pre_policy.update_msg_size + DEFAULT_MEM_BLOCK_SIZE); + = bmp_buffer_alloc(p->buffer_mpool, DEFAULT_MEM_BLOCK_SIZE); buffer update_msgs - = bmp_buffer_alloc(p->buffer_mpool, - p->rt_table_in_pre_policy.update_msg_size); + = bmp_buffer_alloc(p->buffer_mpool, BGP_MAX_EXT_MSG_LENGTH); - struct bmp_data_node *data; - WALK_LIST(data, p->rt_table_in_pre_policy.update_msg_queue) + struct bmp_data_node *data, *data_next; + WALK_LIST_DELSAFE(data, data_next, p->update_msg_queue) { bmp_put_data(&update_msgs, data->data, data->data_size); bmp_route_monitor_msg_serialize(&payload, - is_global_instance_peer, true /* TODO: Hardcoded pre-policy Adj-Rib-In */, - bgp->conn->received_as, bgp->remote_id, remote_caps->as4_support, - sk->daddr, bmp_buffer_data(&update_msgs), bmp_buffer_pos(&update_msgs), - p->rt_table_in_pre_policy.update_begin_time.tv_sec, - p->rt_table_in_pre_policy.update_begin_time.tv_usec); + data->global_peer, true /* TODO: Hardcoded pre-policy Adj-Rib-In */, + data->remote_as, data->remote_id, true, + data->remote_ip, bmp_buffer_data(&update_msgs), bmp_buffer_pos(&update_msgs), + data->timestamp); bmp_schedule_tx_packet(p, bmp_buffer_data(&payload), bmp_buffer_pos(&payload)); bmp_buffer_flush(&payload); bmp_buffer_flush(&update_msgs); + + mb_free(data->data); + rem_node(&data->n); + mb_free(data); } bmp_buffer_free(&payload); bmp_buffer_free(&update_msgs); } -void -bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp) -{ - struct bmp_proto *p; node *n; - WALK_LIST2(p, n, bmp_proto_list, bmp_node) - bmp_route_monitor_update_in_pre_commit_(p, bgp); -} - -static void -bmp_route_monitor_update_in_pre_end_(struct bmp_proto *p) -{ - if (!p->started) - return; - - if (p->monitoring_rib.in_pre_policy == false) - return; - - struct bmp_data_node *upd_msg; - struct bmp_data_node *upd_msg_next; - WALK_LIST_DELSAFE(upd_msg, upd_msg_next, p->rt_table_in_pre_policy.update_msg_queue) - { - mb_free(upd_msg->data); - rem_node((node *) upd_msg); - mb_free(upd_msg); - } - - p->rt_table_in_pre_policy.update_in_progress = false; -} - -void -bmp_route_monitor_update_in_pre_end(void) -{ - struct bmp_proto *p; node *n; - WALK_LIST2(p, n, bmp_proto_list, bmp_node) - bmp_route_monitor_update_in_pre_end_(p); -} - static void bmp_route_monitor_end_of_rib_msg(struct bmp_proto *p, struct bgp_channel *c) { @@ -746,10 +695,7 @@ bmp_route_monitor_end_of_rib_msg(struct bmp_proto *p, struct bgp_channel *c) 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_route_monitor_update_in_pre_begin_(p); - bmp_route_monitor_put_update_in_pre_msg(p, rx_end_payload, pos - rx_end_payload); - bmp_route_monitor_update_in_pre_commit_(p, bgp); - bmp_route_monitor_update_in_pre_end_(p); + bmp_route_monitor_put_update(p, rx_end_payload, pos - rx_end_payload, bgp); } static void @@ -773,14 +719,10 @@ bmp_route_monitor_pre_policy_table_in_snapshot(struct bmp_proto *p, struct bgp_c if (P->proto->class != PROTOCOL_BGP) continue; - bmp_route_monitor_update_in_pre_begin_(p); - rte *e; for (e = n->routes; e; e = e->next) - bgp_bmp_encode_rte(c, p, n->n.addr, e, e->src); + bmp_route_monitor_update_in_notify_(p, c, n->n.addr, e, e->src); - bmp_route_monitor_update_in_pre_commit_(p, (struct bgp_proto *) P); - bmp_route_monitor_update_in_pre_end_(p); ++cnt; } FIB_ITERATE_END; @@ -1071,14 +1013,15 @@ bmp_start(struct proto *P) p->map_mem_pool = rp_new(P->pool, "BMP Map"); p->tx_mem_pool = rp_new(P->pool, "BMP Tx"); p->update_msg_mem_pool = rp_new(P->pool, "BMP Update"); - p->tx_ev = ev_new_init(p->tx_mem_pool, bmp_fire_tx, p); + p->tx_ev = ev_new_init(p->p.pool, bmp_fire_tx, p); + p->update_ev = ev_new_init(p->p.pool, bmp_route_monitor_commit, p); p->connect_retry_timer = tm_new_init(p->p.pool, bmp_connection_retry, p, 0, 0); p->sk = NULL; // bmp_peer_map_init(&p->bgp_peers, p->map_mem_pool); init_list(&p->tx_queue); - init_list(&p->rt_table_in_pre_policy.update_msg_queue); + init_list(&p->update_msg_queue); p->started = false; p->sock_err = 0; add_tail(&bmp_proto_list, &p->bmp_node); diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index 258a5089..0c355754 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -45,21 +45,13 @@ struct bmp_config { struct bgp_proto; struct bmp_proto; -// Keeps necessary information during composing BGP UPDATE MSG which is going -// to be sent to the BMP collector -struct rt_table_info { - list update_msg_queue; // Stores all composed BGP UPDATE MSGs - size_t update_msg_size; // Size of all BGP UPDATE MSGs - struct timeval update_begin_time; // Keeps timestamp of starting BGP UPDATE MSGs composing - bool update_in_progress; // Holds information whether composing process is still in progress -}; - struct bmp_proto { struct proto p; // Parent proto const struct bmp_config *cf; // Shortcut to BMP configuration node bmp_node; // Node in bmp_proto_list sock *sk; // TCP connection event *tx_ev; // TX event + event *update_ev; // Update event char sys_descr[MIB_II_STR_LEN]; // sysDescr MIB-II [RFC1213] object char sys_name[MIB_II_STR_LEN]; // sysName MIB-II [RFC1213] object ip_addr local_addr; // Source local IP address @@ -74,7 +66,7 @@ struct bmp_proto { pool *update_msg_mem_pool; // Memory pool used for BPG UPDATE MSG allocations list tx_queue; // Stores queued packets going to be sent timer *connect_retry_timer; // Timer for retrying connection to the BMP collector - struct rt_table_info rt_table_in_pre_policy; // Pre-policy route import table + list update_msg_queue; // Stores all composed BGP UPDATE MSGs bool started; // Flag that stores running status of BMP instance int sock_err; // Last socket error code }; @@ -91,32 +83,12 @@ bmp_peer_up(const struct bgp_proto *bgp, const byte *rx_open_msg, uint rx_open_length); /** - * The following 5 functions create BMP Route Monitoring message based on - * pre-policy Adj-RIB-In. Composing Route Monitoring message consist of few - * stages. First of all call bmp_route_monitor_update_in_pre_begin() in order - * to start composing message. As a second step, call - * bmp_route_monitor_update_in_notify() to announce each rte, which internally - * calls bmp_route_monitor_put_update_in_pre_msg() in order to save BGP UPDATE - * msg. As a third step call bmp_route_monitor_update_in_pre_commit() in order - * to send BMP Route Monitoring message to the BMP collector. As a last step, - * call bmp_route_monitor_update_in_pre_end() in order to release resources. + * bmp_route_monitor_update_in_notify - send notification that rte vas received */ -void -bmp_route_monitor_update_in_pre_begin(void); - void bmp_route_monitor_update_in_notify(struct channel *C, const net_addr *n, const struct rte *new, const struct rte_src *src); -void -bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp); - -void -bmp_route_monitor_update_in_pre_end(void); - -void -bmp_route_monitor_put_update_in_pre_msg(struct bmp_proto *p, const byte *data, const size_t data_size); - /** * bmp_peer_down - send notification that BGP peer connection is not in * established state @@ -129,9 +101,6 @@ bmp_peer_down(const struct bgp_proto *bgp, const int err_class, const byte *pkt, #else /* BMP build disabled */ static inline void bmp_peer_up(const 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_route_monitor_update_in_pre_begin(void) { } -static inline void bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp UNUSED) { } -static inline void bmp_route_monitor_update_in_pre_end(void) { } static inline void bmp_peer_down(const struct bgp_proto *bgp UNUSED, const int err_class UNUSED, const byte *pkt UNUSED, size_t pkt_size UNUSED) { } #endif /* CONFIG_BMP */ -- cgit v1.2.3 From 4558adabfbbe3696156d20767168010d6238f434 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Tue, 22 Aug 2023 01:24:21 +0200 Subject: BMP: Improve peer_down handling Move all bmp_peer_down() calls to one place and make it synchronous with BGP session down, ensuring that BMP receives peer_down before route withdraws from flushing. Also refactor bmp_peer_down_() message generating code. --- proto/bgp/bgp.c | 25 ++++++++++--------- proto/bgp/packets.c | 8 ++++--- proto/bmp/bmp.c | 69 ++++++++++++++++++++++++++++++++++------------------- proto/bmp/bmp.h | 7 +++--- 4 files changed, 64 insertions(+), 45 deletions(-) (limited to 'proto/bgp/packets.c') diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index ccaa5067..a6e9cf83 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -391,6 +391,9 @@ bgp_close_conn(struct bgp_conn *conn) conn->local_caps = NULL; mb_free(conn->remote_caps); conn->remote_caps = NULL; + + conn->notify_data = NULL; + conn->notify_size = 0; } @@ -694,7 +697,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) } static void -bgp_conn_leave_established_state(struct bgp_proto *p) +bgp_conn_leave_established_state(struct bgp_conn *conn, struct bgp_proto *p) { BGP_TRACE(D_EVENTS, "BGP session closed"); p->last_established = current_time(); @@ -702,6 +705,10 @@ bgp_conn_leave_established_state(struct bgp_proto *p) if (p->p.proto_state == PS_UP) bgp_stop(p, 0, NULL, 0); + + bmp_peer_down(p, p->last_error_class, + conn->notify_code, conn->notify_subcode, + conn->notify_data, conn->notify_size); } void @@ -718,7 +725,7 @@ bgp_conn_enter_close_state(struct bgp_conn *conn) bgp_start_timer(conn->hold_timer, 10); if (os == BS_ESTABLISHED) - bgp_conn_leave_established_state(p); + bgp_conn_leave_established_state(conn, p); } void @@ -732,7 +739,7 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn) ev_schedule(p->event); if (os == BS_ESTABLISHED) - bgp_conn_leave_established_state(p); + bgp_conn_leave_established_state(conn, p); } /** @@ -876,10 +883,7 @@ bgp_graceful_restart_timeout(timer *t) } } else - { bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_NONE, NULL, 0); - } } static void @@ -1003,10 +1007,7 @@ bgp_sock_err(sock *sk, int err) if (err) BGP_TRACE(D_EVENTS, "Connection lost (%M)", err); else - { BGP_TRACE(D_EVENTS, "Connection closed"); - bmp_peer_down(p, BE_SOCKET, NULL, 0); - } if ((conn->state == BS_ESTABLISHED) && p->gr_ready) bgp_handle_graceful_restart(p); @@ -1331,7 +1332,6 @@ bgp_neigh_notify(neighbor *n) bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST); /* Perhaps also run bgp_update_startup_delay(p)? */ bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_MISC, NULL, 0); } } else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP)) @@ -1343,7 +1343,6 @@ bgp_neigh_notify(neighbor *n) if (ps == PS_UP) bgp_update_startup_delay(p); bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_MISC, NULL, 0); } } else @@ -1385,7 +1384,6 @@ bgp_bfd_notify(struct bfd_request *req) if (ps == PS_UP) bgp_update_startup_delay(p); bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_MISC, NULL, 0); } } } @@ -2266,12 +2264,13 @@ bgp_error(struct bgp_conn *c, uint code, uint subcode, byte *data, int len) bgp_log_error(p, BE_BGP_TX, "Error", code, subcode, data, ABS(len)); bgp_store_error(p, c, BE_BGP_TX, (code << 16) | subcode); - bgp_conn_enter_close_state(c); c->notify_code = code; c->notify_subcode = subcode; c->notify_data = data; c->notify_size = (len > 0) ? len : 0; + + bgp_conn_enter_close_state(c); bgp_schedule_packet(c, NULL, PKT_NOTIFICATION); if (code != 6) diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 2f1ff659..6b728b4e 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -3042,7 +3042,6 @@ bgp_fire_tx(struct bgp_conn *conn) { conn->packets_to_send = 1 << PKT_SCHEDULE_CLOSE; end = bgp_create_notification(conn, pkt); - bmp_peer_down(p, BE_BGP_TX, pkt, end - pkt); return bgp_send(conn, PKT_NOTIFICATION, end - buf); } else if (s & (1 << PKT_OPEN)) @@ -3334,6 +3333,11 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len) bgp_log_error(p, BE_BGP_RX, "Received", code, subcode, pkt+21, len-21); bgp_store_error(p, conn, BE_BGP_RX, (code << 16) | subcode); + conn->notify_code = code; + conn->notify_subcode = subcode; + conn->notify_data = pkt+21; + conn->notify_size = len-21; + bgp_conn_enter_close_state(conn); bgp_schedule_packet(conn, NULL, PKT_SCHEDULE_CLOSE); @@ -3352,8 +3356,6 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len) p->p.disabled = 1; } } - - bmp_peer_down(p, BE_BGP_RX, pkt + BGP_HEADER_LENGTH, len - BGP_HEADER_LENGTH); } static void diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index 22b9f2fb..261e9fdd 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -888,7 +888,7 @@ bmp_send_peer_down_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, static void bmp_peer_down_(struct bmp_proto *p, const struct bgp_proto *bgp, - const int err_class, const byte *msg, size_t msg_length) + int err_class, int err_code, int err_subcode, const byte *data, int length) { if (!p->started) return; @@ -899,31 +899,43 @@ bmp_peer_down_(struct bmp_proto *p, const struct bgp_proto *bgp, TRACE(D_STATES, "Peer down for %s", bgp->p.name); - buffer payload = bmp_buffer_alloc(p->buffer_mpool, 1 + BGP_HEADER_LENGTH + msg_length); + uint bmp_code = 0; + uint fsm_code = 0; - if (msg) + switch (err_class) { - if (err_class == BE_BGP_TX) - bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION); - else - bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION); - - bmp_put_bgp_hdr(&payload, BGP_HEADER_LENGTH + msg_length, PKT_NOTIFICATION); - bmp_put_data(&payload, msg, msg_length); + case BE_BGP_RX: + bmp_code = BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION; + break; + + case BE_BGP_TX: + case BE_AUTO_DOWN: + case BE_MAN_DOWN: + bmp_code = BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION; + break; + + default: + bmp_code = BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION; + length = 0; + break; } - else + + buffer payload = bmp_buffer_alloc(p->buffer_mpool, 1 + BGP_HEADER_LENGTH + 2 + length); + bmp_put_u8(&payload, bmp_code); + + switch (bmp_code) { - // TODO: Handle De-configured Peer Down Reason Code - if (err_class == BE_SOCKET || err_class == BE_MISC) - { - bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION); - } - else - { - bmp_put_u8(&payload, BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION); - // TODO: Fill in with appropriate FSM event code - bmp_put_u16(&payload, 0x00); // no relevant Event code is defined - } + case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION: + case BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION: + bmp_put_bgp_hdr(&payload, BGP_HEADER_LENGTH + 2 + length, PKT_NOTIFICATION); + bmp_put_u8(&payload, err_code); + bmp_put_u8(&payload, err_subcode); + bmp_put_data(&payload, data, length); + break; + + case BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION: + bmp_put_u16(&payload, fsm_code); + break; } bmp_send_peer_down_notif_msg(p, bgp, bmp_buffer_data(&payload), bmp_buffer_pos(&payload)); @@ -934,12 +946,12 @@ bmp_peer_down_(struct bmp_proto *p, const struct bgp_proto *bgp, } void -bmp_peer_down(const struct bgp_proto *bgp, const int err_class, - const byte *msg, size_t msg_length) +bmp_peer_down(const struct bgp_proto *bgp, + int err_class, int code, int subcode, const byte *data, int length) { struct bmp_proto *p; node *n; WALK_LIST2(p, n, bmp_proto_list, bmp_node) - bmp_peer_down_(p, bgp, err_class, msg, msg_length); + bmp_peer_down_(p, bgp, err_class, code, subcode, data, length); } static void @@ -988,6 +1000,13 @@ bmp_rt_notify(struct proto *P, struct channel *c, struct network *net, struct bgp_proto *bgp = (void *) src->c.proto; bool policy = (c->table == src->c.table); + /* + * We assume that we receive peer_up before the first route and peer_down + * synchronously with BGP session close. So if bmp_stream exists, the related + * BGP session is up and could be accessed. That may not be true in + * multithreaded setup. + */ + struct bmp_stream *bs = bmp_find_stream(p, bgp, src->afi, policy); if (!bs) return; diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index e51c2ea0..2d700c25 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -116,14 +116,13 @@ bmp_peer_up(struct bgp_proto *bgp, * established state */ void -bmp_peer_down(const struct bgp_proto *bgp, const int err_class, const byte *pkt, - size_t pkt_size); +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(const 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, const byte *pkt UNUSED, size_t pkt_size UNUSED) { } +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 */ -- cgit v1.2.3