mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
bmp and its channels in progress (no, it can not be compiled)
This commit is contained in:
parent
b6c17abd61
commit
9e3d6a9d6e
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -692,10 +692,10 @@ CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
|
||||
{ cmd_show_memory(); } ;
|
||||
|
||||
CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[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, [<protocol> | \"<pattern>\"], [[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; }
|
||||
|
325
nest/proto.c
325
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);
|
||||
@ -257,6 +260,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)
|
||||
{
|
||||
@ -264,6 +277,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);
|
||||
@ -1261,14 +1278,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;
|
||||
}
|
||||
@ -1692,8 +1708,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;
|
||||
@ -1988,7 +2008,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();
|
||||
}
|
||||
@ -2292,10 +2312,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)
|
||||
{
|
||||
@ -2460,7 +2481,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];
|
||||
|
||||
@ -2469,34 +2490,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)
|
||||
@ -2516,6 +2536,7 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
|
||||
}
|
||||
|
||||
cli_msg(-1006, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2718,6 +2739,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)
|
||||
{
|
||||
@ -2797,85 +2858,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)
|
||||
@ -2885,7 +2985,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
|
||||
};
|
||||
@ -2893,25 +2993,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2924,10 +3085,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);
|
||||
|
@ -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;
|
||||
|
||||
@ -685,6 +711,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);
|
||||
|
||||
|
@ -883,6 +883,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
|
||||
|
@ -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",
|
||||
@ -1824,66 +1847,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
|
||||
*
|
||||
@ -1926,20 +1969,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2578,9 +2578,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
|
||||
|
@ -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;
|
||||
|
@ -2463,7 +2463,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,
|
||||
@ -2517,13 +2516,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);
|
||||
|
||||
|
101
proto/bmp/bmp.c
101
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)
|
||||
{
|
||||
if (p->monitoring_rib.in_pre_policy && c->c.in_table)
|
||||
bmp_add_stream(p, bp, c->afi, false, c->c.in_table, c);
|
||||
int proto_id = ea_get_int(bgp_attr, &ea_proto_id, 0);
|
||||
|
||||
if (p->monitoring_rib.in_post_policy && c->c.table)
|
||||
bmp_add_stream(p, bp, c->afi, true, c->c.table, c);
|
||||
ea_list *chan_attr;
|
||||
WALK_LIST(chan_attr, proto_state_table->channels_attrs[proto_id])
|
||||
{
|
||||
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 && 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);*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,23 +78,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;
|
||||
|
@ -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; i<proto_attributes->length; i++)
|
||||
for(u32 i = 0; i<proto_state_table->length; 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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1416,12 +1416,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));
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user