summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-01-14 22:39:50 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-01-14 22:39:50 +0000
commitb1c3d07d4d4cfedeb893c21778201c4158a94d10 (patch)
tree49fb0c3d25c2d8568db362b0e9951d1aa7611a4b /usr.sbin/bgpd
parent337207ec49af7a59ee151a9cef2218d82ffafc29 (diff)
Small step in supporting the Adj-RIB-In additionaly to the Local-RIB.
First step is to define two flags F_LOCAL and F_ORIGINAL. These flags are used to distinguish prefix in the Local-RIB and those in the Adj- RIB-In. Adapt prefix API and add additional checks so that no Adj-RIB- In prefixes get mistakenly selected. Currently no F_ORIGINAL prefixes are created but this may change soon. Looks good Henning.
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/rde.c31
-rw-r--r--usr.sbin/bgpd/rde.h16
-rw-r--r--usr.sbin/bgpd/rde_decide.c13
-rw-r--r--usr.sbin/bgpd/rde_rib.c59
4 files changed, 79 insertions, 40 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 3d42f8b1407..f876984be1f 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.192 2006/01/13 13:04:33 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.193 2006/01/14 22:39:49 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -722,7 +722,8 @@ rde_update_dispatch(struct imsg *imsg)
}
rde_update_log("withdraw", peer, NULL, &prefix, prefixlen);
- prefix_remove(peer, &prefix, prefixlen);
+ prefix_remove(peer, &prefix, prefixlen, F_LOCAL);
+ prefix_remove(peer, &prefix, prefixlen, F_ORIGINAL);
}
if (attrpath_len == 0) /* 0 = no NLRI information in this message */
@@ -774,7 +775,10 @@ rde_update_dispatch(struct imsg *imsg)
rde_update_log("withdraw", peer, NULL,
&prefix, prefixlen);
- prefix_remove(peer, &prefix, prefixlen);
+ prefix_remove(peer, &prefix, prefixlen,
+ F_LOCAL);
+ prefix_remove(peer, &prefix, prefixlen,
+ F_ORIGINAL);
}
break;
default:
@@ -1473,7 +1477,9 @@ rde_dump_upcall(struct pt_entry *pt, void *ptr)
memcpy(&pid, ptr, sizeof(pid));
LIST_FOREACH(p, &pt->prefix_h, prefix_l)
- rde_dump_rib_as(p, pid);
+ /* for now dump only stuff from the local-RIB */
+ if (p->flags & F_LOCAL)
+ rde_dump_rib_as(p, pid);
}
void
@@ -1490,7 +1496,9 @@ rde_dump_as(struct filter_as *a, pid_t pid)
continue;
/* match found */
LIST_FOREACH(p, &asp->prefix_h, path_l)
- rde_dump_rib_as(p, pid);
+ /* for now dump only stuff from the local-RIB */
+ if (p->flags & F_LOCAL)
+ rde_dump_rib_as(p, pid);
}
}
}
@@ -1512,7 +1520,9 @@ rde_dump_prefix_upcall(struct pt_entry *pt, void *ptr)
return;
if (!prefix_compare(&ctl->pref->prefix, &addr, ctl->pref->prefixlen))
LIST_FOREACH(p, &pt->prefix_h, prefix_l)
- rde_dump_rib_as(p, ctl->pid);
+ /* for now dump only stuff from the local-RIB */
+ if (p->flags & F_LOCAL)
+ rde_dump_rib_as(p, ctl->pid);
}
void
@@ -2173,10 +2183,15 @@ network_add(struct network_config *nc, int flagstatic)
void
network_delete(struct network_config *nc, int flagstatic)
{
+ struct rde_peer *p;
+
if (flagstatic)
- prefix_remove(&peerself, &nc->prefix, nc->prefixlen);
+ p = &peerself;
else
- prefix_remove(&peerdynamic, &nc->prefix, nc->prefixlen);
+ p = &peerdynamic;
+
+ prefix_remove(p, &nc->prefix, nc->prefixlen, F_LOCAL);
+ prefix_remove(p, &nc->prefix, nc->prefixlen, F_ORIGINAL);
}
void
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index b40a897718a..fa9c50e81c5 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.82 2006/01/12 14:05:13 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.83 2006/01/14 22:39:49 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -148,6 +148,9 @@ LIST_HEAD(prefix_head, prefix);
#define F_NEXTHOP_BLACKHOLE 0x0400
#define F_NEXTHOP_NOMODIFY 0x0800
#define F_ATTR_LINKED 0x1000
+#define F_LOCAL 0x2000 /* Local-RIB */
+#define F_ORIGINAL 0x4000 /* Adj-RIB-In */
+
#define ORIGIN_IGP 0
#define ORIGIN_EGP 1
@@ -303,12 +306,15 @@ void path_put(struct rde_aspath *);
#define PREFIX_SIZE(x) (((x) + 7) / 8 + 1)
int prefix_compare(const struct bgpd_addr *,
const struct bgpd_addr *, int);
-struct prefix *prefix_get(struct rde_peer *, struct bgpd_addr *, int);
-struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int);
+struct prefix *prefix_get(struct rde_peer *, struct bgpd_addr *, int,
+ u_int32_t);
+struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int,
+ u_int32_t);
struct pt_entry *prefix_move(struct rde_aspath *, struct prefix *);
-void prefix_remove(struct rde_peer *, struct bgpd_addr *, int);
+void prefix_remove(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 pt_entry *, struct rde_peer *);
+struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *, u_int32_t);
void prefix_updateall(struct rde_aspath *, enum nexthop_state);
void prefix_destroy(struct prefix *);
void prefix_network_clean(struct rde_peer *, time_t);
diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c
index e4895538c07..8e2cbe06d97 100644
--- a/usr.sbin/bgpd/rde_decide.c
+++ b/usr.sbin/bgpd/rde_decide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_decide.c,v 1.45 2006/01/13 13:04:33 claudio Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.46 2006/01/14 22:39:49 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -115,6 +115,12 @@ prefix_cmp(struct prefix *p1, struct prefix *p2)
if (p2 == NULL)
return (1);
+ /* only prefix in the Local-RIB are eligible */
+ if (!(p1->flags & F_LOCAL))
+ return (-1);
+ if (!(p2->flags & F_LOCAL))
+ return (1);
+
asp1 = p1->aspath;
asp2 = p2->aspath;
@@ -232,8 +238,9 @@ prefix_evaluate(struct prefix *p, struct pt_entry *pte)
}
xp = LIST_FIRST(&pte->prefix_h);
- if (xp == NULL || (xp->aspath->nexthop != NULL &&
- xp->aspath->nexthop->state != NEXTHOP_REACH))
+ if (xp == NULL || !(xp->flags & F_LOCAL) ||
+ (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state !=
+ NEXTHOP_REACH))
/* xp is ineligible */
xp = NULL;
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 41548ef65b4..b8bf8041028 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.77 2006/01/12 14:05:13 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.78 2006/01/14 22:39:49 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -84,7 +84,7 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp,
rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0);
rde_send_pftable_commit();
- if ((p = prefix_get(peer, prefix, prefixlen)) != NULL) {
+ if ((p = prefix_get(peer, prefix, prefixlen, F_LOCAL)) != NULL) {
if (path_compare(nasp, p->aspath) == 0) {
/* update last change */
p->lastchange = time(NULL);
@@ -107,7 +107,7 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp,
if (p != NULL)
prefix_move(asp, p);
else
- prefix_add(asp, prefix, prefixlen);
+ prefix_add(asp, prefix, prefixlen, F_LOCAL);
}
int
@@ -313,7 +313,7 @@ path_put(struct rde_aspath *asp)
static struct prefix *prefix_alloc(void);
static void prefix_free(struct prefix *);
static void prefix_link(struct prefix *, struct pt_entry *,
- struct rde_aspath *);
+ struct rde_aspath *, u_int32_t);
static void prefix_unlink(struct prefix *);
int
@@ -360,47 +360,44 @@ prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b,
* search for specified prefix of a peer. Returns NULL if not found.
*/
struct prefix *
-prefix_get(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen)
+prefix_get(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen,
+ u_int32_t flags)
{
struct pt_entry *pte;
pte = pt_get(prefix, prefixlen);
if (pte == NULL)
return (NULL);
- return (prefix_bypeer(pte, peer));
+ return (prefix_bypeer(pte, peer, flags));
}
/*
* Adds or updates a prefix.
*/
struct pt_entry *
-prefix_add(struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen)
+prefix_add(struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen,
+ u_int32_t flags)
{
struct prefix *p;
struct pt_entry *pte;
- int needlink = 0;
pte = pt_get(prefix, prefixlen);
if (pte == NULL)
pte = pt_add(prefix, prefixlen);
- p = prefix_bypeer(pte, asp->peer);
+ p = prefix_bypeer(pte, asp->peer, flags);
if (p == NULL) {
- needlink = 1;
p = prefix_alloc();
- }
-
- if (needlink == 1)
- prefix_link(p, pte, asp);
- else {
+ prefix_link(p, pte, asp, flags);
+ } else {
if (p->aspath != asp)
/* prefix belongs to a different aspath so move */
- return prefix_move(asp, p);
+ return (prefix_move(asp, p));
p->lastchange = time(NULL);
}
- return pte;
+ return (pte);
}
/*
@@ -421,6 +418,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
/* peer and prefix pointers are still equal */
np->prefix = p->prefix;
np->lastchange = time(NULL);
+ np->flags = p->flags;
/* add to new as path */
LIST_INSERT_HEAD(&asp->prefix_h, np, path_l);
@@ -464,7 +462,8 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
* pt_entry -- become empty remove them too.
*/
void
-prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen)
+prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen,
+ u_int32_t flags)
{
struct prefix *p;
struct pt_entry *pte;
@@ -474,14 +473,17 @@ prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen)
if (pte == NULL) /* Got a dummy withdrawn request */
return;
- p = prefix_bypeer(pte, peer);
+ p = prefix_bypeer(pte, peer, flags);
if (p == NULL) /* Got a dummy withdrawn request. */
return;
asp = p->aspath;
- rde_send_pftable(asp->pftableid, prefix, prefixlen, 1);
- rde_send_pftable_commit();
+ if (p->flags & F_LOCAL) {
+ /* only prefixes in the local RIB were pushed into pf */
+ rde_send_pftable(asp->pftableid, prefix, prefixlen, 1);
+ rde_send_pftable_commit();
+ }
prefix_unlink(p);
prefix_free(p);
@@ -515,12 +517,12 @@ prefix_write(u_char *buf, int len, struct bgpd_addr *prefix, u_int8_t plen)
* belonging to the peer peer. Returns NULL if no match found.
*/
struct prefix *
-prefix_bypeer(struct pt_entry *pte, struct rde_peer *peer)
+prefix_bypeer(struct pt_entry *pte, struct rde_peer *peer, u_int32_t flags)
{
struct prefix *p;
LIST_FOREACH(p, &pte->prefix_h, prefix_l) {
- if (p->aspath->peer == peer)
+ if (p->aspath->peer == peer && p->flags & flags)
return (p);
}
return (NULL);
@@ -536,6 +538,13 @@ prefix_updateall(struct rde_aspath *asp, enum nexthop_state state)
return;
LIST_FOREACH(p, &asp->prefix_h, path_l) {
+ /*
+ * skip non local-RIB nodes, only local-RIB prefixes are
+ * eligible. Both F_LOCAL and F_ORIGINAL may be set.
+ */
+ if (!(p->flags & F_LOCAL))
+ continue;
+
/* redo the route decision */
LIST_REMOVE(p, prefix_l);
/*
@@ -598,7 +607,8 @@ prefix_network_clean(struct rde_peer *peer, time_t reloadtime)
* Link a prefix into the different parent objects.
*/
static void
-prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp)
+prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp,
+ u_int32_t flags)
{
LIST_INSERT_HEAD(&asp->prefix_h, pref, path_l);
asp->prefix_cnt++;
@@ -607,6 +617,7 @@ prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp)
pref->aspath = asp;
pref->prefix = pte;
pref->lastchange = time(NULL);
+ pref->flags = flags;
/* make route decision */
prefix_evaluate(pref, pte);