diff --git a/nest/proto.c b/nest/proto.c index 0856ec70..337df097 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -3023,9 +3023,18 @@ proto_announce_state_locked(struct proto_state_table_private* ts, struct proto * ASSERT_DIE(p->id < ts->length_states); ea_list *old_attr = ts->states[p->id]; + + if (attr == old_attr) + { + /* Nothing has changed */ + ea_free_later(attr); + return; + } + ts->states[p->id] = attr; - p->ea_state = attr; + ea_free_later(p->ea_state); + p->ea_state = attr ? ea_ref(attr) : NULL; struct proto_pending_update *pupdate = SKIP_BACK(struct proto_pending_update, li, lfjour_push_prepare(&proto_state_table_pub.journal)); @@ -3052,6 +3061,30 @@ proto_announce_state(struct proto *p, ea_list *attr) proto_announce_state_locked(ts, p, attr); } +struct proto_announce_state_deferred { + struct deferred_call dc; + struct proto *p; +}; + +static void proto_announce_state_deferred(struct deferred_call *dc) +{ + SKIP_BACK_DECLARE(struct proto_announce_state_deferred, pasd, dc, dc); + proto_announce_state(pasd->p, pasd->p->ea_state); +} + +void +proto_announce_state_later(struct proto *p, ea_list *attr) +{ + ea_free_later(p->ea_state); + p->ea_state = ea_lookup(attr, 0, EALS_CUSTOM); + + struct proto_announce_state_deferred pasd = { + .dc.hook = proto_announce_state_deferred, + .p = p, + }; + + defer_call(&pasd.dc, sizeof pasd); +} ea_list * channel_get_state(int id) diff --git a/nest/protocol.h b/nest/protocol.h index 75a942d9..8f9723d9 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -445,6 +445,7 @@ struct proto_pending_update { void proto_announce_state_locked(struct proto_state_table_private *ts, struct proto *p, ea_list *attr); void proto_announce_state(struct proto *p, ea_list *attr); +void proto_announce_state_later(struct proto *p, ea_list *attr); ea_list *channel_get_state(int id); ea_list *proto_get_state(int id); void proto_states_subscribe(struct lfjour_recipient *r); diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index bdfba942..5f297872 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -800,14 +800,13 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) #ifdef CONFIG_BMP - ea_list *ea_l = proto_get_state(p->p.id); + ea_list *ea_l = p->p.ea_state; ea_set_attr(&ea_l, EA_LITERAL_STORE_ADATA(&ea_bgp_local_open_msg, 0, conn->local_open_msg, conn->local_open_length)); ea_set_attr(&ea_l, EA_LITERAL_STORE_ADATA(&ea_bgp_remote_open_msg, 0, conn->remote_open_msg, conn->remote_open_length)); ea_set_attr(&ea_l, EA_LITERAL_EMBEDDED(&ea_bgp_local_open_msg_len, 0, conn->local_open_length)); ea_set_attr(&ea_l, EA_LITERAL_EMBEDDED(&ea_bgp_remote_open_msg_len, 0, conn->remote_open_length)); - ea_l = ea_lookup(ea_l, 0, EALS_CUSTOM); - proto_announce_state(&p->p, ea_l); + proto_announce_state_later(&p->p, ea_l); #endif }