diff options
-rw-r--r-- | usr.sbin/bgpd/rde.c | 152 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 13 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 76 |
3 files changed, 125 insertions, 116 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index c4e37f49052..5725d86881e 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.486 2019/08/14 07:39:04 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.487 2019/08/14 11:57:21 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -777,10 +777,10 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) copy_config(nconf, imsg.data); for (rid = 0; rid < rib_size; rid++) { - if (!rib_valid(rid)) + if ((rib = rib_byid(rid)) == NULL) continue; - ribs[rid].state = RECONF_DELETE; - ribs[rid].fibstate = RECONF_NONE; + rib->state = RECONF_DELETE; + rib->fibstate = RECONF_NONE; } break; case IMSG_RECONF_RIB: @@ -1412,7 +1412,7 @@ rde_update_update(struct rde_peer *peer, struct filterstate *in, aspath_origin(in->aspath.aspath)); /* add original path to the Adj-RIB-In */ - if (prefix_update(&ribs[RIB_ADJ_IN], peer, in, prefix, prefixlen, + if (prefix_update(rib_byid(RIB_ADJ_IN), peer, in, prefix, prefixlen, vstate) == 1) peer->prefix_cnt++; @@ -1428,21 +1428,22 @@ rde_update_update(struct rde_peer *peer, struct filterstate *in, wmsg = "path invalid, withdraw"; for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; rde_filterstate_prep(&state, &in->aspath, &in->communities, in->nexthop, in->nhflags); /* input filter */ - action = rde_filter(ribs[i].in_rules, peer, peer, prefix, + action = rde_filter(rib->in_rules, peer, peer, prefix, prefixlen, vstate, &state); if (action == ACTION_ALLOW) { rde_update_log("update", i, peer, &state.nexthop->exit_nexthop, prefix, prefixlen); - prefix_update(&ribs[i], peer, &state, prefix, + prefix_update(rib, peer, &state, prefix, prefixlen, vstate); - } else if (prefix_withdraw(&ribs[i], peer, prefix, + } else if (prefix_withdraw(rib, peer, prefix, prefixlen)) { rde_update_log(wmsg, i, peer, NULL, prefix, prefixlen); @@ -1461,15 +1462,16 @@ rde_update_withdraw(struct rde_peer *peer, struct bgpd_addr *prefix, u_int16_t i; for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - if (prefix_withdraw(&ribs[i], peer, prefix, prefixlen)) + if (prefix_withdraw(rib, peer, prefix, prefixlen)) rde_update_log("withdraw", i, peer, NULL, prefix, prefixlen); } /* remove original path form the Adj-RIB-In */ - if (prefix_withdraw(&ribs[RIB_ADJ_IN], peer, prefix, prefixlen)) + if (prefix_withdraw(rib_byid(RIB_ADJ_IN), peer, prefix, prefixlen)) peer->prefix_cnt--; peer->prefix_rcvd_withdraw++; @@ -2040,7 +2042,7 @@ rde_update_log(const char *message, u_int16_t rid, if (asprintf(&p, "%s/%u", log_addr(prefix), prefixlen) == -1) p = NULL; l = log_fmt_peer(&peer->conf); - log_info("Rib %s: %s AS%s: %s %s%s", ribs[rid].name, + log_info("Rib %s: %s AS%s: %s %s%s", rib_byid(rid)->name, l, log_as(peer->conf.remote_as), message, p ? p : "out of memory", n ? n : ""); @@ -3115,43 +3117,44 @@ rde_reload_done(void) } /* bring ribs in sync */ for (rid = 0; rid < rib_size; rid++) { - if (!rib_valid(rid)) + struct rib *rib = rib_byid(rid); + if (rib == NULL) continue; - rde_filter_calc_skip_steps(ribs[rid].in_rules_tmp); + rde_filter_calc_skip_steps(rib->in_rules_tmp); /* flip rules, make new active */ - fh = ribs[rid].in_rules; - ribs[rid].in_rules = ribs[rid].in_rules_tmp; - ribs[rid].in_rules_tmp = fh; + fh = rib->in_rules; + rib->in_rules = rib->in_rules_tmp; + rib->in_rules_tmp = fh; - switch (ribs[rid].state) { + switch (rib->state) { case RECONF_DELETE: - rib_free(&ribs[rid]); + rib_free(rib); break; case RECONF_RELOAD: - rib_update(&ribs[rid]); - ribs[rid].state = RECONF_KEEP; + rib_update(rib); + rib->state = RECONF_KEEP; /* FALLTHROUGH */ case RECONF_KEEP: - if (rde_filter_equal(ribs[rid].in_rules, - ribs[rid].in_rules_tmp, NULL)) + if (rde_filter_equal(rib->in_rules, + rib->in_rules_tmp, NULL)) /* rib is in sync */ break; log_debug("in filter change: reloading RIB %s", - ribs[rid].name); - ribs[rid].state = RECONF_RELOAD; + rib->name); + rib->state = RECONF_RELOAD; reload++; break; case RECONF_REINIT: /* new rib */ - ribs[rid].state = RECONF_RELOAD; + rib->state = RECONF_RELOAD; reload++; break; case RECONF_NONE: break; } - filterlist_free(ribs[rid].in_rules_tmp); - ribs[rid].in_rules_tmp = NULL; + filterlist_free(rib->in_rules_tmp); + rib->in_rules_tmp = NULL; } filterlist_free(out_rules_tmp); @@ -3165,8 +3168,8 @@ rde_reload_done(void) if (reload > 0) { softreconfig++; - if (rib_dump_new(RIB_ADJ_IN, AID_UNSPEC, - RDE_RUNNER_ROUNDS, &ribs[RIB_ADJ_IN], rde_softreconfig_in, + if (rib_dump_new(RIB_ADJ_IN, AID_UNSPEC, RDE_RUNNER_ROUNDS, + rib_byid(RIB_ADJ_IN), rde_softreconfig_in, rde_softreconfig_in_done, NULL) == -1) fatal("%s: rib_dump_new", __func__); log_info("running softreconfig in"); @@ -3176,10 +3179,10 @@ rde_reload_done(void) } static void -rde_softreconfig_in_done(void *arg, u_int8_t aid) +rde_softreconfig_in_done(void *arg, u_int8_t dummy) { struct rde_peer *peer; - u_int16_t rid; + u_int16_t i; if (arg != NULL) { softreconfig--; @@ -3192,54 +3195,56 @@ rde_softreconfig_in_done(void *arg, u_int8_t aid) /* now do the Adj-RIB-Out sync and a possible FIB sync */ softreconfig = 0; - for (rid = 0; rid < rib_size; rid++) { - if (!rib_valid(rid)) + for (i = 0; i < rib_size; i++) { + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - ribs[rid].state = RECONF_NONE; - if (ribs[rid].fibstate == RECONF_RELOAD) { - if (rib_dump_new(rid, AID_UNSPEC, RDE_RUNNER_ROUNDS, - &ribs[rid], rde_softreconfig_sync_fib, + rib->state = RECONF_NONE; + if (rib->fibstate == RECONF_RELOAD) { + if (rib_dump_new(i, AID_UNSPEC, RDE_RUNNER_ROUNDS, + rib, rde_softreconfig_sync_fib, rde_softreconfig_sync_done, NULL) == -1) fatal("%s: rib_dump_new", __func__); softreconfig++; log_info("starting fib sync for rib %s", - ribs[rid].name); - } else if (ribs[rid].fibstate == RECONF_REINIT) { - if (rib_dump_new(rid, AID_UNSPEC, RDE_RUNNER_ROUNDS, - &ribs[rid], rde_softreconfig_sync_reeval, + rib->name); + } else if (rib->fibstate == RECONF_REINIT) { + if (rib_dump_new(i, AID_UNSPEC, RDE_RUNNER_ROUNDS, + rib, rde_softreconfig_sync_reeval, rde_softreconfig_sync_done, NULL) == -1) fatal("%s: rib_dump_new", __func__); softreconfig++; log_info("starting re-evaluation of rib %s", - ribs[rid].name); + rib->name); } } LIST_FOREACH(peer, &peerlist, peer_l) { if (peer->reconf_out) - ribs[peer->loc_rib_id].state = RECONF_RELOAD; + rib_byid(peer->loc_rib_id)->state = RECONF_RELOAD; else if (peer->reconf_rib) { - u_int8_t i; + u_int8_t aid; /* dump the full table to neighbors that changed rib */ - for (i = 0; i < AID_MAX; i++) { - if (peer->capa.mp[i]) - peer_dump(peer->conf.id, i); + for (aid = 0; aid < AID_MAX; aid++) { + if (peer->capa.mp[aid]) + peer_dump(peer->conf.id, aid); } } } - for (rid = 0; rid < rib_size; rid++) { - if (!rib_valid(rid)) + for (i = 0; i < rib_size; i++) { + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - if (ribs[rid].state == RECONF_RELOAD) { - if (rib_dump_new(rid, AID_UNSPEC, RDE_RUNNER_ROUNDS, - &ribs[rid], rde_softreconfig_out, + if (rib->state == RECONF_RELOAD) { + if (rib_dump_new(i, AID_UNSPEC, RDE_RUNNER_ROUNDS, + rib, rde_softreconfig_out, rde_softreconfig_out_done, NULL) == -1) fatal("%s: rib_dump_new", __func__); softreconfig++; log_info("starting softreconfig out for rib %s", - ribs[rid].name); + rib->name); } } @@ -3264,12 +3269,13 @@ rde_softreconfig_out_done(void *arg, u_int8_t aid) static void rde_softreconfig_done(void) { - u_int16_t rid; + u_int16_t i; - for (rid = 0; rid < rib_size; rid++) { - if (!rib_valid(rid)) + for (i = 0; i < rib_size; i++) { + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - ribs[rid].state = RECONF_NONE; + rib->state = RECONF_NONE; } log_info("RDE soft reconfiguration done"); @@ -3314,10 +3320,10 @@ rde_softreconfig_in(struct rib_entry *re, void *bula) continue; for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + rib = rib_byid(i); + if (rib == NULL) continue; - rib = &ribs[i]; if (rib->state != RECONF_RELOAD && !force_eval) continue; @@ -3724,9 +3730,10 @@ peer_flush_upcall(struct rib_entry *re, void *arg) continue; for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - rp = prefix_get(&ribs[i], peer, &addr, prefixlen); + rp = prefix_get(rib, peer, &addr, prefixlen); if (rp) { asp = prefix_aspath(rp); if (asp->pftableid) @@ -3963,16 +3970,17 @@ network_add(struct network_config *nc, struct filterstate *state) vstate = rde_roa_validity(&conf->rde_roa, &nc->prefix, nc->prefixlen, aspath_origin(state->aspath.aspath)); - if (prefix_update(&ribs[RIB_ADJ_IN], peerself, state, &nc->prefix, + if (prefix_update(rib_byid(RIB_ADJ_IN), peerself, state, &nc->prefix, nc->prefixlen, vstate) == 1) peerself->prefix_cnt++; for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; rde_update_log("announce", i, peerself, state->nexthop ? &state->nexthop->exit_nexthop : NULL, &nc->prefix, nc->prefixlen); - prefix_update(&ribs[i], peerself, state, &nc->prefix, + prefix_update(rib, peerself, state, &nc->prefix, nc->prefixlen, vstate); } filterset_free(&nc->attrset); @@ -4031,14 +4039,15 @@ network_delete(struct network_config *nc) } for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - if (prefix_withdraw(&ribs[i], peerself, &nc->prefix, + if (prefix_withdraw(rib, peerself, &nc->prefix, nc->prefixlen)) rde_update_log("withdraw announce", i, peerself, NULL, &nc->prefix, nc->prefixlen); } - if (prefix_withdraw(&ribs[RIB_ADJ_IN], peerself, &nc->prefix, + if (prefix_withdraw(rib_byid(RIB_ADJ_IN), peerself, &nc->prefix, nc->prefixlen)) peerself->prefix_cnt--; } @@ -4097,9 +4106,10 @@ network_flush_upcall(struct rib_entry *re, void *ptr) continue; for (i = RIB_LOC_START; i < rib_size; i++) { - if (!rib_valid(i)) + struct rib *rib = rib_byid(i); + if (rib == NULL) continue; - rp = prefix_get(&ribs[i], peer, &addr, prefixlen); + rp = prefix_get(rib, peer, &addr, prefixlen); if (rp) { prefix_destroy(rp); rde_update_log("flush announce", i, peer, diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 32a1c083412..3faaa61a6dd 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.225 2019/08/14 07:39:04 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.226 2019/08/14 11:57:21 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -502,8 +502,7 @@ pt_unref(struct pt_entry *pt) } /* rde_rib.c */ -extern u_int16_t rib_size; -extern struct rib *ribs; +extern u_int16_t rib_size; struct rib *rib_new(char *, u_int, u_int16_t); void rib_update(struct rib *); @@ -527,14 +526,6 @@ re_rib(struct rib_entry *re) return rib_byid(re->rib_id); } -static inline int -rib_valid(u_int16_t rid) -{ - if (rid == RIB_NOTFOUND || rid >= rib_size || *ribs[rid].name == '\0') - return 0; - return 1; -} - void path_init(u_int32_t); void path_init(u_int32_t); void path_shutdown(void); diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 028993e1bda..5c10fdd5115 100644 --- a/usr.sbin/bgpd/rde_rib.c +++ b/usr.sbin/bgpd/rde_rib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.205 2019/08/14 07:39:04 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.206 2019/08/14 11:57:21 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -37,7 +37,7 @@ * This is achieved by heavily linking the different parts together. */ u_int16_t rib_size; -struct rib *ribs; +struct rib **ribs; struct rib_entry *rib_add(struct rib *, struct bgpd_addr *, int); static inline int rib_compare(const struct rib_entry *, @@ -136,39 +136,40 @@ rib_compare(const struct rib_entry *a, const struct rib_entry *b) struct rib * rib_new(char *name, u_int rtableid, u_int16_t flags) { - struct rib *xribs; + struct rib *new; u_int16_t id; for (id = 0; id < rib_size; id++) { - if (!rib_valid(id)) + if (ribs[id] == NULL) break; } if (id >= rib_size) { - if ((xribs = reallocarray(ribs, id + 1, - sizeof(struct rib))) == NULL) { - /* XXX this is not clever */ + if ((ribs = recallocarray(ribs, id, id + 8, + sizeof(struct rib))) == NULL) fatal(NULL); - } - ribs = xribs; - rib_size = id + 1; + rib_size = id + 8; } - memset(&ribs[id], 0, sizeof(struct rib)); - strlcpy(ribs[id].name, name, sizeof(ribs[id].name)); - RB_INIT(rib_tree(&ribs[id])); - ribs[id].state = RECONF_REINIT; - ribs[id].id = id; - ribs[id].flags = flags; - ribs[id].rtableid = rtableid; + if ((new = calloc(1, sizeof(*new))) == NULL) + fatal(NULL); + + strlcpy(new->name, name, sizeof(new->name)); + RB_INIT(rib_tree(new)); + new->state = RECONF_REINIT; + new->id = id; + new->flags = flags; + new->rtableid = rtableid; - ribs[id].in_rules = calloc(1, sizeof(struct filter_head)); - if (ribs[id].in_rules == NULL) + new->in_rules = calloc(1, sizeof(struct filter_head)); + if (new->in_rules == NULL) fatal(NULL); - TAILQ_INIT(ribs[id].in_rules); + TAILQ_INIT(new->in_rules); + + ribs[id] = new; log_debug("%s: %s -> %u", __func__, name, id); - return (&ribs[id]); + return (new); } /* @@ -200,11 +201,11 @@ rib_update(struct rib *rib) } struct rib * -rib_byid(u_int16_t rid) +rib_byid(u_int16_t id) { - if (rib_valid(rid)) - return &ribs[rid]; - return NULL; + if (id == RIB_NOTFOUND || id >= rib_size || ribs[id] == NULL) + return NULL; + return ribs[id]; } u_int16_t @@ -217,7 +218,7 @@ rib_find(char *name) return RIB_LOC_START; for (id = 0; id < rib_size; id++) { - if (!strcmp(ribs[id].name, name)) + if (ribs[id] != NULL && !strcmp(ribs[id]->name, name)) return id; } @@ -266,27 +267,34 @@ rib_free(struct rib *rib) return; /* never remove the default ribs */ filterlist_free(rib->in_rules_tmp); filterlist_free(rib->in_rules); - memset(rib, 0, sizeof(struct rib)); + ribs[rib->id] = NULL; + free(rib); } void rib_shutdown(void) { + struct rib *rib; u_int16_t id; for (id = 0; id < rib_size; id++) { - if (!rib_valid(id)) + rib = rib_byid(id); + if (rib == NULL) continue; - if (!RB_EMPTY(rib_tree(&ribs[id]))) { + if (!RB_EMPTY(rib_tree(ribs[id]))) { log_warnx("%s: rib %s is not empty", __func__, - ribs[id].name); + ribs[id]->name); } - rib_free(&ribs[id]); + rib_free(ribs[id]); } for (id = 0; id <= RIB_LOC_START; id++) { - filterlist_free(ribs[id].in_rules_tmp); - filterlist_free(ribs[id].in_rules); - memset(&ribs[id], 0, sizeof(struct rib)); + rib = rib_byid(id); + if (rib == NULL) + continue; + filterlist_free(rib->in_rules_tmp); + filterlist_free(rib->in_rules); + ribs[id] = NULL; + free(rib); } free(ribs); } |