From: Ondrej Zajicek Date: Tue, 3 Dec 2024 18:40:21 +0000 (+0100) Subject: Merge commit 'a47704a53db4f088e52e43f8b24785e5777ce147' into thread-next X-Git-Tag: v3.0.0~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=63221eba2ecaaea6e9ae4aec8c591c29443b7e79;p=thirdparty%2Fbird.git Merge commit 'a47704a53db4f088e52e43f8b24785e5777ce147' into thread-next --- 63221eba2ecaaea6e9ae4aec8c591c29443b7e79 diff --cc proto/bgp/packets.c index 33f46a8fd,81f0d3c4e..157843a62 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@@ -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 19c187ed2,9603c4e8a..aefb195d4 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@@ -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); + } } /**