summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2006-01-24 13:34:33 +0000
committerclaudio <claudio@openbsd.org>2006-01-24 13:34:33 +0000
commit1f78fdc6afed22c998ed379cd9e147d84ffead3a (patch)
tree68ba1560f491096e35d37baa158d1e768a054a05
parentIt is possible that a prefix is part of two RIBs in that case prefix_remove() (diff)
downloadwireguard-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.c34
-rw-r--r--usr.sbin/bgpd/rde.h4
-rw-r--r--usr.sbin/bgpd/rde_rib.c71
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)
{