diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/babel/Makefile | 1 | ||||
-rw-r--r-- | proto/babel/babel.c | 129 | ||||
-rw-r--r-- | proto/babel/babel.h | 1 | ||||
-rw-r--r-- | proto/babel/packets.c | 9 | ||||
-rw-r--r-- | proto/bfd/Makefile | 3 | ||||
-rw-r--r-- | proto/bfd/bfd.c | 19 | ||||
-rw-r--r-- | proto/bfd/io.c | 2 | ||||
-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 | ||||
-rw-r--r-- | proto/mrt/Makefile | 3 | ||||
-rw-r--r-- | proto/mrt/mrt.c | 20 | ||||
-rw-r--r-- | proto/ospf/Makefile | 3 | ||||
-rw-r--r-- | proto/ospf/iface.c | 3 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 90 | ||||
-rw-r--r-- | proto/ospf/rt.c | 54 | ||||
-rw-r--r-- | proto/ospf/topology.c | 2 | ||||
-rw-r--r-- | proto/perf/Makefile | 1 | ||||
-rw-r--r-- | proto/perf/perf.c | 10 | ||||
-rw-r--r-- | proto/pipe/Makefile | 3 | ||||
-rw-r--r-- | proto/pipe/pipe.c | 36 | ||||
-rw-r--r-- | proto/radv/Makefile | 3 | ||||
-rw-r--r-- | proto/radv/radv.c | 10 | ||||
-rw-r--r-- | proto/rip/Makefile | 3 | ||||
-rw-r--r-- | proto/rip/rip.c | 108 | ||||
-rw-r--r-- | proto/rip/rip.h | 1 | ||||
-rw-r--r-- | proto/rpki/Makefile | 3 | ||||
-rw-r--r-- | proto/rpki/rpki.c | 12 | ||||
-rw-r--r-- | proto/static/Makefile | 3 | ||||
-rw-r--r-- | proto/static/static.c | 21 |
32 files changed, 419 insertions, 313 deletions
diff --git a/proto/babel/Makefile b/proto/babel/Makefile index 06b58e95..ae6aeaf2 100644 --- a/proto/babel/Makefile +++ b/proto/babel/Makefile @@ -2,5 +2,6 @@ src := babel.c packets.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,babel_build) tests_objs := $(tests_objs) $(src-o-files) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 0d0304f9..7ea1aba8 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -119,7 +119,7 @@ babel_get_source(struct babel_proto *p, struct babel_entry *e, u64 router_id) } static void -babel_expire_sources(struct babel_proto *p, struct babel_entry *e) +babel_expire_sources(struct babel_proto *p UNUSED, struct babel_entry *e) { struct babel_source *n, *nx; btime now_ = current_time(); @@ -129,7 +129,7 @@ babel_expire_sources(struct babel_proto *p, struct babel_entry *e) if (n->expires && n->expires <= now_) { rem_node(NODE n); - sl_free(p->source_slab, n); + sl_free(n); } } } @@ -174,7 +174,7 @@ babel_retract_route(struct babel_proto *p, struct babel_route *r) } static void -babel_flush_route(struct babel_proto *p, struct babel_route *r) +babel_flush_route(struct babel_proto *p UNUSED, struct babel_route *r) { DBG("Babel: Flush route %N router_id %lR neigh %I\n", r->e->n.addr, r->router_id, r->neigh->addr); @@ -185,7 +185,7 @@ babel_flush_route(struct babel_proto *p, struct babel_route *r) if (r->e->selected == r) r->e->selected = NULL; - sl_free(p->route_slab, r); + sl_free(r); } static void @@ -338,13 +338,13 @@ found: } static void -babel_remove_seqno_request(struct babel_proto *p, struct babel_seqno_request *sr) +babel_remove_seqno_request(struct babel_proto *p UNUSED, struct babel_seqno_request *sr) { if (sr->nbr) rem_node(&sr->nbr_node); rem_node(NODE sr); - sl_free(p->seqno_slab, sr); + sl_free(sr); } static int @@ -640,13 +640,36 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) if (r) { rta a0 = { - .src = p->p.main_source, .source = RTS_BABEL, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, + .pref = c->preference, .from = r->neigh->addr, .nh.gw = r->next_hop, .nh.iface = r->neigh->ifa->iface, + .eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr)), + }; + + *a0.eattrs = (ea_list) { .count = 3 }; + a0.eattrs->attrs[0] = (eattr) { + .id = EA_BABEL_METRIC, + .type = EAF_TYPE_INT, + .u.data = r->metric, + }; + + struct adata *ad = alloca(sizeof(struct adata) + sizeof(u64)); + ad->length = sizeof(u64); + memcpy(ad->data, &(r->router_id), sizeof(u64)); + a0.eattrs->attrs[1] = (eattr) { + .id = EA_BABEL_ROUTER_ID, + .type = EAF_TYPE_OPAQUE, + .u.ptr = ad, + }; + + a0.eattrs->attrs[2] = (eattr) { + .id = EA_BABEL_SEQNO, + .type = EAF_TYPE_INT, + .u.data = r->seqno, }; /* @@ -658,11 +681,7 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) a0.nh.flags = RNF_ONLINK; rta *a = rta_lookup(&a0); - rte *rte = rte_get_temp(a); - rte->u.babel.seqno = r->seqno; - rte->u.babel.metric = r->metric; - rte->u.babel.router_id = r->router_id; - rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID); + rte *rte = rte_get_temp(a, p->p.main_source); e->unreachable = 0; rte_update2(c, e->n.addr, rte, p->p.main_source); @@ -671,17 +690,15 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) { /* Unreachable */ rta a0 = { - .src = p->p.main_source, .source = RTS_BABEL, .scope = SCOPE_UNIVERSE, .dest = RTD_UNREACHABLE, + .pref = 1, }; rta *a = rta_lookup(&a0); - rte *rte = rte_get_temp(a); - memset(&rte->u.babel, 0, sizeof(rte->u.babel)); + rte *rte = rte_get_temp(a, p->p.main_source); rte->pflags = 0; - rte->pref = 1; e->unreachable = 1; rte_update2(c, e->n.addr, rte, p->p.main_source); @@ -2009,7 +2026,13 @@ babel_dump(struct proto *P) static void babel_get_route_info(rte *rte, byte *buf) { - buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id); + u64 rid = 0; + eattr *e = ea_find(rte->attrs->eattrs, EA_BABEL_ROUTER_ID); + if (e) + memcpy(&rid, e->u.ptr->data, sizeof(u64)); + + buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref, + ea_get_int(rte->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY), rid); } static int @@ -2017,6 +2040,9 @@ babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED) { switch (a->id) { + case EA_BABEL_SEQNO: + return GA_FULL; + case EA_BABEL_METRIC: bsprintf(buf, "metric: %d", a->u.data); return GA_FULL; @@ -2230,38 +2256,16 @@ babel_kick_timer(struct babel_proto *p) static int -babel_preexport(struct channel *C, struct rte **new, struct linpool *pool UNUSED) +babel_preexport(struct channel *C, struct rte *new) { - struct rta *a = (*new)->attrs; - + struct rta *a = new->attrs; /* Reject our own unreachable routes */ - if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == C->proto)) + if ((a->dest == RTD_UNREACHABLE) && (new->src->proto == C->proto)) return -1; return 0; } -static void -babel_make_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - struct adata *id = lp_alloc_adata(pool, sizeof(u64)); - memcpy(id->data, &rt->u.babel.router_id, sizeof(u64)); - - rte_init_tmp_attrs(rt, pool, 2); - rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric); - rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id); -} - -static void -babel_store_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 2); - rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC); - - /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */ - rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID); -} - /* * babel_rt_notify - core tells us about new route (possibly our own), * so store it into our data structures. @@ -2276,10 +2280,22 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, if (new) { /* Update */ - uint internal = (new->attrs->src->proto == P); - uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno; + uint rt_seqno; uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0); - u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id; + u64 rt_router_id = 0; + + if (new->src->proto == P) + { + rt_seqno = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data; + eattr *e = ea_find(new->attrs->eattrs, EA_BABEL_ROUTER_ID); + if (e) + memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64)); + } + else + { + rt_seqno = p->update_seqno; + rt_router_id = p->router_id; + } if (rt_metric > BABEL_INFINITY) { @@ -2322,15 +2338,16 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, static int babel_rte_better(struct rte *new, struct rte *old) { - return new->u.babel.metric < old->u.babel.metric; + uint new_metric = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data; + uint old_metric = ea_find(old->attrs->eattrs, EA_BABEL_SEQNO)->u.data; + + return new_metric < old_metric; } -static int -babel_rte_same(struct rte *new, struct rte *old) +static u32 +babel_rte_igp_metric(struct rte *rt) { - return ((new->u.babel.seqno == old->u.babel.seqno) && - (new->u.babel.metric == old->u.babel.metric) && - (new->u.babel.router_id == old->u.babel.router_id)); + return ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY); } @@ -2364,10 +2381,8 @@ babel_init(struct proto_config *CF) P->if_notify = babel_if_notify; P->rt_notify = babel_rt_notify; P->preexport = babel_preexport; - P->make_tmp_attrs = babel_make_tmp_attrs; - P->store_tmp_attrs = babel_store_tmp_attrs; P->rte_better = babel_rte_better; - P->rte_same = babel_rte_same; + P->rte_igp_metric = babel_rte_igp_metric; return P; } @@ -2483,3 +2498,9 @@ struct protocol proto_babel = { .get_route_info = babel_get_route_info, .get_attr = babel_get_attr }; + +void +babel_build(void) +{ + proto_build(&proto_babel); +} diff --git a/proto/babel/babel.h b/proto/babel/babel.h index 84feb085..8b6da3c8 100644 --- a/proto/babel/babel.h +++ b/proto/babel/babel.h @@ -28,6 +28,7 @@ #define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0) #define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1) +#define EA_BABEL_SEQNO EA_CODE(PROTOCOL_BABEL, 2) #define BABEL_MAGIC 42 #define BABEL_VERSION 2 diff --git a/proto/babel/packets.c b/proto/babel/packets.c index 2647a79f..d4acc170 100644 --- a/proto/babel/packets.c +++ b/proto/babel/packets.c @@ -1318,7 +1318,6 @@ babel_send_to(struct babel_iface *ifa, ip_addr dest) static uint babel_write_queue(struct babel_iface *ifa, list *queue) { - struct babel_proto *p = ifa->proto; struct babel_write_state state = { .next_hop_ip6 = ifa->addr }; if (EMPTY_LIST(*queue)) @@ -1346,7 +1345,7 @@ babel_write_queue(struct babel_iface *ifa, list *queue) pos += len; rem_node(NODE msg); - sl_free(p->msg_slab, msg); + sl_free(msg); } pos += babel_auth_add_tlvs(ifa, (struct babel_tlv *) pos, end - pos); @@ -1507,13 +1506,13 @@ babel_process_packet(struct babel_iface *ifa, else if (res == PARSE_IGNORE) { DBG("Babel: Ignoring TLV of type %d\n", tlv->type); - sl_free(p->msg_slab, msg); + sl_free(msg); } else /* PARSE_ERROR */ { LOG_PKT("Bad TLV from %I via %s type %d pos %d - parse error", saddr, ifa->iface->name, tlv->type, (int) ((byte *)tlv - (byte *)pkt)); - sl_free(p->msg_slab, msg); + sl_free(msg); break; } } @@ -1525,7 +1524,7 @@ babel_process_packet(struct babel_iface *ifa, if (tlv_data[msg->msg.type].handle_tlv) tlv_data[msg->msg.type].handle_tlv(&msg->msg, ifa); rem_node(NODE msg); - sl_free(p->msg_slab, msg); + sl_free(msg); } } diff --git a/proto/bfd/Makefile b/proto/bfd/Makefile index 402122fc..dbdc0a09 100644 --- a/proto/bfd/Makefile +++ b/proto/bfd/Makefile @@ -2,5 +2,6 @@ src := bfd.c io.c packets.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,bfd_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/bfd/bfd.c b/proto/bfd/bfd.c index cc941695..873e2ed5 100644 --- a/proto/bfd/bfd.c +++ b/proto/bfd/bfd.c @@ -113,8 +113,8 @@ #define HASH_IP_EQ(a1,n1,a2,n2) ipa_equal(a1, a2) && n1 == n2 #define HASH_IP_FN(a,n) ipa_hash(a) ^ u32_hash(n) -static list bfd_proto_list; -static list bfd_wait_list; +static list STATIC_LIST_INIT(bfd_proto_list); +static list STATIC_LIST_INIT(bfd_wait_list); const char *bfd_state_names[] = { "AdminDown", "Down", "Init", "Up" }; @@ -508,7 +508,7 @@ bfd_remove_session(struct bfd_proto *p, struct bfd_session *s) HASH_REMOVE(p->session_hash_id, HASH_ID, s); HASH_REMOVE(p->session_hash_ip, HASH_IP, s); - sl_free(p->session_slab, s); + sl_free(s); TRACE(D_EVENTS, "Session to %I removed", ip); @@ -1007,13 +1007,6 @@ bfd_notify_init(struct bfd_proto *p) * BFD protocol glue */ -void -bfd_init_all(void) -{ - init_list(&bfd_proto_list); - init_list(&bfd_wait_list); -} - static struct proto * bfd_init(struct proto_config *c) { @@ -1199,3 +1192,9 @@ struct protocol proto_bfd = { .reconfigure = bfd_reconfigure, .copy_config = bfd_copy_config, }; + +void +bfd_build(void) +{ + proto_build(&proto_bfd); +} diff --git a/proto/bfd/io.c b/proto/bfd/io.c index 1cd9365a..e696cc89 100644 --- a/proto/bfd/io.c +++ b/proto/bfd/io.c @@ -482,6 +482,8 @@ birdloop_main(void *arg) birdloop_set_current(loop); + tmp_init(loop->pool); + pthread_mutex_lock(&loop->mutex); while (1) { 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; } diff --git a/proto/mrt/Makefile b/proto/mrt/Makefile index 925fb102..000e1c1c 100644 --- a/proto/mrt/Makefile +++ b/proto/mrt/Makefile @@ -2,5 +2,6 @@ src := mrt.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,mrt_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/mrt/mrt.c b/proto/mrt/mrt.c index 8d97c860..321c6395 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -472,9 +472,9 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r) #ifdef CONFIG_BGP /* Find peer index */ - if (r->attrs->src->proto->proto == &proto_bgp) + if (r->src->proto->proto == &proto_bgp) { - struct bgp_proto *p = (void *) r->attrs->src->proto; + struct bgp_proto *p = (void *) r->src->proto; struct mrt_peer_entry *n = HASH_FIND(s->peer_hash, PEER, p->remote_id, p->remote_as, p->remote_ip); @@ -488,7 +488,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r) /* Path Identifier */ if (s->add_path) - mrt_put_u32(b, r->attrs->src->private_id); + mrt_put_u32(b, r->src->private_id); /* Route Attributes */ mrt_put_u16(b, 0); @@ -519,14 +519,12 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path) continue; /* Skip routes that should be reported in the other phase */ - if (!s->always_add_path && (!rt->attrs->src->private_id != !s->add_path)) + if (!s->always_add_path && (!rt->src->private_id != !s->add_path)) { s->want_add_path = 1; continue; } - rte_make_tmp_attrs(&rt, s->linpool, NULL); - if (f_run(s->filter, &rt, s->linpool, 0) <= F_ACCEPT) mrt_rib_table_entry(s, rt); @@ -562,8 +560,8 @@ mrt_table_dump_init(pool *pp) struct mrt_table_dump_state *s = mb_allocz(pool, sizeof(struct mrt_table_dump_state)); s->pool = pool; - s->linpool = lp_new(pool, 4080); - s->peer_lp = lp_new(pool, 4080); + s->linpool = lp_new(pool); + s->peer_lp = lp_new(pool); mrt_buffer_init(&s->buf, pool, 2 * MRT_ATTR_BUFFER_SIZE); /* We lock the current config as we may reference it indirectly by filter */ @@ -918,3 +916,9 @@ struct protocol proto_mrt = { .reconfigure = mrt_reconfigure, .copy_config = mrt_copy_config, }; + +void +mrt_build(void) +{ + proto_build(&proto_mrt); +} diff --git a/proto/ospf/Makefile b/proto/ospf/Makefile index 39e74f71..85664543 100644 --- a/proto/ospf/Makefile +++ b/proto/ospf/Makefile @@ -2,5 +2,6 @@ src := dbdes.c hello.c iface.c lsack.c lsalib.c lsreq.c lsupd.c neighbor.c ospf. obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,ospf_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/ospf/iface.c b/proto/ospf/iface.c index f38b8210..4cd45033 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -522,7 +522,10 @@ static inline void add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found) { struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node)); + + n->n = (node) {}; add_tail(&ifa->nbma_list, NODE n); + n->ip = src->ip; n->eligible = src->eligible; n->found = found; diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 42ffdb06..ad4b2d14 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -107,12 +107,10 @@ #include <stdlib.h> #include "ospf.h" -static int ospf_preexport(struct channel *C, rte **new, struct linpool *pool); -static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); -static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool); +static int ospf_preexport(struct channel *P, rte *new); static void ospf_reload_routes(struct channel *C); static int ospf_rte_better(struct rte *new, struct rte *old); -static int ospf_rte_same(struct rte *new, struct rte *old); +static u32 ospf_rte_igp_metric(struct rte *rt); static void ospf_disp(timer *timer); @@ -301,7 +299,7 @@ ospf_start(struct proto *P) p->lsab_size = 256; p->lsab_used = 0; p->lsab = mb_alloc(P->pool, p->lsab_size); - p->nhpool = lp_new(P->pool, 12*sizeof(struct nexthop)); + p->nhpool = lp_new(P->pool); init_list(&(p->iface_list)); init_list(&(p->area_list)); fib_init(&p->rtf, P->pool, ospf_get_af(p), sizeof(ort), OFFSETOF(ort, fn), 0, NULL); @@ -378,10 +376,8 @@ ospf_init(struct proto_config *CF) P->reload_routes = ospf_reload_routes; P->feed_begin = ospf_feed_begin; P->feed_end = ospf_feed_end; - P->make_tmp_attrs = ospf_make_tmp_attrs; - P->store_tmp_attrs = ospf_store_tmp_attrs; P->rte_better = ospf_rte_better; - P->rte_same = ospf_rte_same; + P->rte_igp_metric = ospf_rte_igp_metric; return P; } @@ -390,7 +386,9 @@ ospf_init(struct proto_config *CF) static int ospf_rte_better(struct rte *new, struct rte *old) { - if (new->u.ospf.metric1 == LSINFINITY) + u32 new_metric1 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY); + + if (new_metric1 == LSINFINITY) return 0; if(new->attrs->source < old->attrs->source) return 1; @@ -398,27 +396,27 @@ ospf_rte_better(struct rte *new, struct rte *old) if(new->attrs->source == RTS_OSPF_EXT2) { - if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1; - if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0; + u32 old_metric2 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY); + u32 new_metric2 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY); + if(new_metric2 < old_metric2) return 1; + if(new_metric2 > old_metric2) return 0; } - if (new->u.ospf.metric1 < old->u.ospf.metric1) + u32 old_metric1 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY); + if (new_metric1 < old_metric1) return 1; return 0; /* Old is shorter or same */ } -static int -ospf_rte_same(struct rte *new, struct rte *old) +static u32 +ospf_rte_igp_metric(struct rte *rt) { - /* new->attrs == old->attrs always */ - return - new->u.ospf.metric1 == old->u.ospf.metric1 && - new->u.ospf.metric2 == old->u.ospf.metric2 && - new->u.ospf.tag == old->u.ospf.tag && - new->u.ospf.router_id == old->u.ospf.router_id; -} + if (rt->attrs->source == RTS_OSPF_EXT2) + return IGP_METRIC_UNKNOWN; + return ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY); +} void ospf_schedule_rtcalc(struct ospf_proto *p) @@ -484,14 +482,13 @@ ospf_disp(timer * timer) * import to the filters. */ static int -ospf_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) +ospf_preexport(struct channel *C, rte *e) { struct ospf_proto *p = (struct ospf_proto *) C->proto; struct ospf_area *oa = ospf_main_area(p); - rte *e = *new; /* Reject our own routes */ - if (e->attrs->src->proto == &p->p) + if (e->src->proto == &p->p) return -1; /* Do not export routes to stub areas */ @@ -501,26 +498,6 @@ ospf_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) return 0; } -static void -ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 4); - rte_make_tmp_attr(rt, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1); - rte_make_tmp_attr(rt, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2); - rte_make_tmp_attr(rt, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag); - rte_make_tmp_attr(rt, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id); -} - -static void -ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 4); - rt->u.ospf.metric1 = rte_store_tmp_attr(rt, EA_OSPF_METRIC1); - rt->u.ospf.metric2 = rte_store_tmp_attr(rt, EA_OSPF_METRIC2); - rt->u.ospf.tag = rte_store_tmp_attr(rt, EA_OSPF_TAG); - rt->u.ospf.router_id = rte_store_tmp_attr(rt, EA_OSPF_ROUTER_ID); -} - /** * ospf_shutdown - Finish of OSPF instance * @P: OSPF protocol instance @@ -558,6 +535,9 @@ ospf_shutdown(struct proto *P) } FIB_WALK_END; + if (tm_active(p->disp_timer)) + tm_stop(p->disp_timer); + return PS_DOWN; } @@ -607,16 +587,20 @@ ospf_get_route_info(rte * rte, byte * buf) } buf += bsprintf(buf, " %s", type); - buf += bsprintf(buf, " (%d/%d", rte->pref, rte->u.ospf.metric1); + buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY)); if (rte->attrs->source == RTS_OSPF_EXT2) - buf += bsprintf(buf, "/%d", rte->u.ospf.metric2); + buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY)); buf += bsprintf(buf, ")"); - if ((rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) && rte->u.ospf.tag) + if (rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) { - buf += bsprintf(buf, " [%x]", rte->u.ospf.tag); + eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_TAG); + if (ea && (ea->u.data > 0)) + buf += bsprintf(buf, " [%x]", ea->u.data); } - if (rte->u.ospf.router_id) - buf += bsprintf(buf, " [%R]", rte->u.ospf.router_id); + + eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_ROUTER_ID); + if (ea) + buf += bsprintf(buf, " [%R]", ea->u.data); } static int @@ -1550,3 +1534,9 @@ struct protocol proto_ospf = { .get_attr = ospf_get_attr, .get_route_info = ospf_get_route_info }; + +void +ospf_build(void) +{ + proto_build(&proto_ospf); +} diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index faee49dc..471bb586 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -144,7 +144,7 @@ orta_compare(const struct ospf_proto *p, const orta *new, const orta *old) { int r; - if (old->type == RTS_DUMMY) + if (!old->type) return 1; /* Prefer intra-area to inter-area to externals */ @@ -195,7 +195,7 @@ orta_compare_asbr(const struct ospf_proto *p, const orta *new, const orta *old) { int r; - if (old->type == RTS_DUMMY) + if (!old->type) return 1; if (!p->rfc1583) @@ -225,7 +225,7 @@ orta_compare_ext(const struct ospf_proto *p, const orta *new, const orta *old) { int r; - if (old->type == RTS_DUMMY) + if (!old->type) return 1; /* 16.4 (6a) - prefer routes with lower type */ @@ -2053,32 +2053,54 @@ again1: if (nf->n.type) /* Add the route */ { rta a0 = { - .src = p->p.main_source, .source = nf->n.type, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, .nh = *(nf->n.nhs), + .pref = p->p.main_channel->preference, }; if (reload || ort_changed(nf, &a0)) { - rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a); + a0.eattrs = alloca(sizeof(ea_list) + 4 * sizeof(eattr)); + memset(a0.eattrs, 0, sizeof(ea_list)); - rta_free(nf->old_rta); - nf->old_rta = rta_clone(a); - e->u.ospf.metric1 = nf->old_metric1 = nf->n.metric1; - e->u.ospf.metric2 = nf->old_metric2 = nf->n.metric2; - e->u.ospf.tag = nf->old_tag = nf->n.tag; - e->u.ospf.router_id = nf->old_rid = nf->n.rid; - e->pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID); + nf->old_metric1 = nf->n.metric1; + nf->old_metric2 = nf->n.metric2; + nf->old_tag = nf->n.tag; + nf->old_rid = nf->n.rid; + + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_METRIC1, + .type = EAF_TYPE_INT, + .u.data = nf->n.metric1, + }; if (nf->n.type == RTS_OSPF_EXT2) - e->pflags |= EA_ID_FLAG(EA_OSPF_METRIC2); + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_METRIC2, + .type = EAF_TYPE_INT, + .u.data = nf->n.metric2, + }; - /* Perhaps onfly if tag is non-zero? */ if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2)) - e->pflags |= EA_ID_FLAG(EA_OSPF_TAG); + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_TAG, + .type = EAF_TYPE_INT, + .u.data = nf->n.tag, + }; + + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_ROUTER_ID, + .type = EAF_TYPE_ROUTER_ID, + .u.data = nf->n.rid, + }; + + rta *a = rta_lookup(&a0); + rte *e = rte_get_temp(a, p->p.main_source); + + rta_free(nf->old_rta); + nf->old_rta = rta_clone(a); DBG("Mod rte type %d - %N via %I on iface %s, met %d\n", a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 52c2a0ce..9fe68264 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -2135,7 +2135,7 @@ ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e) if (*ee == e) { *ee = e->next; - sl_free(f->hash_slab, e); + sl_free(e); if (f->hash_entries-- < f->hash_entries_min) ospf_top_rehash(f, -HASH_LO_STEP); return; diff --git a/proto/perf/Makefile b/proto/perf/Makefile index 7877fb19..42051f43 100644 --- a/proto/perf/Makefile +++ b/proto/perf/Makefile @@ -2,5 +2,6 @@ src := perf.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,perf_build) tests_objs := $(tests_objs) $(src-o-files) diff --git a/proto/perf/perf.c b/proto/perf/perf.c index ba401a8a..5d228045 100644 --- a/proto/perf/perf.c +++ b/proto/perf/perf.c @@ -143,10 +143,10 @@ perf_loop(void *data) if (!p->attrs_per_rte || !(i % p->attrs_per_rte)) { struct rta a0 = { - .src = p->p.main_source, .source = RTS_PERF, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, + .pref = p->p.main_channel->preference, .nh.iface = p->ifa->iface, .nh.gw = gw, .nh.weight = 1, @@ -161,7 +161,7 @@ perf_loop(void *data) clock_gettime(CLOCK_MONOTONIC, &ts_generated); for (uint i=0; i<N; i++) { - rte *e = rte_get_temp(p->data[i].a); + rte *e = rte_get_temp(p->data[i].a, p->p.main_source); e->pflags = 0; rte_update(P, &(p->data[i].net), e); @@ -315,3 +315,9 @@ struct protocol proto_perf = { .reconfigure = perf_reconfigure, .copy_config = perf_copy_config, }; + +void +perf_build(void) +{ + proto_build(&proto_perf); +} diff --git a/proto/pipe/Makefile b/proto/pipe/Makefile index 5093da98..ba66027f 100644 --- a/proto/pipe/Makefile +++ b/proto/pipe/Makefile @@ -2,5 +2,6 @@ src := pipe.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,pipe_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/pipe/pipe.c b/proto/pipe/pipe.c index 481f5804..1f1ad857 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -43,6 +43,10 @@ #include "pipe.h" +#ifdef CONFIG_BGP +#include "proto/bgp/bgp.h" +#endif + static void pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old) { @@ -65,34 +69,26 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o if (new) { + src = new->src; + a = alloca(rta_size(new->attrs)); memcpy(a, new->attrs, rta_size(new->attrs)); - a->aflags = 0; + a->cached = 0; a->hostentry = NULL; - e = rte_get_temp(a); - e->pflags = 0; - - /* Copy protocol specific embedded attributes. */ - memcpy(&(e->u), &(new->u), sizeof(e->u)); - e->pref = new->pref; + e = rte_get_temp(a, src); e->pflags = new->pflags; #ifdef CONFIG_BGP /* Hack to cleanup cached value */ - if (e->attrs->src->proto->proto == &proto_bgp) - { - e->u.bgp.stale = -1; - e->u.bgp.base_table = NULL; - } + if (e->src->proto->proto == &proto_bgp) + e->pflags &= ~(BGP_REF_STALE | BGP_REF_NOT_STALE); #endif - - src = a->src; } else { e = NULL; - src = old->attrs->src; + src = old->src; } src_ch->table->pipe_busy = 1; @@ -101,9 +97,9 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o } static int -pipe_preexport(struct channel *C, rte **ee, struct linpool *p UNUSED) +pipe_preexport(struct channel *C, rte *e) { - struct proto *pp = (*ee)->sender->proto; + struct proto *pp = e->sender->proto; if (pp == C->proto) return -1; /* Avoid local loops automatically */ @@ -307,3 +303,9 @@ struct protocol proto_pipe = { .get_status = pipe_get_status, .show_proto_info = pipe_show_proto_info }; + +void +pipe_build(void) +{ + proto_build(&proto_pipe); +} diff --git a/proto/radv/Makefile b/proto/radv/Makefile index 05317eff..4780bee3 100644 --- a/proto/radv/Makefile +++ b/proto/radv/Makefile @@ -2,5 +2,6 @@ src := packets.c radv.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,radv_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/radv/radv.c b/proto/radv/radv.c index fe3713ef..541c3986 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -391,12 +391,12 @@ radv_net_match_trigger(struct radv_config *cf, net *n) } int -radv_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) +radv_preexport(struct channel *C, rte *new) { // struct radv_proto *p = (struct radv_proto *) P; struct radv_config *cf = (struct radv_config *) (C->proto->cf); - if (radv_net_match_trigger(cf, (*new)->net)) + if (radv_net_match_trigger(cf, new->net)) return RIC_PROCESS; if (cf->propagate_routes) @@ -771,3 +771,9 @@ struct protocol proto_radv = { .get_status = radv_get_status, .get_attr = radv_get_attr }; + +void +radv_build(void) +{ + proto_build(&proto_radv); +} diff --git a/proto/rip/Makefile b/proto/rip/Makefile index 7feabcd8..b9ff62d6 100644 --- a/proto/rip/Makefile +++ b/proto/rip/Makefile @@ -2,5 +2,6 @@ src := packets.c rip.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,rip_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/rip/rip.c b/proto/rip/rip.c index e1a235a0..6ca7a6b5 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -108,14 +108,14 @@ rip_add_rte(struct rip_proto *p, struct rip_rte **rp, struct rip_rte *src) } static inline void -rip_remove_rte(struct rip_proto *p, struct rip_rte **rp) +rip_remove_rte(struct rip_proto *p UNUSED, struct rip_rte **rp) { struct rip_rte *rt = *rp; rip_unlock_neighbor(rt->from); *rp = rt->next; - sl_free(p->rte_slab, rt); + sl_free(rt); } static inline int rip_same_rte(struct rip_rte *a, struct rip_rte *b) @@ -124,6 +124,11 @@ static inline int rip_same_rte(struct rip_rte *a, struct rip_rte *b) static inline int rip_valid_rte(struct rip_rte *rt) { return rt->from->ifa != NULL; } +struct rip_iface_adata { + struct adata ad; + struct iface *iface; +}; + /** * rip_announce_rte - announce route from RIP routing table to the core * @p: RIP instance @@ -145,7 +150,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) { /* Update */ rta a0 = { - .src = p->p.main_source, + .pref = p->p.main_channel->preference, .source = RTS_RIP, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, @@ -188,13 +193,39 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) a0.nh.iface = rt->from->ifa->iface; } - rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a); + struct { + ea_list l; + eattr e[3]; + struct rip_iface_adata riad; + } ea_block = { + .l = { .count = 3, }, + .e = { + { + .id = EA_RIP_METRIC, + .type = EAF_TYPE_INT, + .u.data = rt_metric, + }, + { + .id = EA_RIP_TAG, + .type = EAF_TYPE_INT, + .u.data = rt_tag, + }, + { + .id = EA_RIP_FROM, + .type = EAF_TYPE_IFACE, + .u.ptr = &ea_block.riad.ad, + } + }, + .riad = { + .ad = { .length = sizeof(struct rip_iface_adata) - sizeof(struct adata) }, + .iface = a0.nh.iface, + }, + }; + + a0.eattrs = &ea_block.l; - e->u.rip.from = a0.nh.iface; - e->u.rip.metric = rt_metric; - e->u.rip.tag = rt_tag; - e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG); + rta *a = rta_lookup(&a0); + rte *e = rte_get_temp(a, p->p.main_source); rte_update(&p->p, en->n.addr, e); } @@ -307,8 +338,10 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s if (new) { /* Update */ - u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1); u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0); + u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1); + const eattr *rie = ea_find(new->attrs->eattrs, EA_RIP_FROM); + struct iface *rt_from = rie ? ((struct rip_iface_adata *) rie->u.ptr)->iface : NULL; if (rt_metric > p->infinity) { @@ -339,7 +372,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s en->valid = RIP_ENTRY_VALID; en->metric = rt_metric; en->tag = rt_tag; - en->from = (new->attrs->src->proto == P) ? new->u.rip.from : NULL; + en->from = (new->src->proto == P) ? rt_from : NULL; en->iface = new->attrs->nh.iface; en->next_hop = new->attrs->nh.gw; } @@ -1068,37 +1101,24 @@ rip_reload_routes(struct channel *C) rip_kick_timer(p); } -static void -rip_make_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 2); - rte_make_tmp_attr(rt, EA_RIP_METRIC, EAF_TYPE_INT, rt->u.rip.metric); - rte_make_tmp_attr(rt, EA_RIP_TAG, EAF_TYPE_INT, rt->u.rip.tag); -} - -static void -rip_store_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 2); - rt->u.rip.metric = rte_store_tmp_attr(rt, EA_RIP_METRIC); - rt->u.rip.tag = rte_store_tmp_attr(rt, EA_RIP_TAG); -} - static int rip_rte_better(struct rte *new, struct rte *old) { - return new->u.rip.metric < old->u.rip.metric; + ASSERT_DIE(new->src == old->src); + struct rip_proto *p = (struct rip_proto *) new->src->proto; + + u32 new_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, p->infinity); + u32 old_metric = ea_get_int(old->attrs->eattrs, EA_RIP_METRIC, p->infinity); + + return new_metric < old_metric; } -static int -rip_rte_same(struct rte *new, struct rte *old) +static u32 +rip_rte_igp_metric(struct rte *rt) { - return ((new->u.rip.metric == old->u.rip.metric) && - (new->u.rip.tag == old->u.rip.tag) && - (new->u.rip.from == old->u.rip.from)); + return ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, IGP_METRIC_UNKNOWN); } - static void rip_postconfig(struct proto_config *CF) { @@ -1120,10 +1140,8 @@ rip_init(struct proto_config *CF) P->rt_notify = rip_rt_notify; P->neigh_notify = rip_neigh_notify; P->reload_routes = rip_reload_routes; - P->make_tmp_attrs = rip_make_tmp_attrs; - P->store_tmp_attrs = rip_store_tmp_attrs; P->rte_better = rip_rte_better; - P->rte_same = rip_rte_same; + P->rte_igp_metric = rip_rte_igp_metric; return P; } @@ -1198,10 +1216,14 @@ rip_reconfigure(struct proto *P, struct proto_config *CF) static void rip_get_route_info(rte *rte, byte *buf) { - buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric); + struct rip_proto *p = (struct rip_proto *) rte->src->proto; + u32 rt_metric = ea_get_int(rte->attrs->eattrs, EA_RIP_METRIC, p->infinity); + u32 rt_tag = ea_get_int(rte->attrs->eattrs, EA_RIP_TAG, 0); + + buf += bsprintf(buf, " (%d/%d)", rte->attrs->pref, rt_metric); - if (rte->u.rip.tag) - bsprintf(buf, " [%04x]", rte->u.rip.tag); + if (rt_tag) + bsprintf(buf, " [%04x]", rt_tag); } static int @@ -1338,3 +1360,9 @@ struct protocol proto_rip = { .get_route_info = rip_get_route_info, .get_attr = rip_get_attr }; + +void +rip_build(void) +{ + proto_build(&proto_rip); +} diff --git a/proto/rip/rip.h b/proto/rip/rip.h index 8d347000..f8713c4a 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -197,6 +197,7 @@ struct rip_rte #define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0) #define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1) +#define EA_RIP_FROM EA_CODE(PROTOCOL_RIP, 2) static inline int rip_is_v2(struct rip_proto *p) { return p->rip2; } diff --git a/proto/rpki/Makefile b/proto/rpki/Makefile index eb09b7df..8e3a2761 100644 --- a/proto/rpki/Makefile +++ b/proto/rpki/Makefile @@ -2,5 +2,6 @@ src := rpki.c packets.c tcp_transport.c ssh_transport.c transport.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,rpki_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/rpki/rpki.c b/proto/rpki/rpki.c index 4ccb38e3..4fca9e54 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -121,18 +121,18 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ struct rpki_proto *p = cache->p; rta a0 = { - .src = p->p.main_source, + .pref = channel->preference, .source = RTS_RPKI, .scope = SCOPE_UNIVERSE, .dest = RTD_NONE, }; rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a); + rte *e = rte_get_temp(a, p->p.main_source); e->pflags = 0; - rte_update2(channel, &pfxr->n, e, a0.src); + rte_update2(channel, &pfxr->n, e, e->src); } void @@ -960,3 +960,9 @@ struct protocol proto_rpki = { .reconfigure = rpki_reconfigure, .get_status = rpki_get_status, }; + +void +rpki_build(void) +{ + proto_build(&proto_rpki); +} diff --git a/proto/static/Makefile b/proto/static/Makefile index e38f9b74..26aed31f 100644 --- a/proto/static/Makefile +++ b/proto/static/Makefile @@ -2,5 +2,6 @@ src := static.c obj := $(src-o-files) $(all-daemon) $(cf-local) +$(call proto-build,static_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/static/static.c b/proto/static/static.c index 2789c1bb..cd31afd3 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -56,10 +56,11 @@ static void static_announce_rte(struct static_proto *p, struct static_route *r) { rta *a = allocz(RTA_MAX_SIZE); - a->src = static_get_source(p, r->index); + struct rte_src *src = static_get_source(p, r->index); a->source = RTS_STATIC; a->scope = SCOPE_UNIVERSE; a->dest = r->dest; + a->pref = p->p.main_channel->preference; if (r->dest == RTD_UNICAST) { @@ -102,7 +103,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) return; /* We skip rta_lookup() here */ - rte *e = rte_get_temp(a); + rte *e = rte_get_temp(a, src); e->pflags = 0; if (r->cmds) @@ -119,7 +120,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) e->net = NULL; } - rte_update2(p->p.main_channel, r->net, e, a->src); + rte_update2(p->p.main_channel, r->net, e, src); r->state = SRS_CLEAN; if (r->cmds) @@ -131,7 +132,7 @@ withdraw: if (r->state == SRS_DOWN) return; - rte_update2(p->p.main_channel, r->net, NULL, a->src); + rte_update2(p->p.main_channel, r->net, NULL, src); r->state = SRS_DOWN; } @@ -485,7 +486,7 @@ static_start(struct proto *P) struct static_route *r; if (!static_lp) - static_lp = lp_new(&root_pool, LP_GOOD_SIZE(1024)); + static_lp = lp_new(&root_pool); if (p->igp_table_ip4) rt_lock_table(p->igp_table_ip4); @@ -721,9 +722,9 @@ static_get_route_info(rte *rte, byte *buf) { eattr *a = ea_find(rte->attrs->eattrs, EA_GEN_IGP_METRIC); if (a) - buf += bsprintf(buf, " (%d/%u)", rte->pref, a->u.data); + buf += bsprintf(buf, " (%d/%u)", rte->attrs->pref, a->u.data); else - buf += bsprintf(buf, " (%d)", rte->pref); + buf += bsprintf(buf, " (%d)", rte->attrs->pref); } static void @@ -792,3 +793,9 @@ struct protocol proto_static = { .copy_config = static_copy_config, .get_route_info = static_get_route_info, }; + +void +static_build(void) +{ + proto_build(&proto_static); +} |