0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-15 13:31:54 +00:00

without ea_normalize wrong, with it falls

This commit is contained in:
Katerina Kubecova 2024-09-19 09:54:06 +02:00
parent 4abc24bfac
commit c32ce0f799
8 changed files with 136 additions and 71 deletions

View File

@ -469,7 +469,8 @@ extern struct ea_class ea_gen_mpls_label,
/* protocol journal attributes */
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_bgp_in_conn, ea_bgp_out_conn, ea_rtable, ea_bgp_afi;
ea_channel_id, ea_deleted, ea_bgp_conn, ea_bgp_in_conn, ea_bgp_out_conn, ea_rtable, ea_bgp_afi,
ea_in_keep;
/* bgp protocol journal attributes */
extern struct ea_class ea_bgp_rem_id, ea_bgp_rem_as, ea_bgp_loc_as, ea_bgp_rem_ip, ea_bgp_peer_type,
ea_bgp_local_open_msg, ea_bgp_remote_open_msg, ea_bgp_local_open_msg_len, ea_bgp_remote_open_msg_len,

View File

@ -3018,7 +3018,7 @@ channel_state_to_eattr(struct channel *ch, int proto_deleting)
{
struct {
ea_list l;
eattr a[6];
eattr a[7];
} eattrs;
eattrs.l = (ea_list) {};
@ -3027,6 +3027,7 @@ channel_state_to_eattr(struct channel *ch, int proto_deleting)
eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_proto_id, 0, ch->proto->id);
eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_channel_id, 0, ch->id);
eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_deleted, 0, proto_deleting);
eattrs.a[eattrs.l.count++] = EA_LITERAL_EMBEDDED(&ea_in_keep, 0, ch->in_keep);
eattrs.a[eattrs.l.count++] = EA_LITERAL_STORE_PTR(&ea_rtable, 0, ch->table);
log("ea_rtable added (%x), eattrs %x, str %x", ch->table, eattrs.l, eattrs.a[0].u.ad->data);

View File

