diff options
-rw-r--r-- | usr.sbin/bgpd/rde.c | 123 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 10 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 48 |
3 files changed, 88 insertions, 93 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 1ca29f3b4ff..fa423adabf6 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.245 2009/05/17 14:45:25 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.246 2009/05/27 06:58:15 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -44,6 +44,10 @@ void rde_sighdlr(int); void rde_dispatch_imsg_session(struct imsgbuf *); void rde_dispatch_imsg_parent(struct imsgbuf *); int rde_update_dispatch(struct imsg *); +void rde_update_update(struct rde_peer *, struct rde_aspath *, + struct bgpd_addr *, u_int8_t); +void rde_update_withdraw(struct rde_peer *, struct bgpd_addr *, + u_int8_t); int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *, struct rde_aspath *, struct mpattr *); u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t); @@ -727,7 +731,7 @@ int rde_update_dispatch(struct imsg *imsg) { struct rde_peer *peer; - struct rde_aspath *asp = NULL, *fasp; + struct rde_aspath *asp = NULL; u_char *p, *mpp = NULL; int error = -1, pos = 0; u_int16_t afi, len, mplen; @@ -848,10 +852,7 @@ rde_update_dispatch(struct imsg *imsg) goto done; } - peer->prefix_rcvd_withdraw++; - rde_update_log("withdraw", peer, NULL, &prefix, prefixlen); - prefix_remove(&ribs[1], peer, &prefix, prefixlen, 0); - prefix_remove(&ribs[0], peer, &prefix, prefixlen, 0); + rde_update_withdraw(peer, &prefix, prefixlen); } if (attrpath_len == 0) { @@ -906,13 +907,7 @@ rde_update_dispatch(struct imsg *imsg) mpp += pos; mplen -= pos; - peer->prefix_rcvd_withdraw++; - rde_update_log("withdraw", peer, NULL, - &prefix, prefixlen); - prefix_remove(&ribs[1], peer, &prefix, - prefixlen, 0); - prefix_remove(&ribs[0], peer, &prefix, - prefixlen, 0); + rde_update_withdraw(peer, &prefix, prefixlen); } break; default: @@ -960,17 +955,7 @@ rde_update_dispatch(struct imsg *imsg) goto done; } - peer->prefix_rcvd_update++; - /* add original path to the Adj-RIB-In */ - if (peer->conf.softreconfig_in) - path_update(&ribs[0], peer, asp, &prefix, prefixlen); - - /* input filter */ - if (rde_filter(&fasp, rules_l, peer, asp, &prefix, prefixlen, - peer, DIR_IN) == ACTION_DENY) { - path_put(fasp); - continue; - } + rde_update_update(peer, asp, &prefix, prefixlen); /* max prefix checker */ if (peer->conf.max_prefix && @@ -978,20 +963,9 @@ rde_update_dispatch(struct imsg *imsg) log_peer_warnx(&peer->conf, "prefix limit reached"); rde_update_err(peer, ERR_CEASE, ERR_CEASE_MAX_PREFIX, NULL, 0); - path_put(fasp); goto done; } - if (fasp == NULL) - fasp = asp; - - rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, - &prefix, prefixlen); - path_update(&ribs[1], peer, fasp, &prefix, prefixlen); - - /* free modified aspath */ - if (fasp != asp) - path_put(fasp); } /* add MP_REACH_NLRI if available */ @@ -1053,19 +1027,8 @@ rde_update_dispatch(struct imsg *imsg) mpp += pos; mplen -= pos; - peer->prefix_rcvd_update++; - /* add original path to the Adj-RIB-In */ - if (peer->conf.softreconfig_in) - path_update(&ribs[0], peer, asp, - &prefix, prefixlen); - - /* input filter */ - if (rde_filter(&fasp, rules_l, peer, asp, - &prefix, prefixlen, peer, DIR_IN) == - ACTION_DENY) { - path_put(fasp); - continue; - } + rde_update_update(peer, asp, &prefix, + prefixlen); /* max prefix checker */ if (peer->conf.max_prefix && @@ -1074,22 +1037,9 @@ rde_update_dispatch(struct imsg *imsg) "prefix limit reached"); rde_update_err(peer, ERR_CEASE, ERR_CEASE_MAX_PREFIX, NULL, 0); - path_put(fasp); goto done; } - if (fasp == NULL) - fasp = asp; - - rde_update_log("update", peer, - &asp->nexthop->exit_nexthop, - &prefix, prefixlen); - path_update(&ribs[1], peer, fasp, &prefix, - prefixlen); - - /* free modified aspath */ - if (fasp != asp) - path_put(fasp); } break; default: @@ -1112,6 +1062,55 @@ done: return (error); } +void +rde_update_update(struct rde_peer *peer, struct rde_aspath *asp, + struct bgpd_addr *prefix, u_int8_t prefixlen) +{ + struct rde_aspath *fasp; + int r = 0; + + peer->prefix_rcvd_update++; + /* add original path to the Adj-RIB-In */ + if (peer->conf.softreconfig_in) + r += path_update(&ribs[0], peer, asp, prefix, prefixlen); + + /* input filter */ + if (rde_filter(&fasp, rules_l, peer, asp, prefix, prefixlen, + peer, DIR_IN) == ACTION_DENY) + goto done; + + if (fasp == NULL) + fasp = asp; + + rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, + prefix, prefixlen); + r += path_update(&ribs[1], peer, fasp, prefix, prefixlen); + +done: + /* free modified aspath */ + if (fasp != asp) + path_put(fasp); + + if (r) + peer->prefix_cnt++; +} + +void +rde_update_withdraw(struct rde_peer *peer, struct bgpd_addr *prefix, + u_int8_t prefixlen) +{ + int r = 0; + + peer->prefix_rcvd_withdraw++; + rde_update_log("withdraw", peer, NULL, prefix, prefixlen); + + r += prefix_remove(&ribs[1], peer, prefix, prefixlen, 0); + r += prefix_remove(&ribs[0], peer, prefix, prefixlen, 0); + + if (r) + peer->prefix_cnt--; +} + /* * BGP UPDATE parser functions */ @@ -1709,7 +1708,6 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) rib.med = asp->med; rib.prefix_cnt = asp->prefix_cnt; rib.active_cnt = asp->active_cnt; - rib.rib_cnt = asp->rib_cnt; strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr)); memcpy(&rib.remote_addr, &asp->peer->remote_addr, sizeof(rib.remote_addr)); @@ -2609,6 +2607,7 @@ peer_down(u_int32_t id) path_remove(asp); } LIST_INIT(&peer->path_h); + peer->prefix_cnt = 0; /* Deletions are performed in path_remove() */ rde_send_pftable_commit(); diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 7f2905db780..c84f7ecf880 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.109 2009/05/21 15:47:03 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.110 2009/05/27 06:58:15 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -67,7 +67,6 @@ struct rde_peer { u_int64_t prefix_sent_update; u_int64_t prefix_sent_withdraw; u_int32_t prefix_cnt; /* # of prefixes */ - u_int32_t rib_cnt; /* # of p. in Adj-RIB-In */ u_int32_t remote_bgpid; /* host byte order! */ u_int32_t up_pcnt; u_int32_t up_acnt; @@ -184,7 +183,6 @@ struct rde_aspath { u_int32_t weight; /* low prio lpref */ u_int32_t prefix_cnt; /* # of prefixes */ u_int32_t active_cnt; /* # of active prefixes */ - u_int32_t rib_cnt; /* # of p. in Adj-RIB-In */ u_int32_t flags; /* internally used */ u_int16_t rtlabelid; /* route label id */ u_int16_t pftableid; /* pf table id */ @@ -355,7 +353,7 @@ void rib_dump_r(struct rib_context *); void path_init(u_int32_t); void path_shutdown(void); -void path_update(struct rib *, struct rde_peer *, +int path_update(struct rib *, struct rde_peer *, struct rde_aspath *, struct bgpd_addr *, int); int path_compare(struct rde_aspath *, struct rde_aspath *); struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *); @@ -371,10 +369,10 @@ int prefix_compare(const struct bgpd_addr *, const struct bgpd_addr *, int); struct prefix *prefix_get(struct rib *, struct rde_peer *, struct bgpd_addr *, int, u_int32_t); -void prefix_add(struct rib *, struct rde_aspath *, +int prefix_add(struct rib *, struct rde_aspath *, struct bgpd_addr *, int); void prefix_move(struct rde_aspath *, struct prefix *); -void prefix_remove(struct rib *, struct rde_peer *, +int prefix_remove(struct rib *, struct rde_peer *, struct bgpd_addr *, int, u_int32_t); int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *, diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 5ee64aedbfb..a4bd6b4a3f7 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.102 2009/05/21 15:47:03 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.103 2009/05/27 06:58:15 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -292,12 +292,9 @@ done: } /* used to bump correct prefix counters */ -#define PREFIX_COUNT(x, id, op) \ - do { \ - if (id == 1) \ - (x)->prefix_cnt += (op); \ - else \ - (x)->rib_cnt += (op); \ +#define PREFIX_COUNT(x, op) \ + do { \ + (x)->prefix_cnt += (op); \ } while (0) /* path specific functions */ @@ -340,7 +337,7 @@ path_shutdown(void) free(pathtable.path_hashtbl); } -void +int path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp, struct bgpd_addr *prefix, int prefixlen) { @@ -359,7 +356,7 @@ path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp, if (path_compare(nasp, p->aspath) == 0) { /* no change, update last change */ p->lastchange = time(NULL); - return; + return (0); } } @@ -378,7 +375,8 @@ path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp, if (p != NULL) prefix_move(asp, p); else - prefix_add(rib, asp, prefix, prefixlen); + return (prefix_add(rib, asp, prefix, prefixlen)); + return (0); } int @@ -466,8 +464,7 @@ void path_destroy(struct rde_aspath *asp) { /* path_destroy can only unlink and free empty rde_aspath */ - if (asp->prefix_cnt != 0 || asp->active_cnt != 0 || - asp->rib_cnt != 0) + if (asp->prefix_cnt != 0 || asp->active_cnt != 0) log_warnx("path_destroy: prefix count out of sync"); nexthop_unlink(asp); @@ -644,7 +641,7 @@ prefix_get(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, /* * Adds or updates a prefix. */ -void +int prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen) @@ -660,13 +657,14 @@ prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix, if (p == NULL) { p = prefix_alloc(); prefix_link(p, re, asp); + return (1); } else { if (p->aspath != asp) { /* prefix belongs to a different aspath so move */ prefix_move(asp, p); - return; - } - p->lastchange = time(NULL); + } else + p->lastchange = time(NULL); + return (0); } } @@ -692,7 +690,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) /* add to new as path */ LIST_INSERT_HEAD(&asp->prefix_h, np, path_l); - PREFIX_COUNT(asp, p->rib->rib->id, 1); + PREFIX_COUNT(asp, 1); /* * no need to update the peer prefix count because we are only moving * the prefix without changing the peer. @@ -712,7 +710,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) /* remove old prefix node */ oasp = p->aspath; LIST_REMOVE(p, path_l); - PREFIX_COUNT(oasp, p->rib->rib->id, -1); + PREFIX_COUNT(oasp, -1); /* as before peer count needs no update because of move */ /* destroy all references to other objects and free the old prefix */ @@ -730,7 +728,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) * Removes a prefix from all lists. If the parent objects -- path or * pt_entry -- become empty remove them too. */ -void +int prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen, u_int32_t flags) { @@ -740,11 +738,11 @@ prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, re = rib_get(rib, prefix, prefixlen); if (re == NULL) /* Got a dummy withdrawn request */ - return; + return (0); p = prefix_bypeer(re, peer, flags); if (p == NULL) /* Got a dummy withdrawn request. */ - return; + return (0); asp = p->aspath; @@ -761,6 +759,8 @@ prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, rib_remove(re); if (path_empty(asp)) path_destroy(asp); + + return (1); } /* dump a prefix into specified buffer */ @@ -895,8 +895,7 @@ static void prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp) { LIST_INSERT_HEAD(&asp->prefix_h, pref, path_l); - PREFIX_COUNT(asp, re->rib->id, 1); - PREFIX_COUNT(asp->peer, re->rib->id, 1); + PREFIX_COUNT(asp, 1); pref->aspath = asp; pref->rib = re; @@ -921,8 +920,7 @@ prefix_unlink(struct prefix *pref) } LIST_REMOVE(pref, path_l); - PREFIX_COUNT(pref->aspath, pref->rib->rib->id, -1); - PREFIX_COUNT(pref->aspath->peer, pref->rib->rib->id, -1); + PREFIX_COUNT(pref->aspath, -1); pt_unref(pref->prefix); if (pt_empty(pref->prefix)) |