diff options
author | 2006-01-24 13:34:33 +0000 | |
---|---|---|
committer | 2006-01-24 13:34:33 +0000 | |
commit | 1f78fdc6afed22c998ed379cd9e147d84ffead3a (patch) | |
tree | 68ba1560f491096e35d37baa158d1e768a054a05 | |
parent | It is possible that a prefix is part of two RIBs in that case prefix_remove() (diff) | |
download | wireguard-openbsd-1f78fdc6afed22c998ed379cd9e147d84ffead3a.tar.xz wireguard-openbsd-1f78fdc6afed22c998ed379cd9e147d84ffead3a.zip |
Finally start using the Adj-RIB-In. The most complex part is the modification
of path_update(). There are about 10 different ways how to update a path and
some of them are tricky. Looks good henning@
-rw-r--r-- | usr.sbin/bgpd/rde.c | 34 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 71 |
3 files changed, 78 insertions, 31 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index fc17dfe7b7a..6297f76686f 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.195 2006/01/20 16:40:17 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.196 2006/01/24 13:34:33 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -831,6 +831,9 @@ rde_update_dispatch(struct imsg *imsg) return (-1); } + /* add original path to the Adj-RIB-In */ + path_update(peer, asp, &prefix, prefixlen, F_ORIGINAL); + /* input filter */ if (rde_filter(&fasp, rules_l, peer, asp, &prefix, prefixlen, peer, DIR_IN) == ACTION_DENY) { @@ -854,7 +857,7 @@ rde_update_dispatch(struct imsg *imsg) rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, &prefix, prefixlen); - path_update(peer, fasp, &prefix, prefixlen); + path_update(peer, fasp, &prefix, prefixlen, F_LOCAL); /* free modified aspath */ if (fasp != asp) @@ -918,6 +921,10 @@ rde_update_dispatch(struct imsg *imsg) mpp += pos; mplen -= pos; + /* add original path to the Adj-RIB-In */ + path_update(peer, asp, &prefix, prefixlen, + F_ORIGINAL); + /* input filter */ if (rde_filter(&fasp, rules_l, peer, asp, &prefix, prefixlen, peer, DIR_IN) == @@ -944,7 +951,8 @@ rde_update_dispatch(struct imsg *imsg) rde_update_log("update", peer, &asp->nexthop->exit_nexthop, &prefix, prefixlen); - path_update(peer, fasp, &prefix, prefixlen); + path_update(peer, fasp, &prefix, prefixlen, + F_LOCAL); /* free modified aspath */ if (fasp != asp) @@ -2160,7 +2168,8 @@ network_init(struct network_head *net_l) void network_add(struct network_config *nc, int flagstatic) { - struct rde_aspath *asp; + struct rde_aspath *asp; + struct rde_peer *p; asp = path_get(); asp->aspath = aspath_get(NULL, 0); @@ -2169,15 +2178,14 @@ network_add(struct network_config *nc, int flagstatic) F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; /* the nexthop is unset unless a default set overrides it */ - if (flagstatic) { - rde_apply_set(asp, &nc->attrset, nc->prefix.af, &peerself, - DIR_IN); - path_update(&peerself, asp, &nc->prefix, nc->prefixlen); - } else { - rde_apply_set(asp, &nc->attrset, nc->prefix.af, &peerdynamic, - DIR_IN); - path_update(&peerdynamic, asp, &nc->prefix, nc->prefixlen); - } + if (flagstatic) + p = &peerself; + else + p = &peerdynamic; + + rde_apply_set(asp, &nc->attrset, nc->prefix.af, p, DIR_IN); + path_update(p, asp, &nc->prefix, nc->prefixlen, F_ORIGINAL); + path_update(p, asp, &nc->prefix, nc->prefixlen, F_LOCAL); path_put(asp); filterset_free(&nc->attrset); diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index d07eb43dd19..2826417c304 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.85 2006/01/20 16:40:17 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.86 2006/01/24 13:34:33 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -294,7 +294,7 @@ int community_set(struct rde_aspath *, int, int); void path_init(u_int32_t); void path_shutdown(void); void path_update(struct rde_peer *, struct rde_aspath *, - struct bgpd_addr *, int); + struct bgpd_addr *, int, u_int32_t); int path_compare(struct rde_aspath *, struct rde_aspath *); struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *); void path_remove(struct rde_aspath *); diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index e7446e71703..d752d97e6ad 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.82 2006/01/24 13:00:35 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.83 2006/01/24 13:34:33 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -85,38 +85,77 @@ path_shutdown(void) void path_update(struct rde_peer *peer, struct rde_aspath *nasp, - struct bgpd_addr *prefix, int prefixlen) + struct bgpd_addr *prefix, int prefixlen, u_int32_t flags) { struct rde_aspath *asp; - struct prefix *p; + struct prefix *p, *oldp = NULL; - rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0); - rde_send_pftable_commit(); + + if (flags & F_LOCAL) { + rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0); + rde_send_pftable_commit(); + } - if ((p = prefix_get(peer, prefix, prefixlen, F_LOCAL)) != NULL) { - if (path_compare(nasp, p->aspath) == 0) { - /* update last change */ - p->lastchange = time(NULL); - return; - } + /* + * First try to find a prefix in the specified RIB or in the + * Adj-RIB-In. This works because Local-RIB has precedence over the + * Adj-RIB-In. In the end this saves use some additional lookups. + */ + if ((p = prefix_get(peer, prefix, prefixlen, flags | F_ORIGINAL)) != + NULL) { + do { + if (path_compare(nasp, p->aspath) == 0) { + if ((p->flags & flags) == 0) { + if (oldp != NULL) { + asp = oldp->aspath; + prefix_destroy(oldp); + if (path_empty(asp)) + path_destroy(asp); + } + p->flags |= flags; + PREFIX_COUNT(p->aspath, flags, 1); + PREFIX_COUNT(peer, flags, 1); + + /* re-evaluate prefix */ + LIST_REMOVE(p, prefix_l); + prefix_evaluate(p, p->prefix); + } + /* update last change */ + p->lastchange = time(NULL); + return; + } + /* + * If the prefix is not already part of the Adj-RIB-In + * do a lookup in there. But keep the original prefix + * around so that it can be removed later. + */ + if (p->flags & F_ORIGINAL) + break; + oldp = p; + p = prefix_get(peer, prefix, prefixlen, F_ORIGINAL); + } while (p != NULL); } + /* Do not try to move a prefix that is in the wrong RIB. */ + if (p != NULL && (p->flags & flags) == 0) + p = oldp; + /* * Either the prefix does not exist or the path changed. * In both cases lookup the new aspath to make sure it is not * already in the RIB. */ if ((asp = path_lookup(nasp, peer)) == NULL) { - /* path not available, create and link new one */ + /* Path not available, create and link a new one. */ asp = path_copy(nasp); path_link(asp, peer); } - /* if the prefix was found move it else add it to the aspath */ + /* If the prefix was found move it else add it to the aspath. */ if (p != NULL) - prefix_move(asp, p, F_LOCAL); + prefix_move(asp, p, flags); else - prefix_add(asp, prefix, prefixlen, F_LOCAL); + prefix_add(asp, prefix, prefixlen, flags); } int @@ -614,7 +653,7 @@ prefix_updateall(struct rde_aspath *asp, enum nexthop_state state) } } -/* kill a prefix. Only called by path_remove. */ +/* kill a prefix. Only called by path_remove and path_update. */ void prefix_destroy(struct prefix *p) { |