#define _BIRD_LIB_ROUTE_H_
#undef RT_SOURCE_DEBUG
-#define EA_FREE_DEBUG
+#undef EA_FREE_DEBUG
#include "lib/type.h"
#include "lib/rcu.h"
init_list(&c->roa_subscriptions);
- /* Announcing existence of the channel */
+ /* Create the channel information ea_list */
+ struct ea_list *ca = NULL;
+
+ ea_set_attr(&ca, EA_LITERAL_STORE_STRING(&ea_name, 0, c->name));
+ ea_set_attr(&ca, EA_LITERAL_EMBEDDED(&ea_proto_id, 0, c->proto->id));
+ ea_set_attr(&ca, EA_LITERAL_EMBEDDED(&ea_channel_id, 0, c->id));
+ ea_set_attr(&ca, EA_LITERAL_EMBEDDED(&ea_in_keep, 0, c->in_keep));
+ ea_set_attr(&ca, EA_LITERAL_STORE_PTR(&ea_rtable, 0, c->table));
+
+ /* Announcing existence of the channel
+ * TODO: make this an actual notification */
PST_LOCKED(ts)
{
/* Allocating channel ID */
ts->length_channels = ts->length_channels * 2;
}
- /* Create the actual channel information */
- struct ea_list *ca = NULL;
-
- ea_set_attr(&ca, EA_LITERAL_STORE_STRING(&ea_name, 0, c->name));
- ea_set_attr(&ca, EA_LITERAL_EMBEDDED(&ea_proto_id, 0, c->proto->id));
- ea_set_attr(&ca, EA_LITERAL_EMBEDDED(&ea_channel_id, 0, c->id));
- ea_set_attr(&ca, EA_LITERAL_EMBEDDED(&ea_in_keep, 0, c->in_keep));
- ea_set_attr(&ca, EA_LITERAL_STORE_PTR(&ea_rtable, 0, c->table));
-
ASSERT_DIE(c->id < ts->length_channels);
ASSERT_DIE(ts->channels[c->id] == NULL);
- ts->channels[c->id] = ea_lookup_slow(ca, 0, EALS_IN_TABLE);
- /* Update channel list in protocol state */
- ASSERT_DIE(c->proto->id < ts->length_states);
+ /* Set the channel info */
+ ts->channels[c->id] = ea_lookup_slow(ca, 0, EALS_IN_TABLE);
+ }
- ea_set_attr(&p->ea_state,
+ /* Update channel list in protocol state */
+ struct ea_list *pes = p->ea_state;
+ ea_set_attr(&pes,
EA_LITERAL_DIRECT_ADATA(&ea_proto_channel_list, 0, int_set_add(
- tmp_linpool, ea_get_adata(p->ea_state, &ea_proto_channel_list), c->id)));
-
- ea_lookup(p->ea_state, 0, EALS_CUSTOM);
- proto_announce_state_locked(ts, c->proto, p->ea_state);
- }
+ tmp_linpool, ea_get_adata(pes, &ea_proto_channel_list), c->id)));
+ proto_announce_state_later(c->proto, pes);
CALL(c->class->init, c, cf);
CD(c, "Removed", c->name);
- ea_set_attr(&p->ea_state,
+ struct ea_list *pes = p->ea_state;
+ ea_set_attr(&pes,
EA_LITERAL_DIRECT_ADATA(&ea_proto_channel_list, 0, int_set_del(
tmp_linpool, ea_get_adata(p->ea_state, &ea_proto_channel_list), c->id)));
- ea_lookup(p->ea_state, 0, EALS_CUSTOM);
- proto_announce_state(c->proto, p->ea_state);
+ proto_announce_state_later(c->proto, pes);
+ /*
+ * This may cause trouble if some protocol flaps really really fast,
+ * like trying to read channel info of a nonexistent channel,
+ * but until something like this actually happens in production,
+ * we are going to fix this anyway.
+ *
+ * (Famous last words by Maria.)
+ */
PST_LOCKED(ts)
{
ASSERT_DIE(c->id < ts->length_channels);
p->mrtdump = cf->mrtdump;
p->name = cf->name;
p->proto = cf->protocol;
+ p->proto_state = PS_DOWN_XX;
+ p->last_state_change = current_time();
+
p->net_type = cf->net_type;
p->disabled = cf->disabled;
p->hash_key = random_u32();
init_list(&p->channels);
/*
- Making first version of proto eatters.
+ Initial version of protocol state.
*/
struct ea_list *state = NULL;
ea_set_attr(&state, EA_LITERAL_EMBEDDED(&ea_proto_id, 0, p->id));
ea_set_attr(&state, EA_LITERAL_STORE_ADATA(&ea_proto_channel_list, 0, NULL, 0));
- proto_announce_state(p, state);
+ proto_announce_state_later(p, state);
return p;
}
struct proto *p = pr->init(c);
p->loop = &main_birdloop;
- p->proto_state = PS_DOWN_XX;
- p->last_state_change = current_time();
p->vrf = c->vrf;
proto_add_after(&global_proto_list, p, after);
+ proto_announce_state(p, p->ea_state);
+
p->event = ev_new_init(proto_pool, proto_event, p);
PD(p, "Initializing%s", p->disabled ? " [disabled]" : "");
{
OBSREF_CLEAR(p->global_config);
OBSREF_SET(p->global_config, new);
+ proto_announce_state(p, p->ea_state);
PROTO_LEAVE_FROM_MAIN(proto_loop);
continue;
}
}
p->reconfiguring = 1;
+ proto_announce_state(p, p->ea_state);
PROTO_LEAVE_FROM_MAIN(proto_loop);
proto_rethink_goal(p);
struct proto_config *nc = p->cf_new;
struct proto *after = p->n.prev;
- proto_announce_state(p, NULL);
-
DBG("%s has shut down for reconfiguration\n", p->name);
p->cf->proto = NULL;
OBSREF_CLEAR(p->global_config);
proto_remove_channels(p);
+
+ proto_announce_state(p, NULL);
+
proto_rem_node(&global_proto_list, p);
rfree(p->event);
mb_free(p->message);
void
proto_notify_state(struct proto *p, uint state)
{
+ ASSERT_DIE(birdloop_inside(p->loop));
+
uint ps = p->proto_state;
DBG("%s reporting state transition %s -> %s\n", p->name, p_states[ps], p_states[state]);
+ /* If nothing happened, announce possible pending extended states immediately */
if (state == ps)
- return;
+ return proto_announce_state(p, p->ea_state);
p->proto_state = state;
p->last_state_change = current_time();
- ea_set_attr(&p->ea_state, EA_LITERAL_EMBEDDED(&ea_state, 0, p->proto_state));
- ea_lookup(p->ea_state, 0, EALS_CUSTOM);
- proto_announce_state(p, p->ea_state);
-
switch (state)
{
case PS_START:
bug("%s: Invalid state %d", p->name, ps);
}
+ ea_list *pes = p->ea_state;
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_state, 0, p->proto_state));
+ ea_set_attr(&pes, EA_LITERAL_STORE_ADATA(&ea_last_modified, 0, &p->last_state_change, sizeof(btime)));
+ proto_announce_state(p, pes);
+
proto_log_state_change(p);
}
}
static void
-proto_journal_item_cleanup_(ea_list *proto_attr, ea_list *old_attr)
+proto_journal_item_cleanup_(bool withdrawal, ea_list *old_attr)
{
+ /* The old attrs can be finally unref'd */
ea_free_later(old_attr);
- if (!proto_attr)
+ if (!withdrawal)
+ return;
+
+ /* The protocol itself is finished, cleanup its ID
+ * The protocol's structure may be already gone,
+ * the only thing left is the ID and the old attributes. */
+ PST_LOCKED(tp)
{
- PST_LOCKED(tp)
- {
- int p_id = ea_get_int(old_attr, &ea_proto_id, 0);
- hmap_clear(&tp->proto_id_map, p_id);
- tp->states[p_id] = NULL;
- }
+ u32 id = ea_get_int(old_attr, &ea_proto_id, 0);
+ ASSERT_DIE(id);
+ ASSERT_DIE(tp->states[id] == NULL);
+ hmap_clear(&tp->proto_id_map, id);
}
}
{
/* Called after a journal update was has been read. */
struct proto_pending_update *pupdate = SKIP_BACK(struct proto_pending_update, li, i);
- proto_journal_item_cleanup_(pupdate->proto_attr, pupdate->old_proto_attr);
+ proto_journal_item_cleanup_(!pupdate->new, pupdate->old);
}
+/*
+ * Protocol state announcement.
+ *
+ * The authoritative protocol state is always stored in ts->states[p->id]
+ * and it holds a reference. But sometimes it's too clumsy to announce all
+ * protocol changes happening in a fast succession, so there is a
+ * state-to-be-announced stored in the protocol itself, in p->ea_state.
+ * That one is also a reference.
+ *
+ * The usage pattern is simple. First, you need to have a local ea_list copy.
+ * ea_list *pes = p->ea_state;
+ *
+ * Then you update the state.
+ * ea_set_attr(&pes, EA_LITERAL_...);
+ * (possibly more of these)
+ *
+ * And finally, you queue the change for announcement.
+ * proto_announce_state_later(p, pes);
+ *
+ * Alternatively, if you need immediate announcement and no table is locked.
+ * proto_announce_state(p, pes);
+ *
+ * In all cases, the p->ea_state is updated immediately, and the public state
+ * is either updated directly (involving a table lock!) or the update is
+ * deferred after the current task ends.
+ *
+ * Never update p->ea_state from outside these functions.
+ * Also never access p->ea_state from outside the protocol context.
+ * It's a local copy for the protocol itself. From outside, always read the
+ * public state table.
+ *
+ * Also no explicit referencing or EAs is needed outside these functions,
+ * the reference lifecycle is complete here.
+ */
+
+struct proto_announce_state_deferred {
+ struct deferred_call dc;
+ struct proto *p;
+};
+
void
-proto_announce_state_locked(struct proto_state_table_private* ts, struct proto *p, ea_list *attr)
+proto_announce_state_locked(struct proto_state_table_private* ts, struct proto *p, ea_list *new_state)
{
- /*
- Should be called each time one (or more) variables tracked in proto eattrs changes.
- Changes proto eattrs and activates journal.
- */
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_last_modified, 0, &p->last_state_change, sizeof(btime)));
+ ASSERT_DIE(birdloop_inside(p->loop));
- attr = ea_lookup(attr, 0, EALS_CUSTOM);
-
- ASSERT_DIE(p->id < ts->length_states);
- ea_list *old_attr = ts->states[p->id];
+ /* Cancel the previous deferred announcement */
+ if (p->deferred_state_announcement)
+ {
+ p->deferred_state_announcement->p = NULL;
+ p->deferred_state_announcement = NULL;
+ }
- if (attr == old_attr)
+ /* First we update the state-to-be-stored */
+ if (new_state != p->ea_state)
{
- /* Nothing has changed */
- ea_free_later(attr);
- return;
+ if (p->ea_state)
+ ea_free_later(p->ea_state);
+
+ p->ea_state = new_state ? ea_lookup(new_state, 0, EALS_IN_TABLE) : NULL;
}
- ts->states[p->id] = attr;
+ /* Then we check the public state */
+ ASSERT_DIE(p->id < ts->length_states);
+ ea_list *old_state = ts->states[p->id];
- if (p->ea_state && p->ea_state->stored)
- ea_free_later(p->ea_state);
- p->ea_state = attr ? ea_ref(attr) : NULL;
+ /* Nothing has changed? */
+ if (p->ea_state == old_state)
+ return;
- struct proto_pending_update *pupdate = SKIP_BACK(struct proto_pending_update, li, lfjour_push_prepare(&proto_state_table_pub.journal));
+ /* Set the new state */
+ ts->states[p->id] = p->ea_state ? ea_ref(p->ea_state) : NULL;
- if (!pupdate)
+ /* Announce the new state */
+ struct lfjour_item *li = lfjour_push_prepare(&proto_state_table_pub.journal);
+ if (!li)
{
- proto_journal_item_cleanup_(attr, old_attr);
+ /* No reader, cleanup immediately
+ * There is another version of this code in
+ * proto_journal_item_cleanup_() but it must
+ * be kept separated because of locking. */
+ ea_free_later(old_state);
+
+ /* Protocol ID cleanup */
+ if (!p->ea_state)
+ hmap_clear(&ts->proto_id_map, p->id);
+
return;
}
- *pupdate = (struct proto_pending_update) {
- .li = pupdate->li, /* Keep the item's internal state */
- .proto_attr = attr,
- .old_proto_attr = old_attr,
- .protocol = p
+ SKIP_BACK_DECLARE(struct proto_pending_update, ppu, li, li);
+ *ppu = (struct proto_pending_update) {
+ .li = ppu->li, /* Keep the item's internal state */
+ .new = p->ea_state,
+ .old = old_state,
};
lfjour_push_commit(&proto_state_table_pub.journal);
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);
+ if (pasd->p)
+ proto_announce_state(pasd->p, pasd->p->ea_state);
}
void
-proto_announce_state_later(struct proto *p, ea_list *attr)
+proto_announce_state_later_internal(struct proto *p, ea_list *new_state)
{
+ /* Cancel the previous deferred announcement */
+ if (p->deferred_state_announcement)
+ p->deferred_state_announcement->p = NULL;
+
+ /* The old stored state isn't needed any more */
ea_free_later(p->ea_state);
- p->ea_state = ea_lookup(attr, 0, EALS_CUSTOM);
+ /* Store the new one */
+ p->ea_state = ea_lookup(new_state, 0, EALS_IN_TABLE);
+
+ /* Defer the rest */
struct proto_announce_state_deferred pasd = {
.dc.hook = proto_announce_state_deferred,
.p = p,
};
- defer_call(&pasd.dc, sizeof pasd);
+ p->deferred_state_announcement =
+ SKIP_BACK(struct proto_announce_state_deferred, dc,
+ defer_call(&pasd.dc, sizeof pasd));
}
ea_list *
char *message; /* State-change message, allocated from proto_pool */
u32 id; /* Sequential ID used as index in proto_state_table */
ea_list *ea_state; /* Last stored protocol state in proto_state_table (cached) */
+ struct proto_announce_state_deferred *deferred_state_announcement;
/*
* General protocol hooks:
struct proto_pending_update {
LFJOUR_ITEM_INHERIT(li);
- ea_list *proto_attr;
- ea_list *old_proto_attr;
- struct proto *protocol;
+ ea_list *new, *old;
};
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);
+
+void proto_announce_state_later_internal(struct proto *p, ea_list *attr);
+#if 0
+#define proto_announce_state_later(p, a) ( log(L_INFO "proto_announce_state_later(%s (%p), %p) at %s:%d", (p)->name, (p), (a), __FILE__, __LINE__), proto_announce_state_later_internal((p), (a)) )
+#else
+#define proto_announce_state_later proto_announce_state_later_internal
+#endif
+
+static inline void
+proto_update_extended_state(struct proto *p, eattr ea)
+{
+ ea_list *pes = p->ea_state;
+ ea_set_attr(&pes, ea);
+ proto_announce_state_later(p, pes);
+}
+
ea_list *channel_get_state(int id);
ea_list *proto_get_state(int id);
void proto_states_subscribe(struct lfjour_recipient *r);
conn->local_open_length = 0;
conn->remote_open_length = 0;
- ea_list *attr = conn->bgp->p.ea_state;
+ ea_list *pes = conn->bgp->p.ea_state;
if (conn == &conn->bgp->incoming_conn)
{
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_local_open_msg, 0, NULL, 0));
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_remote_open_msg, 0, NULL, 0));
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_sk, 0, NULL, 0));
+ ea_unset_attr(&pes, 0, &ea_bgp_in_conn_local_open_msg);
+ ea_unset_attr(&pes, 0, &ea_bgp_in_conn_remote_open_msg);
+ ea_unset_attr(&pes, 0, &ea_bgp_in_conn_sk);
}
else
{
ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_local_open_msg, 0, NULL, 0));
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_remote_open_msg, 0, NULL, 0));
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_sk, 0, NULL, 0));
+ ea_unset_attr(&pes, 0, &ea_bgp_out_conn_local_open_msg);
+ ea_unset_attr(&pes, 0, &ea_bgp_out_conn_remote_open_msg);
+ ea_unset_attr(&pes, 0, &ea_bgp_out_conn_sk);
}
- conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&conn->bgp->p, attr);
+
+ proto_announce_state_later(&conn->bgp->p, pes);
mb_free(conn->local_caps);
conn->local_caps = NULL;
bgp_dump_state_change(conn, conn->state, new_state);
conn->state = new_state;
+ ea_list *pes = conn->bgp->p.ea_state;
if (conn == &conn->bgp->incoming_conn)
- ea_set_attr(&conn->bgp->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_in_conn_state, 0, new_state));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_in_conn_state, 0, new_state));
else
{
ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
- ea_set_attr(&conn->bgp->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_out_conn_state, 0, new_state));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_out_conn_state, 0, new_state));
}
- conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&conn->bgp->p, conn->bgp->p.ea_state);
+
+ proto_announce_state_later(&conn->bgp->p, pes);
}
void
p->last_error_code = 0;
p->as4_session = conn->as4_session;
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_session, 0, conn->as4_session));
- p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&conn->bgp->p, conn->bgp->p.ea_state);
+
+ ea_list *pes = p->p.ea_state;
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_as4_session, 0, conn->as4_session));
+ proto_announce_state_later(&conn->bgp->p, pes);
p->route_refresh = peer->route_refresh;
p->enhanced_refresh = local->enhanced_refresh && peer->enhanced_refresh;
};
memcpy(bscad->data, conn->notify_data, conn->notify_size);
- ea_set_attr(&p->p.ea_state, EA_LITERAL_DIRECT_ADATA(&ea_bgp_close_bmp, 0, &bscad->ad));
- p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
-
- proto_announce_state_later(&p->p, p->p.ea_state);
+ ea_list *pes = p->p.ea_state;
+ ea_set_attr(&pes, EA_LITERAL_DIRECT_ADATA(&ea_bgp_close_bmp, 0, &bscad->ad));
+ proto_announce_state_later(&p->p, pes);
}
void
conn->hold_timer = tm_new_init(p->p.pool, bgp_hold_timeout, conn, 0, 0);
conn->keepalive_timer = tm_new_init(p->p.pool, bgp_keepalive_timeout, conn, 0, 0);
conn->send_hold_timer = tm_new_init(p->p.pool, bgp_send_hold_timeout, conn, 0, 0);
-
- ea_list *attr = conn->bgp->p.ea_state;
- if (conn == &conn->bgp->incoming_conn)
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_sk, 0, NULL, 0));
- else
- {
- ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_sk, 0, NULL, 0));
- }
- conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&p->p, attr);
}
static void
.dport = s->dport,
};
- ea_list *attr = conn->bgp->p.ea_state;
+ ea_list *pes = conn->bgp->p.ea_state;
if (conn == &conn->bgp->incoming_conn)
- ea_set_attr(&attr, EA_LITERAL_DIRECT_ADATA(&ea_bgp_in_conn_sk, 0, &sk_ad.ad));
+ ea_set_attr(&pes, EA_LITERAL_DIRECT_ADATA(&ea_bgp_in_conn_sk, 0, &sk_ad.ad));
else
{
ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
- ea_set_attr(&attr, EA_LITERAL_DIRECT_ADATA(&ea_bgp_out_conn_sk, 0, &sk_ad.ad));
+ ea_set_attr(&pes, EA_LITERAL_DIRECT_ADATA(&ea_bgp_out_conn_sk, 0, &sk_ad.ad));
}
- conn->bgp->p.ea_state = ea_lookup(conn->bgp->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&conn->bgp->p, attr);
+ proto_announce_state_later(&conn->bgp->p, pes);
}
static void
leave:
UNLOCK_DOMAIN(rtable, bgp_listen_domain);
+
+ /* We need to announce possible state changes immediately before
+ * leaving the protocol's loop, otherwise we're gonna access the protocol
+ * without having it locked from proto_announce_state_later(). */
+ proto_announce_state(&p->p, p->p.ea_state);
birdloop_leave(p->p.loop);
return 0;
}
struct bgp_proto *p = (struct bgp_proto *) n->proto;
int ps = p->p.proto_state;
+ ASSERT_DIE(birdloop_inside(p->p.loop));
+ ASSERT_DIE(!birdloop_inside(&main_birdloop));
+
if (n != p->neigh)
return;
bgp_stop(p, 0, NULL, 0);
}
}
+
+ /* BFD notify may run from another thread */
+ proto_announce_state(&p->p, p->p.ea_state);
}
static void
struct bgp_proto *p = _p;
const struct bgp_config *cf = p->cf;
+ ASSERT_DIE(birdloop_inside(p->p.loop));
+
if (p->p.proto_state != PS_START)
{
DBG("BGP: Got lock in different state %d\n", p->p.proto_state);
{
/* Multi-hop sessions do not use neighbor entries */
bgp_initiate(p);
+ proto_announce_state(&p->p, p->p.ea_state);
return;
}
BGP_TRACE(D_EVENTS, "Waiting for link on %s", n->iface->name);
else
bgp_start_neighbor(p);
+
+ proto_announce_state(&p->p, p->p.ea_state);
}
static int
/* Add MPLS channel */
proto_configure_mpls_channel(P, CF, RTS_BGP);
- ea_set_attr(&p->p.ea_state, EA_LITERAL_STORE_ADATA(&ea_bgp_rem_ip, 0, &cf->remote_ip, sizeof(ip_addr)));
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_peer_type, 0, cf->peer_type));
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_loc_as, 0, cf->local_as));
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, cf->remote_as));
+ /* Export public info */
+ ea_list *pes = p->p.ea_state;
+ ea_set_attr(&pes, EA_LITERAL_STORE_ADATA(&ea_bgp_rem_ip, 0, &cf->remote_ip, sizeof(ip_addr)));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_peer_type, 0, cf->peer_type));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_loc_as, 0, cf->local_as));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, cf->remote_as));
- proto_announce_state_later(&p->p, p->p.ea_state);
+ proto_announce_state_later(&p->p, pes);
return P;
}
conn->remote_open_msg = bgp_copy_open(p, pkt, len);
conn->remote_open_length = len - BGP_HEADER_LENGTH;
- ea_list *attr = p->p.ea_state;
if (conn == &conn->bgp->incoming_conn)
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_remote_open_msg, 0, conn->remote_open_msg, conn->remote_open_length));
+ proto_update_extended_state(&conn->bgp->p,
+ EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_remote_open_msg, 0,
+ conn->remote_open_msg, conn->remote_open_length));
else
{
ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_remote_open_msg, 0, conn->remote_open_msg, conn->remote_open_length));
+ proto_update_extended_state(&conn->bgp->p,
+ EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_remote_open_msg, 0,
+ conn->remote_open_msg, conn->remote_open_length));
}
- p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&p->p, attr);
if (bgp_read_options(conn, pkt+29, pkt[28], len-29) < 0)
return;
conn->ext_messages = conn->local_caps->ext_messages && caps->ext_messages;
p->remote_id = id;
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
+ ea_list *pes = p->p.ea_state;
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
if (conn == &p->incoming_conn)
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_in_conn, 0, conn->as4_session));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_as4_in_conn, 0, conn->as4_session));
else
{
ASSERT_DIE(conn == &p->outgoing_conn);
- ea_set_attr(&p->p.ea_state, EA_LITERAL_EMBEDDED(&ea_bgp_as4_out_conn, 0, conn->as4_session));
+ ea_set_attr(&pes, EA_LITERAL_EMBEDDED(&ea_bgp_as4_out_conn, 0, conn->as4_session));
}
-
- p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&p->p, p->p.ea_state);
+ proto_announce_state_later(&p->p, pes);
DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x, AS4 session to %d\n",
conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, conn->as4_session);
conn->local_open_msg = bgp_copy_open(p, buf, end - buf);
conn->local_open_length = end - buf - BGP_HEADER_LENGTH;
- ea_list *attr = p->p.ea_state;
+ ea_list *pes = p->p.ea_state;
if (conn == &conn->bgp->incoming_conn)
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_local_open_msg, 0, conn->local_open_msg, conn->local_open_length));
+ ea_set_attr(&pes, EA_LITERAL_STORE_ADATA(&ea_bgp_in_conn_local_open_msg, 0, conn->local_open_msg, conn->local_open_length));
else
{
ASSERT_DIE(conn == &conn->bgp->outgoing_conn);
- ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_local_open_msg, 0, conn->local_open_msg, conn->local_open_length));
+ ea_set_attr(&pes, EA_LITERAL_STORE_ADATA(&ea_bgp_out_conn_local_open_msg, 0, conn->local_open_msg, conn->local_open_length));
}
- p->p.ea_state = ea_lookup(p->p.ea_state, 0, EALS_CUSTOM);
- proto_announce_state_later(&p->p, attr);
+ proto_announce_state_later(&p->p, pes);
return bgp_send(conn, PKT_OPEN, end - buf);
}
if (!ppu)
return;
- if (bmp_peer_up_inout(p, ppu->proto_attr, true))
+ if (bmp_peer_up_inout(p, ppu->new, true))
goto done;
- SKIP_BACK_DECLARE(struct bgp_session_close_ad, bscad, ad, ea_get_adata(ppu->proto_attr, &ea_bgp_close_bmp));
+ SKIP_BACK_DECLARE(struct bgp_session_close_ad, bscad, ad, ea_get_adata(ppu->new, &ea_bgp_close_bmp));
if (bscad)
{
- bmp_peer_down_(p, ppu->proto_attr, bscad);
+ bmp_peer_down_(p, ppu->new, bscad);
goto done;
}