@ -1915,6 +1915,11 @@ struct ea_class ea_channel_id = {
.type = T_INT,
};
struct ea_class ea_in_keep = {
.name = "channel_in_keep",
.type = T_INT,
};
struct ea_class ea_bgp_rem_id = {
.name = "proto_bgp_rem_id",
.type = T_INT,
@ -2053,6 +2058,7 @@ rta_init(void)
ea_register_init(&ea_proto_id);
ea_register_init(&ea_channel_id);
ea_register_init(&ea_deleted);
ea_register_init(&ea_in_keep);
/* Protocol bgp attributes */
ea_register_init(&ea_bgp_rem_id);

View File

@ -1320,7 +1320,6 @@ bgp_export_attrs(struct bgp_export_state *s, ea_list *a)
static inline int
bgp_encode_attr(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
{
log("size %i %x", size, a->type);
const union bgp_attr_desc *desc = bgp_find_attr_desc(a);
if (s->ignore_non_bgp_attrs == 0)
ASSERT_DIE(desc);
@ -1348,10 +1347,10 @@ bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end
byte *pos = buf;
int i, len;
log("attrs count %i", attrs->count);
for (i = 0; i < attrs->count; i++)
{
len = bgp_encode_attr(s, &attrs->attrs[i], pos, end - pos);
if (len < 0)
return -1;
@ -1815,7 +1814,10 @@ bgp_done_prefix(struct bgp_ptx_private *c, struct bgp_prefix *px, struct bgp_buc
{
/* BMP hack */
if (buck->bmp)
{
rem_node(&px->buck_node);
return;
}
/* Cleanup: We're called from bucket senders. */
ASSERT_DIE(px->cur == buck);

View File

@ -1767,6 +1767,11 @@ bgp_start(struct proto *P)
p->remote_id = 0;
p->link_addr = IPA_NONE;
ea_list *eal = proto_state_table->attrs[p->p.id];
ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_loc_as, 0, p->local_as));
ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_rem_as, 0, p->remote_as));
proto_journal_state_push(eal, &p->p, 1);
/* Lock all channels when in GR recovery mode */
if (p->p.gr_recovery && p->cf->gr_mode)

View File

@ -1047,6 +1047,9 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
conn->as4_session = conn->local_caps->as4_support && caps->as4_support;
conn->ext_messages = conn->local_caps->ext_messages && caps->ext_messages;
p->remote_id = id;
ea_list *eal = proto_state_table->attrs[p->p.id];
ea_set_attr(&eal, EA_LITERAL_EMBEDDED(&ea_bgp_rem_id, 0, p->remote_id));
proto_journal_state_push(eal, &p->p, 1);
DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x, AS4 session to %d\n",
conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, conn->as4_session);
@ -1605,6 +1608,7 @@ bgp_encode_nlri_ip4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
while (!EMPTY_LIST(buck->prefixes) && (size >= BGP_NLRI_MAX))
{
log("list_length(buck->prefixes) %i size %i >= BGP_NLRI_MAX %i", list_length(&buck->prefixes), size, BGP_NLRI_MAX);
struct bgp_prefix *px = HEAD(buck->prefixes);
struct net_addr_ip4 *net = NET_PTR_IP4(&px->ni->addr[0]);
@ -2329,6 +2333,7 @@ bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
lr = bgp_encode_nlri(s, buck, buf+4+la, end);
log("buf+4+la+lr = %i %i %i %i", buf, 4, la, lr);
return buf+4+la+lr;
}
@ -2487,7 +2492,7 @@ bgp_create_update_bmp(ea_list *channel_ea, struct bgp_proto *bgp_p, byte *buf, s
.mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop,
.as4_session = 1,
.add_path = c->add_path_rx,
.mpls = c->desc->mpls, //this is problem, but we can have proto. What about find correct channel in proto? TODO
.mpls = c->desc->mpls,
.ignore_non_bgp_attrs = 1,
};
log("next hop %x (0)", s.mp_next_hop);

View File

@ -217,7 +217,8 @@ static const struct ea_class *bgp_next_hop_ea_class = NULL;
static void bmp_connected(struct birdsock *sk);
static void bmp_sock_err(sock *sk, int err);
static void bmp_close_socket(struct bmp_proto *p);
static void bmp_rt_notify_exp_req(void *p_);
static void bmp_check_routes(void *bt_);
static void bmp_do_pre_policy(void *bt_);
static void
bmp_send_peer_up_notif_msg(struct bmp_proto *p, ea_list *bgp,
@ -285,6 +286,9 @@ bmp_schedule_tx_packet(struct bmp_proto *p, const byte *payload, const size_t si
log("tx_data %x data %x", tx_data, tx_data->data);
memcpy(tx_data->data, payload, size);
tx_data->data_size = size;
log("schedule tx packet size %i", size);
if (size > 5000)
log("too big");
add_tail(&p->tx_queue, &tx_data->n);
if (sk_tx_buffer_empty(p->sk)
@ -541,9 +545,11 @@ bmp_add_table_exp_req(struct bmp_proto *p, rtable *tab)
HASH_INSERT(p->table_map, HASH_TABLE, bt);
bt->event.hook = bmp_rt_notify_exp_req;
bt->event.data = bt;
log("name %s post %i pre %i", p->p.name, p->monitoring_rib.in_post_policy, p->monitoring_rib.in_pre_policy);
//if(p->monitoring_rib.in_post_policy){
bt->event.hook = bmp_check_routes;
bt->out_req = (struct rt_export_request) {
.name = mb_sprintf(p->p.pool, "%s.exp_request", p->p.name),
.r = (struct lfjour_recipient) {
@ -559,19 +565,7 @@ bmp_add_table_exp_req(struct bmp_proto *p, rtable *tab)
//.dump = channel_dump_export_req,
//.fed = channel_export_fed,
};
rt_export_subscribe(tab, all, &bt->out_req);
/*bt->in_req = (struct rt_export_feeder) {
.name = mb_sprintf(p->p.pool, "%s.imp_request", p->p.name),
.trace_routes = c->debug,
.next_feed_index = channel_reimport_next_feed_index,
};
bt->reimport_event = (event) {
.hook = bmp_do_pre_policy,
.data = bt,
};
rt_feeder_subscribe(&c->table->export_all, &bt->in_req);*/
rt_export_subscribe(tab, all, &bt->out_req);//}
return bt;
}
@ -601,7 +595,10 @@ bmp_remove_table_rt(struct bmp_proto *p, struct bmp_table *bt) // still falling
channel_set_state(bt->channel, CS_STOP);
channel_set_state(bt->channel, CS_DOWN);
}
rt_export_unsubscribe(all, &bt->out_req);
//if (p->monitoring_rib.in_post_policy)
rt_export_unsubscribe(all, &bt->out_req);
//else
//rt_feeder_unsubscribe(&bt->in_req);
HASH_REMOVE(p->table_map, HASH_TABLE, bt);
@ -654,8 +651,8 @@ static inline void bmp_unlock_table(struct bmp_proto *p, struct bmp_table *bt)
static inline u32 bmp_stream_key(u32 afi, bool policy)
{ return afi ^ (policy ? BMP_STREAM_KEY_POLICY : 0); }
static inline u32 bmp_stream_afi(struct bmp_stream *bs)
{ return bs->key & ~BMP_STREAM_KEY_POLICY; }
//static inline u32 bmp_stream_afi(struct bmp_stream *bs)
//{ return bs->key & ~BMP_STREAM_KEY_POLICY; }
static inline bool bmp_stream_policy(struct bmp_stream *bs)
{ return !!(bs->key & BMP_STREAM_KEY_POLICY); }
@ -665,6 +662,7 @@ bmp_find_stream(struct bmp_proto *p, const struct bgp_proto *bgp, u32 afi, bool
{
ea_list *bgp_attr = proto_state_table->attrs[bgp->p.id];
return HASH_FIND(p->stream_map, HASH_STREAM, bgp_attr, bmp_stream_key(afi, policy));
}
static struct bmp_stream *
@ -741,13 +739,29 @@ bmp_add_peer(struct bmp_proto *p, ea_list *bgp_attr)
{
log("chan_attr in bmp_add_peer %i, attrs %i", chan_attr, chan_attr->attrs);
rtable *ch_table = (rtable *) ea_get_ptr(chan_attr->attrs, &ea_rtable, 0);
const char *name = ea_get_adata(chan_attr->attrs, &ea_name)->data;
int in_keep = ea_get_int(chan_attr->attrs, &ea_in_keep, 0);
log("name %s ch_table %i first if %i second if %i in keep %i", name, ch_table, p->monitoring_rib.in_pre_policy, p->monitoring_rib.in_post_policy, in_keep);
log("name %i ch_table %i first if %i second if %i", &ch_table->name, ch_table, p->monitoring_rib.in_pre_policy, p->monitoring_rib.in_post_policy);
if (p->monitoring_rib.in_pre_policy && ch_table)
bmp_add_stream(p, bp, ea_get_int(chan_attr->attrs, &ea_bgp_afi, 0), false, ch_table, chan_attr->attrs, 1);
{
log("in pre");
if (in_keep == RIK_PREFILTER)
{
log("add stream in keep %i", in_keep);
bmp_add_stream(p, bp, ea_get_int(chan_attr->attrs, &ea_bgp_afi, 0), false, ch_table, chan_attr->attrs, 1);
}
else
log(L_WARN "%s: Try to do pre policy with disabled import tables (channel %s)", p->p.name, name);
}
if (p->monitoring_rib.in_post_policy && ch_table)
{
log("in post");
bmp_add_stream(p, bp, ea_get_int(chan_attr->attrs, &ea_bgp_afi, 0), true, ch_table, chan_attr->attrs, 0);
}
}
return bp;
@ -893,6 +907,7 @@ bmp_is_peer_global_instance(ea_list *bgp)
int peer_type = ea_get_int(bgp, &ea_bgp_peer_type, 0);
int local_as = ea_get_int(bgp, &ea_bgp_loc_as, 0);
int remote_as = ea_get_int(bgp, &ea_bgp_rem_as, 0);
log("bmp_is_peer_global_instance loc as %i rem as %i peer_type %i (constants BGP_PT_EXTERNAL %i, BGP_PT_INTERNAL %i)", local_as, remote_as, peer_type, BGP_PT_EXTERNAL, BGP_PT_INTERNAL);
return (peer_type != BGP_PT_EXTERNAL &&
peer_type != BGP_PT_INTERNAL)
? (local_as != remote_as)
@ -914,6 +929,7 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, ea_list *bgp,
const int rem_as = ea_get_int(bgp, &ea_bgp_rem_as, 0);
const int rem_id = ea_get_int(bgp, &ea_bgp_rem_id, 0);
log("bmp_send_peer_up_notif_msg rem_as %i rem_id %i", rem_as, rem_id);
const bool is_global_instance_peer = bmp_is_peer_global_instance(bgp);
buffer payload = bmp_buffer_alloc(p->buffer_mpool, DEFAULT_MEM_BLOCK_SIZE);
bmp_peer_up_notif_msg_serialize(&payload, is_global_instance_peer,
@ -933,6 +949,7 @@ bmp_route_monitor_put_update(struct bmp_proto *p, struct bmp_stream *bs, const b
log("upd_msg %x, data %x", upd_msg, upd_msg->data);
memcpy(upd_msg->data, data, length);
upd_msg->data_size = length;
add_tail(&p->update_msg_queue, &upd_msg->n);
/* Save some metadata */
@ -953,6 +970,7 @@ static void
bmp_route_monitor_notify(struct bmp_proto *p, struct bgp_proto *bgp_p, struct bmp_stream *bs,
const net_addr *n, const struct rte *new, const struct rte_src *src)
{
log("notified");
byte buf[BGP_MAX_EXT_MSG_LENGTH];
byte *end = bgp_bmp_encode_rte(bs->sender, bgp_p, buf, n, new, src);
@ -1184,30 +1202,41 @@ bmp_rt_notify(struct proto *P, struct channel *c, const net_addr *net,
}
static void
/*static void
bmp_do_pre_policy(void *bt_)
{
log("do pre policy");
struct bmp_table *bt = (struct bmp_table *)bt_;
struct bmp_proto *p = bt->p;
RT_FEED_WALK(&bt->in_req, f)
{
bool seen = 0;
log("count rout %i", f->count_routes);
for (uint i = 0; i < f->count_routes; i++)
{
rte *r = &f->block[i];
if (r->flags & REF_OBSOLETE)
break;
}
rte new = rte_init_from(r);
rte new = rte_init_from(r);
/* Strip the later attribute layers */
new.attrs = ea_strip_to(new.attrs, BIT32_ALL(EALS_PREIMPORT));
// Strip the later attribute layers
new.attrs = ea_strip_to(new.attrs, BIT32_ALL(EALS_PREIMPORT));
struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, new.src->owner);
if (rte_proto->proto != &proto_bgp || !bgp_next_hop_present(new))
break;
struct bgp_proto *bgp = (struct bgp_proto *) rte_proto;
struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, new.sender->req);
struct bgp_channel *src = SKIP_BACK(struct bgp_channel, c.in_req, new.sender->req);
bool policy = (bc->c.table == src->c.table); //TODO?
struct bmp_stream *bs = bmp_find_stream(p, bgp, src->afi, policy);
bmp_route_monitor_notify(p, bgp, bs, new.net, &new, new.src);
}
}
}
}*/
int
bgp_next_hop_present(const rte *n)
@ -1224,15 +1253,58 @@ bgp_next_hop_present(const rte *n)
return 0;
}
static void
bmp_rt_notify_exp_req(void *bt_)
void
solve_for_post_and_pre(struct bmp_proto *p, rte *new)
{
log("ok in notify exp req");
struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, new->src->owner);
log("solve_for_post_and_pre %s", rte_proto->name);
new->attrs = ea_normalize(new->attrs, 0);
log("after normalize ea_list %x, new %x", new->attrs, new);
log("new next %x", new->attrs->next);
if (rte_proto->proto != &proto_bgp || !bgp_next_hop_present(new)){
log("CONTINUED %s rte_proto->proto %x!= &proto_bgp %x || !bgp_next_hop_present(new %x) %i", rte_proto->proto->name, rte_proto->proto, &proto_bgp, new, !bgp_next_hop_present(new));
return;
}
struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, new->sender->req);
struct bgp_proto *bgp = (struct bgp_proto *) rte_proto;
struct bgp_channel *src = SKIP_BACK(struct bgp_channel, c.in_req, new->sender->req);
struct bmp_stream *bs = bmp_find_stream(p, bgp, src->afi, false);
if (bs)
{
log("s true bmp stream found feed, pre policy %i proto %s", bs->in_pre_policy, p->p.name);
if (bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]) == NULL)
bug("not implemented");
bmp_route_monitor_notify(p, bgp, bs, new->net, new, new->src);
}
bs = bmp_find_stream(p, bgp, src->afi, true);
if (bs)
{
if (bc->c.in_keep != RIK_PREFILTER){
log("CONTINUED bc->c.in_keep != RIK_PREFILTER");
return;
}
log("s false bmp stream found feed, pre policy %i proto %s", bs->in_pre_policy, p->p.name);
if (bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]) == NULL)
bug("not implemented");
new->attrs = ea_strip_to(new->attrs, BIT32_ALL(EALS_PREIMPORT));
if (new->attrs == NULL)
bug("Null attrs after ea_strip. This should never happen, because we checked the import table is enabled.");
bmp_route_monitor_notify(p, bgp, bs, new->net, new, new->src);
}
log("attrs out %x %s", new->attrs, rte_proto->name);
}
static void
bmp_check_routes(void *bt_)
{
log("bmp_check_routes");
struct bmp_table *bt = (struct bmp_table *)bt_;
struct bmp_proto *p = bt->p;
RT_EXPORT_WALK(&bt->out_req, u) //const struct rt_export_union *_u;
{
log("feeder %x rte ptr %x", &bt->out_req, u);
switch (u->kind)
{
case RT_EXPORT_STOP:
@ -1245,49 +1317,22 @@ bmp_rt_notify_exp_req(void *bt_)
oldpos++;
/* Send updates one after another */
log("oldpos %i", oldpos);
for (uint i = 0; i < oldpos; i++)
{
rte *new = &u->feed->block[i];
struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, new->src->owner);
if (rte_proto->proto != &proto_bgp || !bgp_next_hop_present(new))
break;
struct bgp_proto *bgp = (struct bgp_proto *) rte_proto;
struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, new->sender->req);
struct bgp_channel *src = SKIP_BACK(struct bgp_channel, c.in_req, new->sender->req);
bool policy = (bc->c.table == src->c.table); //TODO?
struct bmp_stream *bs = bmp_find_stream(p, bgp, src->afi, policy);
if (!bs)
{
log("bmp stream not found in p %i", p);
return;
}
log("bmp stream found feed, policy %i", bs->in_pre_policy);
if (bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]) == NULL)
bug("not implemented");
bmp_route_monitor_notify(p, bgp, bs, new->net, new, new->src);
log("pre policy %i rte attr %x", p->monitoring_rib.in_pre_policy, new->attrs);
solve_for_post_and_pre(p, new);
}
break;
case RT_EXPORT_UPDATE:
log("export update");
const rte *new = u->update->new;
const rte *old = u->update->old;
struct proto *rte_proto = (struct proto*) SKIP_BACK(struct proto, sources, (new ?: old)->src->owner);
if (rte_proto->proto != &proto_bgp || !bgp_next_hop_present(new ?: old))
break;
struct bgp_proto *bgp = (struct bgp_proto *) rte_proto;
struct bgp_channel *bc = (struct bgp_channel *) SKIP_BACK(struct channel, in_req, (new ?: old)->sender->req);
struct bgp_channel *src = SKIP_BACK(struct bgp_channel, c.in_req, (new ?: old)->sender->req);
bool policy = (bc->c.table == src->c.table); //TODO?
struct bmp_stream *bs = bmp_find_stream(p, bgp, src->afi, policy);
if (!bs)
{
log("bmp stream not found in p %i", p);
return;
}
log("bmp stream found update");
if (bmp_find_peer(p, proto_state_table->attrs[bgp->p.id]) == NULL)
bug("not implemented");
bmp_route_monitor_notify(p, bgp, bs, (new ?: old)->net, new, (new ?: old)->src);
rte *new = u->update->new;
rte *old = u->update->old;
log("attrs %x", new? new->attrs:1);
solve_for_post_and_pre(p, (new ?: old));
}
}
log("end of notify fce");

View File

@ -100,8 +100,8 @@ struct bmp_table {
struct bmp_table *next;
struct channel *channel;
struct rt_export_request out_req;
struct rt_export_feeder in_req;
struct bmp_proto *p;
struct rt_export_feeder in_req;
event event;
atomic_int uc;
};