diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/Makefile | 3 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 98 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 29 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 16 | ||||
-rw-r--r-- | proto/bgp/packets.c | 33 |
5 files changed, 89 insertions, 90 deletions
diff --git a/proto/bgp/Makefile b/proto/bgp/Makefile index 00aaef5e..2a4cc99c 100644 --- a/proto/bgp/Makefile +++ b/proto/bgp/Makefile @@ -2,5 +2,6 @@ src := attrs.c bgp.c packets.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,bgp_build) -tests_objs := $(tests_objs) $(src-o-files)
\ No newline at end of file +tests_objs := $(tests_objs) $(src-o-files) diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 0d2116b7..a56aeb19 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -106,7 +106,7 @@ bgp_set_attr(ea_list **attrs, struct linpool *pool, uint code, uint flags, uintp ({ REPORT(msg, ## args); s->err_withdraw = 1; return; }) #define UNSET(a) \ - ({ a->type = EAF_TYPE_UNDEF; return; }) + ({ a->undef = 1; return; }) #define REJECT(msg, args...) \ ({ log(L_ERR "%s: " msg, s->proto->p.name, ## args); s->err_reject = 1; return; }) @@ -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 @@ -1165,7 +1172,7 @@ bgp_export_attr(struct bgp_export_state *s, eattr *a, ea_list *to) a->flags = (a->flags & BAF_PARTIAL) | desc->flags; /* Set partial bit if new opt-trans attribute is attached to non-local route */ - if ((s->src != NULL) && (a->type & EAF_ORIGINATED) && + if ((s->src != NULL) && (a->originated) && (a->flags & BAF_OPTIONAL) && (a->flags & BAF_TRANSITIVE)) a->flags |= BAF_PARTIAL; @@ -1173,7 +1180,7 @@ bgp_export_attr(struct bgp_export_state *s, eattr *a, ea_list *to) CALL(desc->export, s, a); /* Attribute might become undefined in hook */ - if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) + if (a->undef) return; } else @@ -1700,7 +1707,7 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) HASH_REMOVE2(c->prefix_hash, PXH, c->pool, px); if (c->prefix_slab) - sl_free(c->prefix_slab, px); + sl_free(px); else mb_free(px); } @@ -1711,13 +1718,12 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) */ int -bgp_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) +bgp_preexport(struct channel *C, rte *e) { - rte *e = *new; - struct proto *SRC = e->attrs->src->proto; - struct bgp_channel *c = (struct bgp_channel *) C; + struct proto *SRC = e->src->proto; struct bgp_proto *p = (struct bgp_proto *) C->proto; struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL; + struct bgp_channel *c = (struct bgp_channel *) C; /* Reject our routes */ if (src == p) @@ -1784,7 +1790,7 @@ bgp_preexport(struct channel *C, 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; @@ -1824,7 +1830,7 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at /* MULTI_EXIT_DESC attribute - accept only if set in export filter */ a = bgp_find_attr(attrs0, BA_MULTI_EXIT_DISC); - if (a && !(a->type & EAF_FRESH)) + if (a && !(a->fresh)) bgp_unset_attr(&attrs, pool, BA_MULTI_EXIT_DISC); } @@ -1918,7 +1924,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) @@ -1926,14 +1932,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); @@ -1953,34 +1957,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) @@ -2118,13 +2132,13 @@ 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) + if ((pri->pflags ^ sec->pflags) & BGP_REF_SUPPRESSED) return 0; /* RFC 4271 9.1.2.1. Route resolvability test */ @@ -2197,13 +2211,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; } @@ -2212,9 +2226,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 @@ -2266,11 +2280,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))) @@ -2282,7 +2296,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; } @@ -2293,16 +2307,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 @@ -2350,7 +2364,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; } @@ -2435,9 +2449,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 0f06746f..f07fcc16 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -127,9 +127,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); @@ -162,10 +160,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) @@ -205,12 +199,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: @@ -239,15 +227,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 @@ -1701,6 +1680,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); @@ -2637,3 +2617,8 @@ struct protocol proto_bgp = { .get_route_info = bgp_get_route_info, .show_proto_info = bgp_show_proto_info }; + +void bgp_build(void) +{ + proto_build(&proto_bgp); +} diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index fea87304..15a759fb 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; @@ -212,6 +211,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; @@ -464,7 +467,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() */ @@ -511,9 +513,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); @@ -580,9 +579,7 @@ bgp_set_attr_data(ea_list **to, struct linpool *pool, uint code, uint flags, voi bgp_set_attr(to, pool, code, flags, (uintptr_t) a); } -static inline void -bgp_unset_attr(ea_list **to, struct linpool *pool, uint code) -{ eattr *e = bgp_set_attr(to, pool, code, 0, 0); e->type = EAF_TYPE_UNDEF; } +#define bgp_unset_attr(to, pool, code) ea_unset_attr(to, pool, 0, code) int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size); @@ -604,8 +601,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 channel *, struct rte **, struct linpool *); +int bgp_preexport(struct channel *, 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 54423a1a..3aa62c39 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1068,9 +1068,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)) { @@ -1108,7 +1105,7 @@ bgp_use_next_hop(struct bgp_export_state *s, eattr *a) return 1; /* Keep it when explicitly set in export filter */ - if (a->type & EAF_FRESH) + if (a->fresh) return 1; /* Check for non-matching AF */ @@ -1429,8 +1426,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); @@ -1438,12 +1433,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); } @@ -2374,11 +2366,14 @@ bgp_create_update(struct bgp_channel *c, byte *buf) again: ; + struct lp_state tmpp; + lp_save(tmp_linpool, &tmpp); + /* Initialize write state */ 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, @@ -2404,6 +2399,7 @@ again: ; if (EMPTY_LIST(buck->prefixes)) { bgp_free_bucket(c, buck); + lp_restore(tmp_linpool, &tmpp); goto again; } @@ -2417,7 +2413,10 @@ again: ; bgp_defer_bucket(c, buck); if (!res) + { + lp_restore(tmp_linpool, &tmpp); goto again; + } goto done; } @@ -2428,7 +2427,7 @@ again: ; done: BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE"); p->stats.tx_updates++; - lp_flush(s.pool); + lp_restore(tmp_linpool, &tmpp); return res; } @@ -2507,8 +2506,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 @@ -2524,6 +2521,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); @@ -2558,10 +2556,13 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) bgp_start_timer(conn->hold_timer, conn->hold_time); + struct lp_state tmpp; + lp_save(tmp_linpool, &tmpp); + /* Initialize parse state */ struct bgp_parse_state s = { .proto = p, - .pool = bgp_linpool, + .pool = tmp_linpool, .as4_session = p->as4_session, }; @@ -2639,7 +2640,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) done: rta_free(s.cached_rta); - lp_flush(s.pool); + lp_restore(tmp_linpool, &tmpp); return; } |