diff --git a/lib/resource.c b/lib/resource.c index 0a668acc..397f28f2 100644 --- a/lib/resource.c +++ b/lib/resource.c @@ -442,7 +442,7 @@ mb_alloc(pool *p, unsigned size) b->r.class = &mb_class; b->r.n = (struct resource_node) {}; - log("mb alloc %x %x %x", b, b->r.n, b->data); + //log("mb alloc %x %x %x", b, b->r.n, b->data); resource_add_tail(&p->inside, &b->r); b->size = size; return b->data; diff --git a/lib/route.h b/lib/route.h index 536ea46a..d14d336c 100644 --- a/lib/route.h +++ b/lib/route.h @@ -472,7 +472,8 @@ extern struct ea_class ea_name, ea_protocol_name, ea_protocol_type, ea_table, ea_channel_id, ea_deleted, ea_bgp_conn, ea_bgp_in_conn, ea_bgp_out_conn, ea_rtable, ea_bgp_afi; /* bgp protocol journal attributes */ extern struct ea_class ea_bgp_rem_id, ea_bgp_rem_as, ea_bgp_loc_as, ea_bgp_rem_ip, ea_bgp_peer_type, - ea_bgp_local_open_msg, ea_bgp_remote_open_msg, ea_bgp_local_open_msg_len, ea_bgp_remote_open_msg_len; + ea_bgp_local_open_msg, ea_bgp_remote_open_msg, ea_bgp_local_open_msg_len, ea_bgp_remote_open_msg_len, + ea_bgp_close_bmp, ea_bgp_close_bmp_set, ea_bgp_as4_session; /* Source: An old method to devise the route source protocol and kind. * To be superseded in a near future by something more informative. */ diff --git a/lib/type.h b/lib/type.h index 135da81c..c7346680 100644 --- a/lib/type.h +++ b/lib/type.h @@ -99,6 +99,7 @@ enum btype { T_ENUM_NETTYPE = 0x3b, T_ENUM_AF = 0x3d, T_RTABLE = 0x3e, + T_BMP_CLOSING = 0x40, /* new enums go here */ diff --git a/nest/proto.c b/nest/proto.c index 06f24d58..8c4d0f44 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -2992,7 +2992,7 @@ proto_state_to_eattr(struct proto *p, int old_state, int proto_deleting) //log("protocol %s to eattr", p->name); struct { ea_list l; - eattr a[9+15]; + eattr a[9+19]; } eattrs; eattrs.l = (ea_list) {}; diff --git a/nest/rt-attr.c b/nest/rt-attr.c index ba0037b2..66c09cbc 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -1985,6 +1985,21 @@ struct ea_class ea_bgp_remote_open_msg = { .type = T_BYTESTRING, }; +struct ea_class ea_bgp_close_bmp = { + .name = "bgp_close_bmp", + .type = T_BMP_CLOSING, +}; + +struct ea_class ea_bgp_close_bmp_set = { + .name = "bgp_close_bmp_set", + .type = T_INT, +}; + +struct ea_class ea_bgp_as4_session = { + .name = "bgp_as4_session", + .type = T_INT, +}; + /** * rta_init - initialize route attribute cache * @@ -2054,6 +2069,9 @@ rta_init(void) ea_register_init(&ea_bgp_remote_open_msg); ea_register_init(&ea_bgp_local_open_msg_len); ea_register_init(&ea_bgp_remote_open_msg_len); + ea_register_init(&ea_bgp_close_bmp); + ea_register_init(&ea_bgp_close_bmp_set); + ea_register_init(&ea_bgp_as4_session); } /* diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 470f0658..8b7b04c1 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -825,9 +825,27 @@ bgp_conn_leave_established_state(struct bgp_conn *conn, struct bgp_proto *p) bgp_stop(p, 0, NULL, 0); #ifdef CONFIG_BMP - bmp_peer_down(p, p->last_error_class, - conn->notify_code, conn->notify_subcode, - conn->notify_data, conn->notify_size); + struct { + struct closing_bgp closing_struct; + byte data[conn->notify_size]; + } to_ea; + + to_ea.closing_struct = (struct closing_bgp) { + .err_class = p->last_error_class, + .err_code = conn->notify_code, + .err_subcode = conn->notify_subcode, + .length = conn->notify_size, + }; + memcpy(to_ea.data, conn->notify_data, conn->notify_size); + + ea_list *eal = proto_state_table->attrs[p->p.id]; + ea_set_attr(&eal, EA_LITERAL_STORE_ADATA(&ea_bgp_close_bmp, 0, &to_ea.closing_struct, sizeof(to_ea))); + ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_close_bmp_set, 0, 1)); + proto_journal_state_push(eal, &p->p, 0); + + //bmp_peer_down(p, p->last_error_class, + // conn->notify_code, conn->notify_subcode, + // conn->notify_data, conn->notify_size); #endif } @@ -2595,6 +2613,7 @@ bgp_state_to_eattr(struct proto *P, ea_list *l, eattr *attributes) attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_peer_type, 0, p->cf->peer_type); attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_loc_as, 0, p->local_as); attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, p->remote_as); + attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_as4_session, 0, p->as4_session); if (p->conn) { attributes[l->count++] = EA_LITERAL_STORE_PTR(&ea_bgp_conn, 0, &p->conn); @@ -2611,6 +2630,9 @@ bgp_state_to_eattr(struct proto *P, ea_list *l, eattr *attributes) attributes[l->count++] = EA_LITERAL_STORE_ADATA(&ea_bgp_remote_open_msg, 0, NULL, 0); attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_local_open_msg_len, 0, 0); attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_remote_open_msg_len, 0, 0); + + attributes[l->count++] = EA_LITERAL_STORE_ADATA(&ea_bgp_close_bmp, 0, NULL, 0); + attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_close_bmp_set, 0, 0); } static void diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index b5251352..0c31a3a7 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -326,6 +326,14 @@ struct journal_bgp_conn { struct bgp_conn incoming_conn; }; +struct closing_bgp { + int err_class; + int err_code; + int err_subcode; + int length; + byte data[0]; +}; + struct bgp_listen_request { node n; /* Node in bgp_socket / pending list */ struct bgp_socket *sock; /* Assigned socket */ diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index fc6d8828..391de91b 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -705,24 +705,15 @@ bmp_peer_up_(struct bmp_proto *p, ea_list *bgp_attr, bool sync, } } -void -bmp_peer_up(ea_list *bgp, - const byte *tx_open_msg, uint tx_open_length, - const byte *rx_open_msg, uint rx_open_length) -{ - int need_unlock = 1; - if (DG_IS_LOCKED(p->p.pool->domain)) - need_unlock = 0; - else - DG_LOCK(p->p.pool->domain); - - struct bmp_proto *p; node *n; - WALK_LIST2(p, n, bmp_proto_list, bmp_node) - bmp_peer_up_(p, bgp, true, tx_open_msg, tx_open_length, rx_open_msg, rx_open_length); - - if (need_unlock) - DG_UNLOCK(p->p.pool->domain); -} +//void +//bmp_peer_up(ea_list *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, true, tx_open_msg, tx_open_length, rx_open_msg, rx_open_length); +//} static void bmp_peer_init(struct bmp_proto *p, ea_list *bgp_attr) @@ -771,28 +762,31 @@ bmp_get_birdsock_ext(ea_list *bgp) } static const struct bgp_caps * -bmp_get_bgp_remote_caps(const struct bgp_proto *bgp) +bmp_get_bgp_remote_caps(struct bgp_conn *bgp_conn) { - if (bgp->conn && bgp->conn->remote_caps) - return bgp->conn->remote_caps; + if (bgp_conn && bgp_conn->remote_caps) + return bgp_conn->remote_caps; return NULL; } static const struct bgp_caps * -bmp_get_bgp_remote_caps_ext(const struct bgp_proto *bgp) +bmp_get_bgp_remote_caps_ext(ea_list *bgp) { - const struct bgp_caps *remote_caps = bmp_get_bgp_remote_caps(bgp); + struct bgp_conn *bgp_conn = (struct bgp_conn*) ea_get_adata(bgp, &ea_bgp_conn)->data; + const struct bgp_caps *remote_caps = bmp_get_bgp_remote_caps(bgp_conn); if (remote_caps != NULL) return remote_caps; - if (bgp->incoming_conn.remote_caps) + struct bgp_conn *bgp_in_conn = (struct bgp_conn*) ea_get_adata(bgp, &ea_bgp_in_conn)->data; + struct bgp_conn *bgp_out_conn = (struct bgp_conn*) ea_get_adata(bgp, &ea_bgp_out_conn)->data; + if (bgp_in_conn->remote_caps) { - remote_caps = bgp->incoming_conn.remote_caps; + remote_caps = bgp_in_conn->remote_caps; } - else if (bgp->outgoing_conn.remote_caps) + else if (bgp_out_conn->remote_caps) { - remote_caps = bgp->outgoing_conn.remote_caps; + remote_caps = bgp_out_conn->remote_caps; } return remote_caps; @@ -924,36 +918,36 @@ bmp_route_monitor_end_of_rib(struct bmp_proto *p, struct bmp_stream *bs) } static void -bmp_send_peer_down_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, +bmp_send_peer_down_notif_msg(struct bmp_proto *p, ea_list *bgp, const byte *data, const size_t data_size) { ASSERT(p->started); const struct bgp_caps *remote_caps = bmp_get_bgp_remote_caps_ext(bgp); - bool is_global_instance_peer = bmp_is_peer_global_instance(proto_state_table->attrs[bgp->p.id]); + bool is_global_instance_peer = bmp_is_peer_global_instance(bgp); buffer payload = bmp_buffer_alloc(p->buffer_mpool, DEFAULT_MEM_BLOCK_SIZE); bmp_peer_down_notif_msg_serialize(&payload, is_global_instance_peer, - bgp->remote_as, bgp->remote_id, - remote_caps ? remote_caps->as4_support : bgp->as4_session, - bgp->remote_ip, data, data_size); + ea_get_int(bgp, &ea_bgp_rem_as, 0), ea_get_int(bgp, &ea_bgp_rem_id, 0), + remote_caps ? remote_caps->as4_support : ea_get_int(bgp, &ea_bgp_as4_session, 0), + *((ip_addr*)ea_get_adata(bgp, &ea_bgp_rem_ip)->data), data, data_size); bmp_schedule_tx_packet(p, bmp_buffer_data(&payload), bmp_buffer_pos(&payload)); bmp_buffer_free(&payload); } static void -bmp_peer_down_(struct bmp_proto *p, const struct bgp_proto *bgp, +bmp_peer_down_(struct bmp_proto *p, ea_list *bgp, int err_class, int err_code, int err_subcode, const byte *data, int length) { if (!p->started) return; - struct bmp_peer *bp = bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]); + struct bmp_peer *bp = bmp_find_peer(p, bgp); if (!bp) return; - TRACE(D_STATES, "Peer down for %s", bgp->p.name); + TRACE(D_STATES, "Peer down for %s", ea_find(bgp, &ea_name)->u.ad->data); uint bmp_code = 0; uint fsm_code = 0; @@ -1001,25 +995,25 @@ bmp_peer_down_(struct bmp_proto *p, const struct bgp_proto *bgp, bmp_remove_peer(p, bp); } -#if 0 -void -bmp_peer_down(const struct bgp_proto *bgp, - int err_class, int code, int subcode, const byte *data, int length) -{ - int need_unlock = 1; - if (DG_IS_LOCKED(p->p.pool->domain)) - need_unlock = 0; - else - DG_LOCK(p->p.pool->domain); +//#if 0 +//void +//bmp_peer_down(const struct bgp_proto *bgp, +// int err_class, int code, int subcode, const byte *data, int length) +//{ +// int need_unlock = 1; +// if (DG_IS_LOCKED(p->p.pool->domain)) +// need_unlock = 0; +// else +// DG_LOCK(p->p.pool->domain); - struct bmp_proto *p; node *n; - WALK_LIST2(p, n, bmp_proto_list, bmp_node) - bmp_peer_down_(p, bgp, err_class, code, subcode, data, length); +// struct bmp_proto *p; node *n; +// WALK_LIST2(p, n, bmp_proto_list, bmp_node) +// bmp_peer_down_(p, bgp, err_class, code, subcode, data, length); - if (need_unlock) - DG_UNLOCK(p->p.pool->domain); -} -#endif +// if (need_unlock) +// DG_UNLOCK(p->p.pool->domain); +//} +//#endif static void bmp_send_termination_msg(struct bmp_proto *p, @@ -1319,7 +1313,7 @@ fc_for_bmp_recipient(void *_p) //log("received update, locked %i", locking_stack.service); struct lfjour_item *last_up; struct proto_pending_update *pupdate; - while (last_up = lfjour_get((struct lfjour_recipient *)rec)) + while (last_up = lfjour_get(&p->proto_state_reader)) { pupdate = SKIP_BACK(struct proto_pending_update, li, last_up); const byte *tx_open_msg = ea_get_adata(pupdate->proto_attr, &ea_bgp_local_open_msg)->data; @@ -1338,28 +1332,35 @@ fc_for_bmp_recipient(void *_p) const byte *rx_open_msg = ea_get_adata(pupdate->proto_attr, &ea_bgp_remote_open_msg)->data; int l_len = ea_get_int(pupdate->proto_attr, &ea_bgp_remote_open_msg_len, 0); int r_len = ea_get_int(pupdate->proto_attr, &ea_bgp_remote_open_msg_len, 0); - bmp_peer_up_(p, proto_state_table->attrs[id], tx_open_msg, l_len, rx_open_msg, r_len); + bmp_peer_up_(p, proto_state_table->attrs[id], true, tx_open_msg, l_len, rx_open_msg, r_len); /* !!! or bmp_peer_down_() or ignore if irrelevant */ } + else if (ea_get_int(pupdate->proto_attr, &ea_bgp_close_bmp_set, 0)) + { + struct closing_bgp *closing = (struct closing_bgp *) ea_get_ptr(pupdate->proto_attr, &ea_protocol_type, 0); + bmp_peer_down_(p, proto_state_table->attrs[id], + closing->err_class, closing->err_code, closing->err_subcode, closing->data, closing->length); + } - lfjour_release(rec); + lfjour_release(&p->proto_state_reader); } } void create_bmp_recipient(struct bmp_proto *p) { - struct lfjour_recipient *r = mb_allocz(&root_pool, sizeof(struct lfjour_recipient)); - log("recipient %x", r); - r->event = ev_new_init(&root_pool, fc_for_bmp_recipient, r); - //struct birdloop *loop = birdloop_new(&root_pool, DOMAIN_ORDER(service), 1, "bmp recipient loop"); - r->target = birdloop_event_list(P->loop); + struct lfjour_recipient *r = &p->proto_state_reader; + r->event = &p->proto_state_changed; + *r->event = (event) { .hook = fc_for_bmp_recipient, .data = p }; + log("p->p.loop %x", p->p.loop); + r->target = birdloop_event_list(p->p.loop); LOCK_DOMAIN(rtable, proto_journal_domain); lfjour_register(proto_journal, r); UNLOCK_DOMAIN(rtable, proto_journal_domain); + p->lf_jour_inited = 1; } /** Configuration handle section **/ @@ -1383,7 +1384,7 @@ bmp_init(struct proto_config *CF) strcpy(p->sys_name, cf->sys_name); p->monitoring_rib.in_pre_policy = cf->monitoring_rib_in_pre_policy; p->monitoring_rib.in_post_policy = cf->monitoring_rib_in_post_policy; - //create_bmp_recipient(P); should be here, but. + //create_bmp_recipient(p); //should be here, but. log("new proto created locked %i", locking_stack.service); return P; @@ -1416,12 +1417,12 @@ bmp_start(struct proto *P) init_list(&p->update_msg_queue); p->started = false; p->sock_err = 0; - add_tail(&bmp_proto_list, &p->bmp_node); //TODO remove tm_start(p->connect_retry_timer, CONNECT_INIT_TIME); log("end of start locked %i", locking_stack.service); - create_bmp_recipient(p); + if (p->lf_jour_inited == 0) + create_bmp_recipient(p); return PS_START; } @@ -1437,8 +1438,6 @@ bmp_shutdown(struct proto *P) } p->sock_err = 0; - log("rem_node(&p->bmp_node %x)", p->bmp_node); - rem_node(&p->bmp_node); return PS_DOWN; } diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index ed1ee7f7..3ca47402 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -47,7 +47,6 @@ struct bmp_proto; 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 HASH(struct bmp_peer) peer_map; HASH(struct bmp_stream) stream_map; @@ -76,6 +75,7 @@ struct bmp_proto { struct lfjour_recipient proto_state_reader; // Reader of protocol states event proto_state_changed; + int lf_jour_inited; }; struct bmp_peer {