diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/attrs.c | 91 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 24 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 12 | ||||
-rw-r--r-- | proto/bgp/packets.c | 17 |
4 files changed, 63 insertions, 81 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 1f927cbd..65e87c96 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -374,6 +374,13 @@ bgp_init_aigp_metric(rte *e, u64 *metric, const struct adata **ad) return *metric < IGP_METRIC_UNKNOWN; } +u32 +bgp_rte_igp_metric(struct rte *rt) +{ + u64 metric = bgp_total_aigp_metric(rt); + return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN); +} + /* * Attribute hooks @@ -1668,10 +1675,9 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) */ int -bgp_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) +bgp_preexport(struct proto *P, rte *e) { - rte *e = *new; - struct proto *SRC = e->attrs->src->proto; + struct proto *SRC = e->src->proto; struct bgp_proto *p = (struct bgp_proto *) P; struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL; @@ -1730,7 +1736,7 @@ bgp_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) static ea_list * bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs0, struct linpool *pool) { - struct proto *SRC = e->attrs->src->proto; + struct proto *SRC = e->src->proto; struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (void *) SRC : NULL; struct bgp_export_state s = { .proto = p, .channel = c, .pool = pool, .src = src, .route = e, .mpls = c->desc->mpls }; ea_list *attrs = attrs0; @@ -1854,7 +1860,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old) if (new) { - struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, bgp_linpool2); + struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, tmp_linpool); /* Error during attribute processing */ if (!attrs) @@ -1862,14 +1868,12 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old) /* If attributes are invalid, we fail back to withdraw */ buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c); - path = new->attrs->src->global_id; - - lp_flush(bgp_linpool2); + path = new->src->global_id; } else { buck = bgp_get_withdraw_bucket(c); - path = old->attrs->src->global_id; + path = old->src->global_id; } px = bgp_get_prefix(c, n->n.addr, c->add_path_tx ? path : 0); @@ -1889,34 +1893,44 @@ bgp_get_neighbor(rte *r) return as; /* If AS_PATH is not defined, we treat rte as locally originated */ - struct bgp_proto *p = (void *) r->attrs->src->proto; + struct bgp_proto *p = (void *) r->src->proto; return p->cf->confederation ?: p->local_as; } static inline int rte_stale(rte *r) { - if (r->u.bgp.stale < 0) + if (r->pflags & BGP_REF_STALE) + return 1; + + if (r->pflags & BGP_REF_NOT_STALE) + return 0; + + /* If staleness is unknown, compute and cache it */ + eattr *a = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); + if (a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE)) { - /* If staleness is unknown, compute and cache it */ - eattr *a = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY)); - r->u.bgp.stale = a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE); + r->pflags |= BGP_REF_STALE; + return 1; + } + else + { + r->pflags |= BGP_REF_NOT_STALE; + return 0; } - - return r->u.bgp.stale; } int bgp_rte_better(rte *new, rte *old) { - struct bgp_proto *new_bgp = (struct bgp_proto *) new->attrs->src->proto; - struct bgp_proto *old_bgp = (struct bgp_proto *) old->attrs->src->proto; + struct bgp_proto *new_bgp = (struct bgp_proto *) new->src->proto; + struct bgp_proto *old_bgp = (struct bgp_proto *) old->src->proto; eattr *x, *y; u32 n, o; /* Skip suppressed routes (see bgp_rte_recalculate()) */ - n = new->u.bgp.suppressed; - o = old->u.bgp.suppressed; + n = new->pflags & BGP_REF_SUPPRESSED; + o = old->pflags & BGP_REF_SUPPRESSED; if (n > o) return 0; if (n < o) @@ -2054,23 +2068,20 @@ bgp_rte_better(rte *new, rte *old) int bgp_rte_mergable(rte *pri, rte *sec) { - struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->attrs->src->proto; - struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->attrs->src->proto; + struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->src->proto; + struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->src->proto; eattr *x, *y; u32 p, s; /* Skip suppressed routes (see bgp_rte_recalculate()) */ - if (pri->u.bgp.suppressed != sec->u.bgp.suppressed) + /* LLGR draft - depreference stale routes */ + if (pri->pflags != sec->pflags) return 0; /* RFC 4271 9.1.2.1. Route resolvability test */ if (rte_resolvable(pri) != rte_resolvable(sec)) return 0; - /* LLGR draft - depreference stale routes */ - if (rte_stale(pri) != rte_stale(sec)) - return 0; - /* Start with local preferences */ x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF)); @@ -2133,13 +2144,13 @@ bgp_rte_mergable(rte *pri, rte *sec) static inline int same_group(rte *r, u32 lpref, u32 lasn) { - return (r->pref == lpref) && (bgp_get_neighbor(r) == lasn); + return (r->attrs->pref == lpref) && (bgp_get_neighbor(r) == lasn); } static inline int use_deterministic_med(rte *r) { - struct proto *P = r->attrs->src->proto; + struct proto *P = r->src->proto; return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med; } @@ -2148,9 +2159,9 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best) { rte *r, *s; rte *key = new ? new : old; - u32 lpref = key->pref; + u32 lpref = key->attrs->pref; u32 lasn = bgp_get_neighbor(key); - int old_suppressed = old ? old->u.bgp.suppressed : 0; + int old_suppressed = old ? !!(old->pflags & BGP_REF_SUPPRESSED) : 0; /* * Proper RFC 4271 path selection is a bit complicated, it cannot be @@ -2202,11 +2213,11 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best) */ if (new) - new->u.bgp.suppressed = 1; + new->pflags |= BGP_REF_SUPPRESSED; if (old) { - old->u.bgp.suppressed = 1; + old->pflags |= BGP_REF_SUPPRESSED; /* The fast case - replace not best with worse (or remove not best) */ if (old_suppressed && !(new && bgp_rte_better(new, old))) @@ -2218,7 +2229,7 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best) for (s=net->routes; rte_is_valid(s); s=s->next) if (use_deterministic_med(s) && same_group(s, lpref, lasn)) { - s->u.bgp.suppressed = 1; + s->pflags |= BGP_REF_SUPPRESSED; if (!r || bgp_rte_better(s, r)) r = s; } @@ -2229,16 +2240,16 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best) /* Found if new is mergable with best-in-group */ if (new && (new != r) && bgp_rte_mergable(r, new)) - new->u.bgp.suppressed = 0; + new->pflags &= ~BGP_REF_SUPPRESSED; /* Found all existing routes mergable with best-in-group */ for (s=net->routes; rte_is_valid(s); s=s->next) if (use_deterministic_med(s) && same_group(s, lpref, lasn)) if ((s != r) && bgp_rte_mergable(r, s)) - s->u.bgp.suppressed = 0; + s->pflags &= ~BGP_REF_SUPPRESSED; /* Found best-in-group */ - r->u.bgp.suppressed = 0; + r->pflags &= ~BGP_REF_SUPPRESSED; /* * There are generally two reasons why we have to force @@ -2286,7 +2297,7 @@ bgp_rte_modify_stale(struct rte *r, struct linpool *pool) r = rte_cow_rta(r, pool); bgp_set_attr_ptr(&(r->attrs->eattrs), pool, BA_COMMUNITY, flags, int_set_add(pool, ad, BGP_COMM_LLGR_STALE)); - r->u.bgp.stale = 1; + r->pflags |= BGP_REF_STALE; return r; } @@ -2371,9 +2382,9 @@ bgp_get_route_info(rte *e, byte *buf) eattr *o = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); u32 origas; - buf += bsprintf(buf, " (%d", e->pref); + buf += bsprintf(buf, " (%d", e->attrs->pref); - if (e->u.bgp.suppressed) + if (e->pflags & BGP_REF_SUPPRESSED) buf += bsprintf(buf, "-"); if (rte_stale(e)) diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 619a816b..52400762 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -126,9 +126,7 @@ #include "bgp.h" -struct linpool *bgp_linpool; /* Global temporary pool */ -struct linpool *bgp_linpool2; /* Global temporary pool for bgp_rt_notify() */ -static list bgp_sockets; /* Global list of listening sockets */ +static list STATIC_LIST_INIT(bgp_sockets); /* Global list of listening sockets */ static void bgp_connect(struct bgp_proto *p); @@ -161,10 +159,6 @@ bgp_open(struct bgp_proto *p) uint flags = p->cf->free_bind ? SKF_FREEBIND : 0; uint flag_mask = SKF_FREEBIND; - /* FIXME: Add some global init? */ - if (!bgp_linpool) - init_list(&bgp_sockets); - /* We assume that cf->iface is defined iff cf->local_ip is link-local */ WALK_LIST(bs, bgp_sockets) @@ -204,12 +198,6 @@ bgp_open(struct bgp_proto *p) add_tail(&bgp_sockets, &bs->n); - if (!bgp_linpool) - { - bgp_linpool = lp_new_default(proto_pool); - bgp_linpool2 = lp_new_default(proto_pool); - } - return 0; err: @@ -238,15 +226,6 @@ bgp_close(struct bgp_proto *p) rfree(bs->sk); rem_node(&bs->n); mb_free(bs); - - if (!EMPTY_LIST(bgp_sockets)) - return; - - rfree(bgp_linpool); - bgp_linpool = NULL; - - rfree(bgp_linpool2); - bgp_linpool2 = NULL; } static inline int @@ -1700,6 +1679,7 @@ bgp_init(struct proto_config *CF) P->rte_mergable = bgp_rte_mergable; P->rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL; P->rte_modify = bgp_rte_modify_stale; + P->rte_igp_metric = bgp_rte_igp_metric; p->cf = cf; p->is_internal = (cf->local_as == cf->remote_as); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 4969c0b9..bff49c3a 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -20,7 +20,6 @@ #include "lib/hash.h" #include "lib/socket.h" -struct linpool; struct eattr; @@ -203,6 +202,10 @@ struct bgp_channel_config { #define BGP_BFD_GRACEFUL 2 /* BFD down triggers graceful restart */ +/* rte->pflags */ +#define BGP_REF_SUPPRESSED 0x1 /* Used for deterministic MED comparison */ +#define BGP_REF_STALE 0x2 /* Route is LLGR_STATE */ +#define BGP_REF_NOT_STALE 0x4 /* Route is NOT LLGR_STATE */ struct bgp_af_caps { u32 afi; @@ -454,7 +457,6 @@ struct bgp_parse_state { jmp_buf err_jmpbuf; struct hostentry *hostentry; - struct rtable *base_table; adata *mpls_labels; /* Cached state for bgp_rte_update() */ @@ -495,9 +497,6 @@ bgp_parse_error(struct bgp_parse_state *s, uint subcode) longjmp(s->err_jmpbuf, 1); } -extern struct linpool *bgp_linpool; -extern struct linpool *bgp_linpool2; - void bgp_start_timer(timer *t, uint value); void bgp_check_config(struct bgp_config *c); @@ -588,8 +587,9 @@ int bgp_rte_better(struct rte *, struct rte *); int bgp_rte_mergable(rte *pri, rte *sec); int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best); struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool); +u32 bgp_rte_igp_metric(struct rte *); void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old); -int bgp_preexport(struct proto *, struct rte **, struct linpool *); +int bgp_preexport(struct proto *, struct rte *); int bgp_get_attr(const struct eattr *e, byte *buf, int buflen); void bgp_get_route_info(struct rte *, byte *buf); int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index f13625e2..66f14150 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1025,9 +1025,6 @@ bgp_apply_flow_validation(struct bgp_parse_state *s, const net_addr *n, rta *a) int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->proto->is_interior); a->dest = valid ? RTD_NONE : RTD_UNREACHABLE; - /* Set rte.bgp.base_table later from this state variable */ - s->base_table = c->base_table; - /* Invalidate cached rta if dest changes */ if (s->cached_rta && (s->cached_rta->dest != a->dest)) { @@ -1386,8 +1383,6 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a /* Prepare cached route attributes */ if (s->cached_rta == NULL) { - a0->src = s->last_src; - /* Workaround for rta_lookup() breaking eattrs */ ea_list *ea = a0->eattrs; s->cached_rta = rta_lookup(a0); @@ -1395,12 +1390,9 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a } rta *a = rta_clone(s->cached_rta); - rte *e = rte_get_temp(a); + rte *e = rte_get_temp(a, s->last_src); e->pflags = 0; - e->u.bgp.suppressed = 0; - e->u.bgp.stale = -1; - e->u.bgp.base_table = s->base_table; rte_update3(&s->channel->c, n, e, s->last_src); } @@ -2335,7 +2327,7 @@ again: ; struct bgp_write_state s = { .proto = p, .channel = c, - .pool = bgp_linpool, + .pool = tmp_linpool, .mp_reach = (c->afi != BGP_AF_IPV4) || c->ext_next_hop, .as4_session = p->as4_session, .add_path = c->add_path_tx, @@ -2464,8 +2456,6 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis s->last_id = 0; s->last_src = s->proto->p.main_source; - s->base_table = NULL; - /* * IPv4 BGP and MP-BGP may be used together in one update, therefore we do not * add BA_NEXT_HOP in bgp_decode_attrs(), but we add it here independently for @@ -2481,6 +2471,7 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis a->scope = SCOPE_UNIVERSE; a->from = s->proto->remote_ip; a->eattrs = ea; + a->pref = c->c.preference; c->desc->decode_next_hop(s, nh, nh_len, a); bgp_finish_attrs(s, a); @@ -2518,7 +2509,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) /* Initialize parse state */ struct bgp_parse_state s = { .proto = p, - .pool = bgp_linpool, + .pool = tmp_linpool, .as4_session = p->as4_session, }; |