diff --git a/configure.ac b/configure.ac index 9c809201..aaf4d851 100644 --- a/configure.ac +++ b/configure.ac @@ -308,6 +308,7 @@ if test "$enable_mpls_kernel" != no ; then fi fi +<<<<<<< HEAD BIRD_CHECK_CLOCK(CLOCK_MONOTONIC) if test "$bird_cv_clock_CLOCK_MONOTONIC" != yes ; then AC_MSG_ERROR([Monotonic clock not supported]) @@ -320,7 +321,7 @@ else AC_DEFINE([HAVE_CLOCK_MONOTONIC_COARSE], [1], [Define to 1 if coarse clock is available]) fi -all_protocols="aggregator bfd babel bgp l3vpn ospf pipe radv rip rpki static mrt" +all_protocols="aggregator bfd babel bgp l3vpn ospf pipe radv rip rpki static mrt bmp" all_protocols=`echo $all_protocols | sed 's/ /,/g'` if test "$with_protocols" = all ; then diff --git a/filter/data.c b/filter/data.c index 6311ac30..db4a6bbe 100644 --- a/filter/data.c +++ b/filter/data.c @@ -654,6 +654,8 @@ mem_hash_mix_f_val(u64 *h, struct f_val *v) case T_PTR: case T_ENUM_STATE: case T_BTIME: + case T_POINTER: + case T_BGP_CONN: bug("Invalid type %s in f_val hashing", f_type_name(v->type)); } } diff --git a/lib/route.h b/lib/route.h index f73c49e1..205caaed 100644 --- a/lib/route.h +++ b/lib/route.h @@ -467,11 +467,11 @@ extern struct ea_class ea_gen_mpls_label, ea_gen_mpls_policy, ea_gen_mpls_class; /* protocol journal attributes */ -extern struct ea_class ea_proto_name, ea_proto_protocol_name, ea_proto_table, - ea_proto_state, ea_proto_old_state, ea_proto_last_modified, ea_proto_info, - ea_proto_id, ea_proto_deleted; +extern struct ea_class ea_name, ea_protocol_name, ea_protocol_type, ea_table, + ea_state, ea_old_state, ea_last_modified, ea_info, ea_proto_id, + ea_channel_id, ea_deleted, ea_bgp_conn, ea_rtable, ea_bgp_afi; /* bgp protocol journal attributes */ -extern struct ea_class ea_proto_bgp_rem_id, ea_proto_bgp_rem_as, ea_proto_bgp_rem_ip; +extern struct ea_class ea_bgp_rem_id, ea_bgp_rem_as, ea_bgp_rem_ip; /* 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 ec476a52..b09ed86f 100644 --- a/lib/type.h +++ b/lib/type.h @@ -98,6 +98,7 @@ enum btype { T_ENUM_ROA = 0x39, T_ENUM_NETTYPE = 0x3b, T_ENUM_AF = 0x3d, + T_RTABLE = 0x3e, /* new enums go here */ @@ -120,6 +121,8 @@ enum btype { /* protocol */ T_ENUM_STATE = 0xd1, T_BTIME = 0xd4, + T_POINTER = 0xd8, + T_BGP_CONN = 0xcb, } PACKED; typedef enum btype btype; diff --git a/nest/config.Y b/nest/config.Y index a0a10daf..6b9f6e94 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -692,10 +692,10 @@ CF_CLI(SHOW MEMORY,,, [[Show memory usage]]) { cmd_show_memory(); } ; CF_CLI(SHOW PROTOCOLS, proto_patt2, [ | \"\"], [[Show routing protocols]]) -{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ; +{ proto_apply_cmd_no_lock($3, proto_cmd_show, 0, (union cmd_arg){.verbose = 0}); } ; CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [ | \"\"], [[Show routing protocol details]]) -{ proto_apply_cmd($4, proto_cmd_show, 0, 1); } ; +{ proto_apply_cmd_no_lock($4, proto_cmd_show, 0, (union cmd_arg){.verbose = 1}); } ; optproto: CF_SYM_KNOWN { cf_assert_symbol($1, SYM_PROTO); $$ = $1; } diff --git a/nest/proto.c b/nest/proto.c index f938bb73..f453a985 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -30,6 +30,7 @@ static TLIST_LIST(proto) global_proto_list; static list STATIC_LIST_INIT(protocol_list); struct lfjour *proto_journal; +struct lfjour *channel_journal; DOMAIN(rtable) proto_journal_domain; #define CD(c, msg, args...) ({ if (c->debug & D_STATES) log(L_TRACE "%s.%s: " msg, c->proto->name, c->name ?: "?", ## args); }) @@ -49,7 +50,8 @@ static char *p_states[] = { "DOWN", "START", "UP", "STOP" }; static char *c_states[] = { "DOWN", "START", "UP", "STOP", "RESTART" }; extern struct protocol proto_unix_iface; -struct proto_attrs *proto_attributes; +struct proto_attrs *proto_state_table; +struct proto_attrs *channel_state_table; static void proto_rethink_goal(struct proto *p); static char *proto_state_name(struct proto *p); @@ -58,6 +60,7 @@ static void channel_update_limit(struct channel *c, struct limit *l, int dir, st static void channel_reset_limit(struct channel *c, struct limit *l, int dir); static void channel_stop_export(struct channel *c); static void channel_check_stopped(struct channel *c); +void init_journals(void); static inline void channel_reimport(struct channel *c, struct rt_feeding_request *rfr) { rt_export_refeed(&c->reimporter, rfr); @@ -255,6 +258,16 @@ proto_add_channel(struct proto *p, struct channel_config *cf) return c; } +struct channel * +proto_add_main_channel(struct proto *p, struct channel_config *cf) +{ + p->main_channel = proto_add_channel(p, cf); + ea_list *eal = proto_state_table->attrs[p->id]; + ea_set_attr(&eal, EA_LITERAL_STORE_STRING(&ea_table, 0, p->main_channel->table->name)); + proto_journal_state_push(eal, p); + return p->main_channel; +} + void proto_remove_channel(struct proto *p UNUSED, struct channel *c) { @@ -262,6 +275,10 @@ proto_remove_channel(struct proto *p UNUSED, struct channel *c) CD(c, "Removed", c->name); + ea_list *eal = *get_channel_ea(c)->attrs; + ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_deleted, 0, 1)); + channel_journal_state_push(eal,c); + rt_unlock_table(c->table); rem_node(&c->n); mb_free(c); @@ -1304,14 +1321,13 @@ proto_init(struct proto_config *c, struct proto *after) PD(p, "Initializing%s", p->disabled ? " [disabled]" : ""); - p->id = hmap_first_zero(proto_attributes->proto_id_maker); - hmap_set(proto_attributes->proto_id_maker, p->id); - if (p->id >= proto_attributes->length) + p->id = hmap_first_zero(proto_state_table->proto_id_maker); + hmap_set(proto_state_table->proto_id_maker, p->id); + if (p->id >= proto_state_table->length) protos_attr_field_grow(); ea_list *eal = proto_state_to_eattr(p, old_state, 0); - ea_list *old_eal = proto_attributes->attrs[p->id]; - atomic_store(&proto_attributes->attrs[p->id], eal); - proto_journal_state_changed(eal, old_eal, p); + + proto_journal_state_push(eal, p); return p; } @@ -1735,8 +1751,12 @@ proto_rethink_goal(struct proto *p) struct proto_config *nc = p->cf_new; struct proto *after = p->n.prev; - hmap_clear(proto_attributes->proto_id_maker, p->id); - atomic_store(&proto_attributes->attrs[p->id], NULL); + ea_list *eal = proto_state_table->attrs[p->id]; + ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_deleted, 0, 1)); + proto_journal_state_push(eal, p); + log("deleting %i", p->id); + hmap_clear(proto_state_table->proto_id_maker, p->id); + atomic_store(&proto_state_table->attrs[p->id], NULL); DBG("%s has shut down for reconfiguration\n", p->name); p->cf->proto = NULL; @@ -2031,7 +2051,7 @@ protos_build(void) { proto_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Protocols"); - init_proto_journal(); + init_journals(); //create_dummy_recipient(); protos_build_gen(); } @@ -2330,10 +2350,11 @@ proto_notify_state(struct proto *p, uint state) int old_state = p->proto_state; p->proto_state = state; p->last_state_change = current_time(); - ea_list *eal = proto_state_to_eattr(p, old_state, 0); - ea_list *old_eal = proto_attributes->attrs[p->id]; - atomic_store(&proto_attributes->attrs[p->id], eal); - proto_journal_state_changed(eal, old_eal, p); + + ea_list *eal = proto_state_table->attrs[p->id]; + ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_state, 0, p->proto_state)); + ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_old_state, 0, old_state)); + proto_journal_state_push(eal, p); switch (state) { @@ -2498,7 +2519,7 @@ channel_cmd_debug(struct channel *c, uint mask) } void -proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) +proto_cmd_show(struct proto *p, union cmd_arg verbose, int cnt) { byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE]; @@ -2507,34 +2528,33 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) cli_msg(-2002, "%-10s %-10s %-10s %-6s %-12s %s", "Name", "Proto", "Table", "State", "Since", "Info"); - rcu_read_lock(); - ea_list *eal = proto_attributes->attrs[p->id]; - ea_free_later(ea_ref(eal)); - rcu_read_unlock(); + ea_list *eal = proto_get_state_list(p->id); - const char *name = ea_find(eal, &ea_proto_name)->u.ad->data; - const char *proto = ea_find(eal, &ea_proto_protocol_name)->u.ad->data; - const int state = ea_find(eal, &ea_proto_state)->u.i; - const char *table = ea_find(eal, &ea_proto_table)->u.ad->data; - const char *info = ea_find(eal, &ea_proto_info)->u.ad->data; - const btime *time = (btime*) ea_find(eal, &ea_proto_last_modified)->u.ad->data; + const char *name = ea_get_adata(eal, &ea_name)->data; + struct protocol **type = (struct protocol **)ea_get_adata(eal, &ea_protocol_type)->data; + const int state = ea_get_int(eal, &ea_state, 0); + const char *table = ea_get_adata(eal, &ea_table)->data; buf[0] = 0; if (p->proto->get_status) - p->proto->get_status(p, buf); + { + PROTO_LOCKED_FROM_MAIN(p) + p->proto->get_status(p, buf); + } + const btime *time = (btime *)ea_get_adata(eal, &ea_last_modified)->data; + tm_format_time(tbuf, &config->tf_proto, *time); - rcu_read_lock(); - tm_format_time(tbuf, &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto, p->last_state_change); - rcu_read_unlock(); cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s %s", name, - proto, - table, + (*type)->name, + table ? table : "---", proto_state_name_from_int(state), tbuf, - info); + buf); - if (verbose) + if (verbose.verbose) { + PROTO_LOCKED_FROM_MAIN(p) + { if (p->cf->dsc) cli_msg(-1006, " Description: %s", p->cf->dsc); if (p->message) @@ -2554,6 +2574,7 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) } cli_msg(-1006, ""); + } } } @@ -2756,6 +2777,46 @@ proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, in proto_apply_cmd_symbol(ps.ptr, cmd, arg); } +void +proto_apply_cmd_no_lock(struct proto_spec ps, void (* cmd)(struct proto *, union cmd_arg, int), + int restricted, union cmd_arg arg) +{ + if (restricted && cli_access_restricted()) + return; + + if (ps.patt) + { + int cnt = 0; + const char *patt = ps.ptr; + + WALK_TLIST(proto, p, &global_proto_list) + if (!patt || patmatch(patt, p->name)) + cmd(p, arg, cnt++); + + if (!cnt) + cli_msg(8003, "No protocols match"); + else + cli_msg(0, ""); + } + else + { + const struct symbol *s = ps.ptr; + if (s->class != SYM_PROTO) + { + cli_msg(9002, "%s is not a protocol", s->name); + return; + } + if (s->proto->proto) + { + struct proto *p = s->proto->proto; + cmd(p, arg, 0); + cli_msg(0, ""); + } + else + cli_msg(9002, "%s does not exist", s->name); + } +} + struct proto * proto_get_named(struct symbol *sym, struct protocol *pr) { @@ -2835,85 +2896,124 @@ proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *ol void protos_attr_field_init(void) { - proto_attributes = mb_allocz(&root_pool, sizeof(struct proto_attrs)); - proto_attributes->attrs = mb_allocz(&root_pool, sizeof(ea_list *_Atomic)*16); - proto_attributes->length = 16; - proto_attributes->proto_id_maker = mb_allocz(&root_pool, sizeof(struct hmap)); - hmap_init(proto_attributes->proto_id_maker, &root_pool, 16); + proto_state_table = mb_allocz(&root_pool, sizeof(struct proto_attrs)); + proto_state_table->attrs = mb_allocz(&root_pool, sizeof(ea_list *_Atomic)*16); + proto_state_table->length = 16; + proto_state_table->proto_id_maker = mb_allocz(&root_pool, sizeof(struct hmap)); + proto_state_table->channel_id_maker = mb_allocz(&root_pool, sizeof(struct hmap)); + hmap_init(proto_state_table->proto_id_maker, &root_pool, 16); + hmap_init(proto_state_table->channel_id_maker, &root_pool, 16*2); //TODO free? or have self pool? } void protos_attr_field_grow(void) { - ea_list *_Atomic * new_field = mb_allocz(&root_pool, sizeof(ea_list *_Atomic)*proto_attributes->length*2); - memcpy(new_field, proto_attributes->attrs, proto_attributes->length*(sizeof(ea_list* _Atomic))); - atomic_store(&proto_attributes->attrs, new_field); - atomic_store(&proto_attributes->length, (proto_attributes->length*2)); + log("grow"); + ea_list *_Atomic * new_field = mb_allocz(&root_pool, sizeof(ea_list *_Atomic)*proto_state_table->length*2); + memcpy(new_field, proto_state_table->attrs, proto_state_table->length*(sizeof(ea_list* _Atomic))); + atomic_store(&proto_state_table->attrs, new_field); + atomic_store(&proto_state_table->length, (proto_state_table->length*2)); } void cleanup_journal_item(struct lfjour * journal UNUSED, struct lfjour_item *i) { + log("cleanup_journal_item"); struct proto_pending_update *pupdate = SKIP_BACK(struct proto_pending_update, li, i); ea_free_later(pupdate->old_attr); - eattr *new_ea = ea_find(pupdate->proto_attr, &ea_proto_deleted); + eattr *new_ea = ea_find(pupdate->proto_attr, &ea_deleted); if (new_ea->u.i) + { + log("try to delete"); ea_free_later(pupdate->proto_attr); + } } void after_journal_birdloop_stop(void* arg UNUSED){} void -init_proto_journal(void) +init_journal(int item_size, char *loop_name) { - protos_attr_field_init(); proto_journal = mb_allocz(&root_pool, sizeof(struct lfjour)); struct settle_config cf = {.min = 0, .max = 0}; proto_journal->item_done = cleanup_journal_item; - proto_journal->item_size = sizeof(struct proto_pending_update); - proto_journal->loop = birdloop_new(&root_pool, DOMAIN_ORDER(service), 1, "Protocol state journal"); - proto_journal_domain = DOMAIN_NEW_RCU_SYNC(rtable); + proto_journal->item_size = item_size; + proto_journal->loop = birdloop_new(&root_pool, DOMAIN_ORDER(service), 1, loop_name); proto_journal->domain = proto_journal_domain.rtable; lfjour_init(proto_journal, &cf); } +void +init_journals(void) +{ + protos_attr_field_init(); + proto_journal_domain = DOMAIN_NEW_RCU_SYNC(rtable); + init_journal(sizeof(struct proto_pending_update), "proto journal loop"); + init_journal(sizeof(struct channel_pending_update), "channel journal loop"); +} + ea_list * proto_state_to_eattr(struct proto *p, int old_state, int proto_deleting) { - int eatt_len = 8; - if (p->proto == &proto_bgp) - eatt_len += 3; struct { ea_list l; - eattr a[eatt_len]; + eattr a[15]; } eattrs; eattrs.l = (ea_list) {}; - eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_proto_name, 0, p->name); - eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_proto_protocol_name, 0, p->proto->name); - eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_proto_table, 0, p->main_channel ? p->main_channel->table->name : "---"); - eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_proto_state, 0, p->proto_state); - eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_proto_old_state, 0, old_state); - eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_ADATA(&ea_proto_last_modified, 0, &p->last_state_change, sizeof(btime)); + eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_name, 0, p->name); + //eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_protocol_name, 0, p->proto->name); this info is stored in ea_protocol_type + eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_ADATA(&ea_protocol_type, 0, &p->proto, sizeof(struct protocol *)); + if (p->main_channel) + eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_table, 0, p->main_channel->table->name); + eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_state, 0, p->proto_state); + eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_old_state, 0, old_state); + eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_ADATA(&ea_last_modified, 0, &p->last_state_change, sizeof(btime)); eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_proto_id, 0, p->id); - eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_proto_deleted, 0, proto_deleting); + eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_deleted, 0, proto_deleting); if (p->proto == &proto_bgp) bgp_state_to_eattr(p, &eattrs.l, eattrs.a); - byte buf[256]; - buf[0] = 0; - if (p->proto->get_status) - p->proto->get_status(p, buf); - eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_proto_info, 0, buf); + return ea_lookup_slow(&eattrs.l, 0, EALS_CUSTOM); } -void -proto_journal_state_changed(ea_list *attr, ea_list *old_attr, struct proto *p) +ea_list * +channel_state_to_eattr(struct channel *ch, int proto_deleting) { + struct { + ea_list l; + eattr a[5]; + } eattrs; + eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_STRING(&ea_name, 0, ch->name); + eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_proto_id, 0, ch->proto->id); + eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_deleted, 0, proto_deleting); + if (ch->table) + { + struct rtable_adata rad = (struct rtable_adata){.table = h->table}; + eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_ADATA(&ea_gen_rtable, 0, &rad, sizeof(rtable *)); + } + if (ch->proto->proto == &proto_bgp && ch != ch->proto->mpls_channel) + { + struct bgp_channel *bc = (struct bgp_channel *) ch; + eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_bgp_afi, 0, bc->afi); + } + return ea_lookup_slow(&eattrs.l, 0, EALS_CUSTOM); +} + +//mpls!!!!! ch nonskip + +void +proto_journal_state_push(ea_list *attr, struct proto *p) +{ + ea_set_attr(&attr, EA_LITERAL_STORE_ADATA(&ea_last_modified, 0, &p->last_state_change, sizeof(btime))); + + attr = ea_lookup(attr, 0, EALS_CUSTOM); + atomic_store(&proto_state_table->attrs[p->id], attr); + ea_list *old_attr = proto_state_table->attrs[p->id]; LOCK_DOMAIN(rtable, proto_journal_domain); struct proto_pending_update *pupdate = SKIP_BACK(struct proto_pending_update, li, lfjour_push_prepare(proto_journal)); if (!pupdate) @@ -2923,7 +3023,7 @@ proto_journal_state_changed(ea_list *attr, ea_list *old_attr, struct proto *p) } *pupdate = (struct proto_pending_update) { .li = pupdate->li, /* Keep the item's internal state */ - .proto_attr = attr, + .proto_attr = proto_state_table->attrs[p->id], .old_attr = old_attr, .protocol = p }; @@ -2931,25 +3031,86 @@ proto_journal_state_changed(ea_list *attr, ea_list *old_attr, struct proto *p) UNLOCK_DOMAIN(rtable, proto_journal_domain); } +ea_list * +proto_get_state_list(int id) +{ + rcu_read_lock(); + ea_list *eal = proto_state_table->attrs[id]; + if (eal) + ea_free_later(ea_ref(eal)); + rcu_read_unlock(); + return eal; +} + +struct channel_attrs * +get_channel_ea(struct channel *ch) +{ + struct channel_attrs *chan_att; + WALK_LIST(chan_att, proto_state_table->channels_attrs[ch->proto->id]) + { + const int id = ea_get_int(*chan_att->attrs, &ea_channel_id, 0); + if (ch->id == id) + return chan_att; + } + return NULL; +} + +void +channel_journal_state_push(ea_list *attr, struct channel *ch) +{ + ea_list *old_attr = *get_channel_ea(ch)->attrs; + LOCK_DOMAIN(rtable, proto_journal_domain); + struct channel_pending_update *pupdate = SKIP_BACK(struct channel_pending_update, li, lfjour_push_prepare(channel_journal)); + if (!pupdate) + { + UNLOCK_DOMAIN(rtable, proto_journal_domain); + return; + } + *pupdate = (struct channel_pending_update) { + .li = pupdate->li, /* Keep the item's internal state */ + .channel_attr = attr, + .old_attr = old_attr, + .channel = ch + }; + lfjour_push_commit(channel_journal); + UNLOCK_DOMAIN(rtable, proto_journal_domain); +} + +/*void +channel_journal_state_change(struct channel *ch, int old_state, int new_state) +{ + ea_list *eal = channel_state_to_eattr(ch, new_state); + struct channel_attrs *chan_att = get_channel_ea(ch); + atomic_store(&chan_att->attrs, eal); + channel_journal_state_changed(eal, old_eal, ch); +}*/ + +void +add_journal_channel(struct channel *ch, int new_state) +{ + ea_list *eal = channel_state_to_eattr(ch, new_state); + struct channel_attrs *attr = mb_allocz(&root_pool, sizeof(struct channel_attrs)); + atomic_store(attr->attrs, eal); + ASSERT_DIE(proto_state_table->attrs[ch->proto->id] != NULL); + add_tail(&proto_state_table->channels_attrs[ch->proto->id], &ch->n); + +} + void dummy_log_proto_attr_list(void) { //debugging function ea_list *eal; - for(u32 i = 0; i < proto_attributes->length; i++) + for(u32 i = 0; i < proto_state_table->length; i++) { - rcu_read_lock(); - eal = proto_attributes->attrs[i]; - if (eal) - ea_free_later(ea_ref(eal)); - rcu_read_unlock(); + eal = proto_get_state_list(i); if (eal) { - const char *name = ea_find(eal, &ea_proto_name)->u.ad->data; - const char *type = ea_find(eal, &ea_proto_protocol_name)->u.ad->data; - const int state = ea_find(eal, &ea_proto_state)->u.i; - const char *table = ea_find(eal, &ea_proto_table)->u.ad->data; - const btime *time = (btime*) ea_find(eal, &ea_proto_last_modified)->u.ad->data; - log("protocol %s of type %s is in state %i (table %s, last modified %t)", name, type, state, table, time); + const char *name = ea_find(eal, &ea_name)->u.ad->data; + struct protocol **t = (struct protocol **)ea_get_adata(eal, &ea_protocol_type)->data; + const int state = ea_get_int(eal, &ea_state, 0); + const char *table = ea_get_adata(eal, &ea_table)->data; + const btime *time = (btime *)ea_get_adata(eal, &ea_last_modified)->data; + log("protocol %s of type %s is in state %i (table %s, last modified %t)", name, (*t)->name, state, table, time); } } } @@ -2962,10 +3123,10 @@ fc_for_dummy_recipient(void *rec) while (last_up = lfjour_get((struct lfjour_recipient *)rec)) { pupdate = SKIP_BACK(struct proto_pending_update, li, last_up); - eattr *name = ea_find(pupdate->proto_attr, &ea_proto_name); - eattr *state = ea_find(pupdate->proto_attr, &ea_proto_state); + const char *name = ea_get_adata(pupdate->proto_attr, &ea_name)->data; + int state = ea_get_int(pupdate->proto_attr, &ea_state, 0); if (name && state) - log("protocol %s changed state to %i", name->u.ad->data, state->u.i); + log("protocol %s changed state to %i", name, state); else log("not found in %i", pupdate->proto_attr); lfjour_release(rec); diff --git a/nest/protocol.h b/nest/protocol.h index 12750b8d..187d6023 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -174,7 +174,7 @@ struct proto { btime last_state_change; /* Time of last state transition */ char *last_state_name_announced; /* Last state name we've announced to the user */ char *message; /* State-change message, allocated from proto_pool */ - u32 id; /* Id of the protocol indexing its position in proto_attributes */ + u32 id; /* Id of the protocol indexing its position in proto_state_table */ /* * General protocol hooks: @@ -262,7 +262,13 @@ void channel_show_limit(struct limit *l, const char *dsc, int active, int action void channel_show_info(struct channel *c); void channel_cmd_debug(struct channel *c, uint mask); -void proto_cmd_show(struct proto *, uintptr_t, int); +union cmd_arg { + int verbose; + struct proto_reload_request *prr; + char *msg; +}; + +void proto_cmd_show(struct proto *, union cmd_arg verbose, int); void proto_cmd_disable(struct proto *, uintptr_t, int); void proto_cmd_enable(struct proto *, uintptr_t, int); void proto_cmd_restart(struct proto *, uintptr_t, int); @@ -271,6 +277,7 @@ void proto_cmd_debug(struct proto *, uintptr_t, int); void proto_cmd_mrtdump(struct proto *, uintptr_t, int); void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), int restricted, uintptr_t arg); +void proto_apply_cmd_no_lock(struct proto_spec ps, void (* cmd)(struct proto *, union cmd_arg, int), int restricted, union cmd_arg arg); struct proto *proto_get_named(struct symbol *, struct protocol *); struct proto *proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old); @@ -397,12 +404,20 @@ static inline int proto_is_inactive(struct proto *p) struct proto_attrs { ea_list *_Atomic *attrs; + list *channels_attrs; _Atomic u32 length; struct hmap *proto_id_maker; + struct hmap *channel_id_maker; }; extern struct lfjour *proto_journal; -extern struct proto_attrs *proto_attributes; +extern struct lfjour *channel_journal; +extern struct proto_attrs *proto_state_table; + +struct channel_attrs { + node n; + ea_list *_Atomic *attrs; +}; struct proto_pending_update { LFJOUR_ITEM_INHERIT(li); @@ -411,10 +426,20 @@ struct proto_pending_update { struct proto *protocol; }; -void proto_journal_state_changed(ea_list *attr, ea_list *old_attr, struct proto *p); +struct channel_pending_update { + LFJOUR_ITEM_INHERIT(li); + ea_list *channel_attr; + ea_list *old_attr; + struct channel *channel; +}; + +void proto_journal_state_push(ea_list *attr, struct proto *p); +void channel_journal_state_push(ea_list *attr, struct channel *ch); ea_list *proto_state_to_eattr(struct proto *p, int old_state, int protocol_deleting); +struct channel_attrs *get_channel_ea(struct channel *ch); void create_dummy_recipient(void); void protos_attr_field_grow(void); +ea_list *proto_get_state_list(int id); /* @@ -550,6 +575,7 @@ struct channel { node n; /* Node in proto->channels */ const char *name; /* Channel name (may be NULL) */ + int id; const struct channel_class *class; struct proto *proto; @@ -686,6 +712,7 @@ static inline struct channel_config *proto_cf_mpls_channel(struct proto_config * struct channel *proto_find_channel_by_table(struct proto *p, rtable *t); struct channel *proto_find_channel_by_name(struct proto *p, const char *n); struct channel *proto_add_channel(struct proto *p, struct channel_config *cf); +struct channel *proto_add_main_channel(struct proto *p, struct channel_config *cf); void proto_remove_channel(struct proto *p, struct channel *c); int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf); diff --git a/nest/route.h b/nest/route.h index 72089929..d00cca5f 100644 --- a/nest/route.h +++ b/nest/route.h @@ -896,6 +896,11 @@ struct hostentry_adata { u32 labels[0]; }; +struct rtable_adata { + adata ad; + struct rtable *table; +}; + #define HOSTENTRY_LABEL_COUNT(head) (head->ad.length + sizeof(struct adata) - sizeof(struct hostentry_adata)) / sizeof(u32) void diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 7faf23e2..6052c6c6 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -168,6 +168,29 @@ struct ea_class ea_gen_hostentry_version = { .hidden = 1, }; +static void +ea_gen_rtable_stored(const eattr *ea) +{ + struct rtable_adata *had = (struct rtable_adata *) ea->u.ptr; + rt_lock_table(had->table); +} + +static void +ea_gen_rtable_freed(const eattr *ea) +{ + struct rtable_adata *had = (struct rtable_adata *) ea->u.ptr; + rt_unlock_table(had->table); +} + +struct ea_class ea_gen_rtable = { + .name = "rtable", + .type = T_RTABLE, + .readonly = 1, + .stored = ea_gen_rtable_stored, + .freed = ea_gen_rtable_freed, +}; + + const char * rta_dest_names[RTD_MAX] = { [RTD_NONE] = "", [RTD_UNICAST] = "unicast", @@ -1837,66 +1860,86 @@ ea_show_list(struct cli *c, ea_list *eal) } -struct ea_class ea_proto_name = { +struct ea_class ea_name = { .name = "proto_name", .type = T_STRING, }; -struct ea_class ea_proto_protocol_name = { +struct ea_class ea_protocol_name = { .name = "proto_protocol_name", .type = T_STRING, }; -struct ea_class ea_proto_table = { +struct ea_class ea_protocol_type = { + .name = "proto_protocol_type", + .type = T_POINTER, +}; + +struct ea_class ea_table = { .name = "proto_table", .type = T_STRING, }; -struct ea_class ea_proto_state = { +struct ea_class ea_state = { .name = "proto_state", .type = T_ENUM_STATE, }; -struct ea_class ea_proto_old_state = { +struct ea_class ea_old_state = { .name = "proto_old_state", .type = T_ENUM_STATE, }; -struct ea_class ea_proto_last_modified = { +struct ea_class ea_last_modified = { .name = "proto_last_modified", .type = T_BTIME, }; -struct ea_class ea_proto_info = { +struct ea_class ea_info = { .name = "proto_info", .type = T_STRING, }; -struct ea_class ea_proto_deleted = { +struct ea_class ea_deleted = { .name = "proto_deleted", .type = T_INT, }; struct ea_class ea_proto_id = { - .name = "proto_id", + .name = "proto_proto_id", .type = T_INT, }; -struct ea_class ea_proto_bgp_rem_id = { +struct ea_class ea_channel_id = { + .name = "proto_channel_id", + .type = T_INT, +}; + +struct ea_class ea_bgp_rem_id = { .name = "proto_bgp_rem_id", .type = T_INT, }; -struct ea_class ea_proto_bgp_rem_as = { +struct ea_class ea_bgp_rem_as = { .name = "proto_bgp_rem_as", .type = T_INT, }; -struct ea_class ea_proto_bgp_rem_ip = { +struct ea_class ea_bgp_rem_ip = { .name = "proto_bgp_rem_ip", .type = T_IP, }; +struct ea_class ea_bgp_conn = { + .name = "proto_bgp_rem_conn", + .type = T_BGP_CONN, +}; + +struct ea_class ea_bgp_afi = { + .name = "bgp_afi", + .type = T_INT, +}; + /** * rta_init - initialize route attribute cache * @@ -1939,20 +1982,26 @@ rta_init(void) ea_register_init(&ea_gen_mpls_label); /* Protocol attributes */ - ea_register_init(&ea_proto_name); - ea_register_init(&ea_proto_protocol_name); - ea_register_init(&ea_proto_table); - ea_register_init(&ea_proto_state); - ea_register_init(&ea_proto_old_state); - ea_register_init(&ea_proto_last_modified); - ea_register_init(&ea_proto_info); + ea_register_init(&ea_name); + ea_register_init(&ea_protocol_name); + ea_register_init(&ea_protocol_type); + ea_register_init(&ea_table); + ea_register_init(&ea_state); + ea_register_init(&ea_old_state); + ea_register_init(&ea_last_modified); + ea_register_init(&ea_info); ea_register_init(&ea_proto_id); - ea_register_init(&ea_proto_deleted); + ea_register_init(&ea_channel_id); + ea_register_init(&ea_deleted); /* Protocol bgp attributes */ - ea_register_init(&ea_proto_bgp_rem_id); - ea_register_init(&ea_proto_bgp_rem_as); - ea_register_init(&ea_proto_bgp_rem_ip); + ea_register_init(&ea_bgp_rem_id); + ea_register_init(&ea_bgp_rem_as); + ea_register_init(&ea_bgp_rem_ip); + ea_register_init(&ea_bgp_conn); + ea_register_init(&ea_rtable); + ea_register_init(&ea_bgp_afi); + ea_register_init(&ea_gen_rtable); } /* diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 3486e8b8..ccdeedc1 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -2570,9 +2570,20 @@ void bgp_state_to_eattr(struct proto *P, ea_list *l, eattr *attributes) { struct bgp_proto *p = (struct bgp_proto *) P; - attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_proto_bgp_rem_id, 0, p->remote_id); - attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_proto_bgp_rem_as, 0, p->remote_as); - attributes[l->count++] = EA_LITERAL_STORE_ADATA(&ea_proto_bgp_rem_ip, 0, &p->remote_ip, sizeof(ip_addr)); + attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id); + attributes[l->count++] = EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, p->remote_as); + attributes[l->count++] = EA_LITERAL_STORE_ADATA(&ea_bgp_rem_ip, 0, &p->remote_ip, sizeof(ip_addr)); + if (p->conn) + { + struct journal_bgp_conn conn = { + .state = p->conn->state, + .local_open_msg = p->conn->local_open_msg, + .remote_open_msg = p->conn->remote_open_msg, + .local_open_length = p->conn->local_open_length, + .remote_open_length = p->conn->remote_open_length, + }; + attributes[l->count++] = EA_LITERAL_STORE_ADATA(&ea_bgp_conn, 0, &conn, sizeof(struct journal_bgp_conn)); + } } static void diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index a54d98b7..044f1043 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -290,6 +290,15 @@ struct bgp_stats { uint fsm_established_transitions; }; +struct journal_bgp_conn { + u8 state; + + byte *local_open_msg; + byte *remote_open_msg; + uint local_open_length; + uint remote_open_length; +}; + struct bgp_conn { struct bgp_proto *bgp; struct birdsock *sk; diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 10ee4bc0..d3edd012 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -2466,7 +2466,6 @@ bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, struct bgp_write_state s = { .proto = p, - .channel = c, .pool = tmp_linpool, .mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop, .as4_session = 1, @@ -2520,13 +2519,14 @@ bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, const net_addr *n, init_list(&b->prefixes); if (attrs) - memcpy(b->eattrs, attrs, ea_size); + memcpy(b->attrs, attrs, ea_size); /* Temporary prefix */ struct bgp_prefix *px = tmp_allocz(prefix_size); - px->path_id = (u32) src->private_id; - net_copy(px->net, n); - add_tail(&b->prefixes, &px->buck_node_xx); + px->src = tmp_allocz(sizeof(struct rte_src)); + memcpy(px->src, src, sizeof(struct rte_src)); + //FIXME net_copy(px->net, n); + add_tail(&b->prefixes, &px->buck_node); // why was there _xx ? byte *end = bgp_create_update_bmp(c, pkt, b, !!new); diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index 261e9fdd..5252c1a3 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -219,7 +219,7 @@ static void bmp_sock_err(sock *sk, int err); static void bmp_close_socket(struct bmp_proto *p); static void -bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp, +bmp_send_peer_up_notif_msg(struct bmp_proto *p, const ea_list *bgp, const byte *tx_data, const size_t tx_data_size, const byte *rx_data, const size_t rx_data_size); @@ -482,13 +482,13 @@ bmp_peer_down_notif_msg_serialize(buffer *stream, const bool is_peer_global, */ static struct bmp_table * -bmp_find_table(struct bmp_proto *p, struct rtable *tab) +bmp_find_table(struct bmp_proto *p, rtable *tab) { return HASH_FIND(p->table_map, HASH_TABLE, tab); } static struct bmp_table * -bmp_add_table(struct bmp_proto *p, struct rtable *tab) +bmp_add_table(struct bmp_proto *p, rtable *tab) { struct bmp_table *bt = mb_allocz(p->p.pool, sizeof(struct bmp_table)); bt->table = tab; @@ -498,12 +498,12 @@ bmp_add_table(struct bmp_proto *p, struct rtable *tab) struct channel_config cc = { .name = "monitor", - .channel = &channel_basic, + //.channel = &channel_basic, .table = tab->config, .in_filter = FILTER_REJECT, .net_type = tab->addr_type, .ra_mode = RA_ANY, - .bmp_hack = 1, + //.bmp_hack = 1, }; bt->channel = proto_add_channel(&p->p, &cc); @@ -515,7 +515,7 @@ bmp_add_table(struct bmp_proto *p, struct rtable *tab) static void bmp_remove_table(struct bmp_proto *p, struct bmp_table *bt) { - channel_set_state(bt->channel, CS_FLUSHING); + channel_set_state(bt->channel, CS_STOP); channel_set_state(bt->channel, CS_DOWN); proto_remove_channel(&p->p, bt->channel); @@ -527,7 +527,7 @@ bmp_remove_table(struct bmp_proto *p, struct bmp_table *bt) mb_free(bt); } -static inline struct bmp_table *bmp_get_table(struct bmp_proto *p, struct rtable *tab) +static inline struct bmp_table *bmp_get_table(struct bmp_proto *p, rtable *tab) { return bmp_find_table(p, tab) ?: bmp_add_table(p, tab); } static inline void bmp_lock_table(struct bmp_proto *p UNUSED, struct bmp_table *bt) @@ -551,13 +551,13 @@ static inline bool bmp_stream_policy(struct bmp_stream *bs) { return !!(bs->key & BMP_STREAM_KEY_POLICY); } static struct bmp_stream * -bmp_find_stream(struct bmp_proto *p, const struct bgp_proto *bgp, u32 afi, bool policy) +bmp_find_stream(struct bmp_proto *p, ea_list *bgp_attr, u32 afi, bool policy) { - return HASH_FIND(p->stream_map, HASH_STREAM, bgp, bmp_stream_key(afi, policy)); + return HASH_FIND(p->stream_map, HASH_STREAM, (void*)bgp_attr, bmp_stream_key(afi, policy)); } static struct bmp_stream * -bmp_add_stream(struct bmp_proto *p, struct bmp_peer *bp, u32 afi, bool policy, struct rtable *tab, struct bgp_channel *sender) +bmp_add_stream(struct bmp_proto *p, struct bmp_peer *bp, u32 afi, bool policy, rtable *tab, ea_list *sender, int in_pre_policy) { struct bmp_stream *bs = mb_allocz(p->p.pool, sizeof(struct bmp_stream)); bs->bgp = bp->bgp; @@ -571,6 +571,7 @@ bmp_add_stream(struct bmp_proto *p, struct bmp_peer *bp, u32 afi, bool policy, s bs->sender = sender; bs->sync = false; + bs->in_pre_policy = in_pre_policy; return bs; } @@ -593,29 +594,32 @@ bmp_remove_stream(struct bmp_proto *p, struct bmp_stream *bs) */ static struct bmp_peer * -bmp_find_peer(struct bmp_proto *p, const struct bgp_proto *bgp) +bmp_find_peer(struct bmp_proto *p, ea_list *bgp_attr) { - return HASH_FIND(p->peer_map, HASH_PEER, bgp); + return HASH_FIND(p->peer_map, HASH_PEER, (void *)bgp_attr); //TODO this is wrong, hash find is not for eattrs. but. } static struct bmp_peer * -bmp_add_peer(struct bmp_proto *p, struct bgp_proto *bgp) +bmp_add_peer(struct bmp_proto *p, ea_list *bgp_attr) { struct bmp_peer *bp = mb_allocz(p->p.pool, sizeof(struct bmp_peer)); - bp->bgp = bgp; + bp->bgp = bgp_attr; init_list(&bp->streams); HASH_INSERT(p->peer_map, HASH_PEER, bp); - struct bgp_channel *c; - BGP_WALK_CHANNELS(bgp, c) + int proto_id = ea_get_int(bgp_attr, &ea_proto_id, 0); + + ea_list *chan_attr; + WALK_LIST(chan_attr, proto_state_table->channels_attrs[proto_id]) { - if (p->monitoring_rib.in_pre_policy && c->c.in_table) - bmp_add_stream(p, bp, c->afi, false, c->c.in_table, c); + rtable *ch_table = (rtable *) ea_get_adata(chan_attr, &ea_rtable)->data; + if (p->monitoring_rib.in_pre_policy && ch_table) + bmp_add_stream(p, bp, ea_get_int(chan_attr, &ea_bgp_afi, 0), false, ch_table, chan_attr, 1); - if (p->monitoring_rib.in_post_policy && c->c.table) - bmp_add_stream(p, bp, c->afi, true, c->c.table, c); + if (p->monitoring_rib.in_post_policy && ch_table) + bmp_add_stream(p, bp, ea_get_int(chan_attr, &ea_bgp_afi, 0), true, ch_table, chan_attr, 0); } return bp; @@ -634,22 +638,23 @@ bmp_remove_peer(struct bmp_proto *p, struct bmp_peer *bp) } static void -bmp_peer_up_(struct bmp_proto *p, struct bgp_proto *bgp, bool sync, +bmp_peer_up_(struct bmp_proto *p, ea_list *bgp_attr, bool sync, const byte *tx_open_msg, uint tx_open_length, const byte *rx_open_msg, uint rx_open_length) { if (!p->started) return; - struct bmp_peer *bp = bmp_find_peer(p, bgp); + struct bmp_peer *bp = bmp_find_peer(p, bgp_attr); if (bp) return; - TRACE(D_STATES, "Peer up for %s", bgp->p.name); + const char *name = ea_find(bgp_attr, &ea_name)->u.ad->data; + TRACE(D_STATES, "Peer up for %s", name); - bp = bmp_add_peer(p, bgp); + bp = bmp_add_peer(p, bgp_attr); - bmp_send_peer_up_notif_msg(p, bgp, tx_open_msg, tx_open_length, rx_open_msg, rx_open_length); + bmp_send_peer_up_notif_msg(p, bgp_attr, tx_open_msg, tx_open_length, rx_open_msg, rx_open_length); /* * We asssume peer_up() notifications are received before any route @@ -668,7 +673,7 @@ bmp_peer_up_(struct bmp_proto *p, struct bgp_proto *bgp, bool sync, } void -bmp_peer_up(struct bgp_proto *bgp, +bmp_peer_up(ea_list *bgp, const byte *tx_open_msg, uint tx_open_length, const byte *rx_open_msg, uint rx_open_length) { @@ -678,15 +683,15 @@ bmp_peer_up(struct bgp_proto *bgp, } static void -bmp_peer_init(struct bmp_proto *p, struct bgp_proto *bgp) +bmp_peer_init(struct bmp_proto *p, ea_list *bgp_attr) { - struct bgp_conn *conn = bgp->conn; + struct journal_bgp_conn *conn = (struct journal_bgp_conn *) ea_find(bgp_attr, &ea_bgp_conn)->u.ad->data; if (!conn || (conn->state != BS_ESTABLISHED) || !conn->local_open_msg || !conn->remote_open_msg) return; - bmp_peer_up_(p, bgp, false, conn->local_open_msg, conn->local_open_length, + bmp_peer_up_(p, bgp_attr, false, conn->local_open_msg, conn->local_open_length, conn->remote_open_msg, conn->remote_open_length); } @@ -855,7 +860,7 @@ bmp_route_monitor_commit(void *p_) 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", bs->bgp->p.name, bs->sender->c.name); + TRACE(D_PACKETS, "Sending END-OF-RIB for %s.%s", bs->bgp->p.name, ea_get_adata(bs->sender, &ea_name)->adata); byte rx_end_payload[DEFAULT_MEM_BLOCK_SIZE]; byte *pos = bgp_create_end_mark_(bs->sender, rx_end_payload + BGP_HEADER_LENGTH); @@ -979,19 +984,26 @@ bmp_send_termination_msg(struct bmp_proto *p, int bmp_preexport(struct channel *C UNUSED, rte *e) { - /* Reject non-direct routes */ - if (e->src->proto != e->sender->proto) + /* Reject non-direct routes. Check if sender proto is the same as proto which created the route. + * It assumes that route was created in a protocol. + */ + struct rt_import_request *req = e->sender->req; + struct channel *ch = SKIP_BACK(struct channel, in_req, req); + + struct rte_owner *owner = e->src->owner; + struct proto *p = SKIP_BACK(struct proto, sources, owner); + if (ch->proto != p) return -1; /* Reject non-BGP routes */ - if (e->sender->channel != &channel_bgp) + if (p->proto != &proto_bgp) return -1; return 1; } static void -bmp_rt_notify(struct proto *P, struct channel *c, struct network *net, +bmp_rt_notify(struct proto *P, struct channel *c, const net_addr *net, struct rte *new, struct rte *old) { struct bmp_proto *p = (void *) P; @@ -1011,7 +1023,7 @@ bmp_rt_notify(struct proto *P, struct channel *c, struct network *net, if (!bs) return; - bmp_route_monitor_notify(p, bs, net->n.addr, new, (new ?: old)->src); + bmp_route_monitor_notify(p, bs, net, new, (new ?: old)->src); } static void @@ -1068,10 +1080,21 @@ bmp_startup(struct bmp_proto *p) bmp_buffer_free(&payload); /* Send Peer Up messages */ - struct proto *peer; + for (int i = 0; i < bgp_attributes->length; i++) + { + ea_list *bgp_attr = bgp_attributes->attrs[i]; + if (bgp_attr == NULL) + continue; + struct protocol *proto = (struct protocol *) ea_find(bgp_attr, &ea_protocol_type)->u.ad->data; + const int state = ea_find(bgp_attr, &ea_state)->u.i; + if (proto != &proto_bgp || state != PS_UP) + continue; + bmp_peer_init(p, bgp_attr); + } + /*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); + if ((peer->proto != &proto_bgp) && (peer->proto_state == PS_UP)) + bmp_peer_init(p, (struct bgp_proto *) peer);*/ } /** diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index d69aaafb..55fa4230 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -76,23 +76,24 @@ struct bmp_proto { }; struct bmp_peer { - struct bgp_proto *bgp; + ea_list *bgp; struct bmp_peer *next; list streams; }; struct bmp_stream { node n; - struct bgp_proto *bgp; + ea_list *bgp; u32 key; bool sync; struct bmp_stream *next; struct bmp_table *table; - struct bgp_channel *sender; + ea_list *sender; + int in_pre_policy; }; struct bmp_table { - struct rtable *table; + rtable *table; struct bmp_table *next; struct channel *channel; u32 uc; diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index d8645910..e19bac65 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -68,6 +68,7 @@ log(L_ERR "%s: " msg, s->proto->p.name, ## args); \ }) +extern struct proto_attrs *proto_state_table; /* * MRT buffer code @@ -381,10 +382,10 @@ mrt_peer_table_dump(struct mrt_table_dump_state *s) mrt_peer_table_entry(s, 0, 0, IPA_NONE); #ifdef CONFIG_BGP - for(u32 i = 0; ilength; i++) + for(u32 i = 0; ilength; i++) { rcu_read_lock(); - ea_list *eal = proto_attributes->attrs[i]; + ea_list *eal = proto_state_table->attrs[i]; if (eal) ea_free_later(ea_ref(eal)); else @@ -393,14 +394,14 @@ mrt_peer_table_dump(struct mrt_table_dump_state *s) continue; } rcu_read_unlock(); - eattr *name = ea_find(proto_attributes->attrs[i], &ea_proto_protocol_name); - eattr *state = ea_find(proto_attributes->attrs[i], &ea_proto_state); - if ((strcmp(name->u.ad->data, "BGP") == 0) && (state->u.i != PS_DOWN)) + struct protocol **type = (struct protocol **)ea_get_adata(eal, &ea_protocol_type)->data; + int state = ea_get_int(eal, &ea_state, 0); + if ((*type == &proto_bgp) && (state != PS_DOWN)) { - eattr *rem_id = ea_find(proto_attributes->attrs[i], &ea_proto_bgp_rem_id); - eattr *rem_as = ea_find(proto_attributes->attrs[i], &ea_proto_bgp_rem_as); - eattr *rem_ip = ea_find(proto_attributes->attrs[i], &ea_proto_bgp_rem_ip); - mrt_peer_table_entry(s, rem_id->u.i, rem_as->u.i, *((ip_addr*) rem_ip->u.ad->data)); + int rem_id = ea_get_int(eal, &ea_bgp_rem_id, 0); + int rem_as = ea_get_int(eal, &ea_bgp_rem_as, 0); + ip_addr *rem_ip = (ip_addr *)ea_get_adata(eal, &ea_bgp_rem_ip)->data; + mrt_peer_table_entry(s, rem_id, rem_as, *rem_ip); } } #endif @@ -789,6 +790,7 @@ mrt_bgp_buffer(void) static buffer b; ASSERT(this_metaloop); + log("loop in mrt %x, pool %i (main loop is %x, pool %i)", this_metaloop, this_metaloop->pool, &main_birdloop, main_birdloop.pool); ASSERT(this_metaloop->pool); if (!b.start) mrt_buffer_init(&b, this_metaloop->pool, 1024); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 7c649214..0077ff48 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -368,7 +368,7 @@ ospf_init(struct proto_config *CF) struct ospf_config *cf = (struct ospf_config *) CF; struct proto *P = proto_new(CF); - P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); + proto_add_main_channel(P, proto_cf_main_channel(CF)); P->rt_notify = ospf_rt_notify; P->iface_sub.if_notify = ospf_if_notify; diff --git a/proto/radv/radv.c b/proto/radv/radv.c index ea0b8d38..5ee4ca03 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -579,7 +579,7 @@ radv_init(struct proto_config *CF) { struct proto *P = proto_new(CF); - P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); + proto_add_main_channel(P, proto_cf_main_channel(CF)); P->preexport = radv_preexport; P->rt_notify = radv_rt_notify; diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 1d4e6cf5..a4727018 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -1162,7 +1162,7 @@ rip_init(struct proto_config *CF) { struct proto *P = proto_new(CF); - P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); + proto_add_main_channel(P, proto_cf_main_channel(CF)); P->iface_sub.if_notify = rip_if_notify; P->rt_notify = rip_rt_notify; diff --git a/proto/static/static.c b/proto/static/static.c index c8fdcc37..366cc2b2 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -507,7 +507,7 @@ static_init(struct proto_config *CF) struct static_proto *p = (void *) P; struct static_config *cf = (void *) CF; - P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); + proto_add_main_channel(P, proto_cf_main_channel(CF)); proto_configure_mpls_channel(P, CF, RTS_STATIC); diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index d4225d3a..779e2142 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -1435,12 +1435,14 @@ birdloop_init(void) main_birdloop.time.domain = the_bird_domain.the_bird; main_birdloop.time.loop = &main_birdloop; + main_birdloop.pool = rp_new(&root_pool, the_bird_domain.the_bird, "Main loop"); times_update(); timers_init(&main_birdloop.time, &root_pool); birdloop_enter_locked(&main_birdloop); this_birdloop = this_metaloop = &main_birdloop; + this_thread = &main_thread; defer_init(lp_new(&root_pool)); diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index d6c1a31d..7039181c 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -835,7 +835,7 @@ krt_init(struct proto_config *CF) struct krt_proto *p = proto_new(CF); // struct krt_config *cf = (void *) CF; - p->p.main_channel = proto_add_channel(&p->p, proto_cf_main_channel(CF)); + proto_add_main_channel(&p->p, proto_cf_main_channel(CF)); p->p.preexport = krt_preexport; p->p.rt_notify = krt_rt_notify;