summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-04-23 19:23:28 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-04-23 19:23:28 +0000
commit494f39a1befc308729799247c26849ad4c2c1a50 (patch)
tree9b51c476c22bd280b7fa15bf6dc1d678e75f679a /usr.sbin/bgpd
parent9bac2bbde33a8f9b7e1d52e78e5db683f788aad9 (diff)
Rework the way we handle announced networks. Instead of two freak rde_peers
use one that is less freaky. Merge bgpctl and config networks into one tree. First step of a larger change in the RDE and this goes now in to allow to move forward.
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/rde.c112
-rw-r--r--usr.sbin/bgpd/rde.h6
-rw-r--r--usr.sbin/bgpd/rde_decide.c11
-rw-r--r--usr.sbin/bgpd/rde_rib.c32
4 files changed, 77 insertions, 84 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 93d63f19644..c8618fec25b 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.240 2009/03/18 19:45:09 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.241 2009/04/23 19:23:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -97,7 +97,6 @@ void network_init(struct network_head *);
void network_add(struct network_config *, int);
void network_delete(struct network_config *, int);
void network_dump_upcall(struct pt_entry *, void *);
-void network_flush(int);
void rde_shutdown(void);
int sa_cmp(struct bgpd_addr *, struct sockaddr *);
@@ -106,8 +105,7 @@ volatile sig_atomic_t rde_quit = 0;
struct bgpd_config *conf, *nconf;
time_t reloadtime;
struct rde_peer_head peerlist;
-struct rde_peer peerself;
-struct rde_peer peerdynamic;
+struct rde_peer *peerself;
struct filter_head *rules_l, *newrules;
struct imsgbuf *ibuf_se;
struct imsgbuf *ibuf_se_ctl;
@@ -439,7 +437,8 @@ badnet:
log_warnx("rde_dispatch: wrong imsg len");
break;
}
- network_flush(0);
+ prefix_network_clean(peerself, time(NULL),
+ F_ANN_DYNAMIC);
break;
case IMSG_FILTER_SET:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
@@ -629,10 +628,12 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
free(nconf);
nconf = NULL;
parent_set = NULL;
- prefix_network_clean(&peerself, reloadtime);
+ prefix_network_clean(peerself, reloadtime, 0);
/* check if filter changed */
LIST_FOREACH(peer, &peerlist, peer_l) {
+ if (peer->conf.id == 0)
+ continue;
peer->reconf_out = 0;
peer->reconf_in = 0;
if (peer->conf.softreconfig_out &&
@@ -1824,8 +1825,6 @@ rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req)
rde_dump_filterout(peer, p, req);
return;
}
- LIST_FOREACH(peer, &peerlist, peer_l)
- rde_dump_filterout(peer, p, req);
}
}
@@ -2122,6 +2121,8 @@ rde_softreconfig_out(struct pt_entry *pt, void *ptr)
pt_getaddr(pt, &addr);
LIST_FOREACH(peer, &peerlist, peer_l) {
+ if (peer->conf.id == 0)
+ continue;
if (peer->reconf_out == 0)
continue;
if (up_test_update(peer, p) != 1)
@@ -2249,6 +2250,8 @@ rde_generate_updates(struct prefix *new, struct prefix *old)
return;
LIST_FOREACH(peer, &peerlist, peer_l) {
+ if (peer->conf.id == 0)
+ continue;
if (peer->state != PEER_UP)
continue;
up_generate_updates(rules_l, peer, new, old);
@@ -2266,6 +2269,8 @@ rde_update_queue_runner(void)
do {
sent = 0;
LIST_FOREACH(peer, &peerlist, peer_l) {
+ if (peer->conf.id == 0)
+ continue;
if (peer->state != PEER_UP)
continue;
/* first withdraws */
@@ -2312,6 +2317,8 @@ rde_update6_queue_runner(void)
do {
sent = 0;
LIST_FOREACH(peer, &peerlist, peer_l) {
+ if (peer->conf.id == 0)
+ continue;
if (peer->state != PEER_UP)
continue;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
@@ -2333,6 +2340,8 @@ rde_update6_queue_runner(void)
do {
sent = 0;
LIST_FOREACH(peer, &peerlist, peer_l) {
+ if (peer->conf.id == 0)
+ continue;
if (peer->state != PEER_UP)
continue;
len = sizeof(queue_buf) - MSGSIZE_HEADER;
@@ -2395,6 +2404,8 @@ struct peer_table {
void
peer_init(u_int32_t hashsize)
{
+ struct peer_config pc;
+ struct in_addr id;
u_int32_t hs, i;
for (hs = 1; hs < hashsize; hs <<= 1)
@@ -2408,6 +2419,19 @@ peer_init(u_int32_t hashsize)
LIST_INIT(&peerlist);
peertable.peer_hashmask = hs - 1;
+
+ bzero(&pc, sizeof(pc));
+ pc.remote_as = conf->as;
+ id.s_addr = conf->bgpid;
+ snprintf(pc.descr, sizeof(pc.descr), "LOCAL: ID %s", inet_ntoa(id));
+
+ peerself = peer_add(0, &pc);
+ if (peerself == NULL)
+ fatalx("peer_init add self");
+
+ peerself->state = PEER_UP;
+ peerself->remote_bgpid = ntohl(conf->bgpid);
+ peerself->short_as = conf->short_as;
}
void
@@ -2660,24 +2684,8 @@ void
network_init(struct network_head *net_l)
{
struct network *n;
- struct in_addr id;
reloadtime = time(NULL);
- bzero(&peerself, sizeof(peerself));
- peerself.state = PEER_UP;
- peerself.remote_bgpid = ntohl(conf->bgpid);
- id.s_addr = conf->bgpid;
- peerself.conf.remote_as = conf->as;
- peerself.short_as = conf->short_as;
- snprintf(peerself.conf.descr, sizeof(peerself.conf.descr),
- "LOCAL: ID %s", inet_ntoa(id));
- bzero(&peerdynamic, sizeof(peerdynamic));
- peerdynamic.state = PEER_UP;
- peerdynamic.remote_bgpid = ntohl(conf->bgpid);
- peerdynamic.conf.remote_as = conf->as;
- peerdynamic.short_as = conf->short_as;
- snprintf(peerdynamic.conf.descr, sizeof(peerdynamic.conf.descr),
- "LOCAL: ID %s", inet_ntoa(id));
while ((n = TAILQ_FIRST(net_l)) != NULL) {
TAILQ_REMOVE(net_l, n, entry);
@@ -2690,7 +2698,7 @@ void
network_add(struct network_config *nc, int flagstatic)
{
struct rde_aspath *asp;
- struct rde_peer *p;
+ u_int32_t flags = F_PREFIX_ANNOUNCED;
asp = path_get();
asp->aspath = aspath_get(NULL, 0);
@@ -2698,15 +2706,12 @@ network_add(struct network_config *nc, int flagstatic)
asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
/* the nexthop is unset unless a default set overrides it */
+ if (!flagstatic)
+ flags |= F_ANN_DYNAMIC;
- if (flagstatic)
- p = &peerself;
- else
- p = &peerdynamic;
-
- rde_apply_set(asp, &nc->attrset, nc->prefix.af, p, p);
- path_update(p, asp, &nc->prefix, nc->prefixlen, F_ORIGINAL);
- path_update(p, asp, &nc->prefix, nc->prefixlen, F_LOCAL);
+ rde_apply_set(asp, &nc->attrset, nc->prefix.af, peerself, peerself);
+ path_update(peerself, asp, &nc->prefix, nc->prefixlen, flags | F_ORIGINAL);
+ path_update(peerself, asp, &nc->prefix, nc->prefixlen, flags | F_LOCAL);
path_put(asp);
filterset_free(&nc->attrset);
@@ -2715,15 +2720,13 @@ network_add(struct network_config *nc, int flagstatic)
void
network_delete(struct network_config *nc, int flagstatic)
{
- struct rde_peer *p;
+ u_int32_t flags = F_PREFIX_ANNOUNCED;
- if (flagstatic)
- p = &peerself;
- else
- p = &peerdynamic;
+ if (!flagstatic)
+ flags |= F_ANN_DYNAMIC;
- prefix_remove(p, &nc->prefix, nc->prefixlen, F_LOCAL);
- prefix_remove(p, &nc->prefix, nc->prefixlen, F_ORIGINAL);
+ prefix_remove(peerself, &nc->prefix, nc->prefixlen, flags | F_LOCAL);
+ prefix_remove(peerself, &nc->prefix, nc->prefixlen, flags | F_ORIGINAL);
}
void
@@ -2745,7 +2748,7 @@ network_dump_upcall(struct pt_entry *pt, void *ptr)
pt_getaddr(p->prefix, &addr);
k.prefix.s_addr = addr.v4.s_addr;
k.prefixlen = p->prefix->prefixlen;
- if (p->aspath->peer == &peerself)
+ if (p->aspath->peer == peerself)
k.flags = F_KERNEL;
if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0,
pid, -1, &k, sizeof(k)) == -1)
@@ -2757,7 +2760,7 @@ network_dump_upcall(struct pt_entry *pt, void *ptr)
pt_getaddr(p->prefix, &addr);
memcpy(&k6.prefix, &addr.v6, sizeof(k6.prefix));
k6.prefixlen = p->prefix->prefixlen;
- if (p->aspath->peer == &peerself)
+ if (p->aspath->peer == peerself)
k6.flags = F_KERNEL;
if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK6, 0,
pid, -1, &k6, sizeof(k6)) == -1)
@@ -2767,21 +2770,11 @@ network_dump_upcall(struct pt_entry *pt, void *ptr)
}
}
-void
-network_flush(int flagstatic)
-{
- if (flagstatic)
- prefix_network_clean(&peerself, time(NULL));
- else
- prefix_network_clean(&peerdynamic, time(NULL));
-}
-
/* clean up */
void
rde_shutdown(void)
{
struct rde_peer *p;
- struct rde_aspath *asp, *nasp;
struct filter_rule *r;
u_int32_t i;
@@ -2797,21 +2790,6 @@ rde_shutdown(void)
while ((p = LIST_FIRST(&peertable.peer_hashtbl[i])) != NULL)
peer_down(p->conf.id);
- /* free announced network prefixes */
- peerself.remote_bgpid = 0;
- peerself.state = PEER_DOWN;
- for (asp = LIST_FIRST(&peerself.path_h); asp != NULL; asp = nasp) {
- nasp = LIST_NEXT(asp, peer_l);
- path_remove(asp);
- }
-
- peerdynamic.remote_bgpid = 0;
- peerdynamic.state = PEER_DOWN;
- for (asp = LIST_FIRST(&peerdynamic.path_h); asp != NULL; asp = nasp) {
- nasp = LIST_NEXT(asp, peer_l);
- path_remove(asp);
- }
-
/* free filters */
while ((r = TAILQ_FIRST(rules_l)) != NULL) {
TAILQ_REMOVE(rules_l, r, entry);
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index e2709d4e513..78debe20f4b 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.105 2009/03/19 06:52:59 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.106 2009/04/23 19:23:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -164,6 +164,8 @@ LIST_HEAD(prefix_head, prefix);
#define F_ATTR_LINKED 0x20000
#define F_LOCAL 0x40000 /* Local-RIB */
#define F_ORIGINAL 0x80000 /* Adj-RIB-In */
+#define F_RIB_MASK (F_LOCAL | F_ORIGINAL)
+#define F_ANN_DYNAMIC 0x100000
#define ORIGIN_IGP 0
@@ -357,7 +359,7 @@ struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *, u_int32_t);
void prefix_updateall(struct rde_aspath *, enum nexthop_state,
enum nexthop_state);
void prefix_destroy(struct prefix *);
-void prefix_network_clean(struct rde_peer *, time_t);
+void prefix_network_clean(struct rde_peer *, time_t, u_int32_t);
void nexthop_init(u_int32_t);
void nexthop_shutdown(void);
diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c
index 963d95718be..c7f0d2dd93a 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.51 2008/05/08 09:51:46 henning Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.52 2009/04/23 19:23:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -201,9 +201,16 @@ prefix_cmp(struct prefix *p1, struct prefix *p2)
&p2->aspath->peer->remote_addr,
sizeof(p1->aspath->peer->remote_addr)));
+ /* 12. for announced prefixes prefer dynamic routes */
+ if ((p1->flags & F_ANN_DYNAMIC) != (p2->flags & F_ANN_DYNAMIC)) {
+ if (p1->flags & F_ANN_DYNAMIC)
+ return (1);
+ else
+ return (-1);
+ }
+
fatalx("Uh, oh a politician in the decision process");
/* NOTREACHED */
- return (0);
}
/*
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 6e3410cb31a..299cea252a1 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.97 2008/11/21 17:41:22 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.98 2009/04/23 19:23:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -104,14 +104,14 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp,
NULL) {
do {
if (path_compare(nasp, p->aspath) == 0) {
- if ((p->flags & flags) == 0) {
+ if ((p->flags & flags & F_RIB_MASK) == 0) {
if (oldp != NULL) {
asp = oldp->aspath;
prefix_destroy(oldp);
if (path_empty(asp))
path_destroy(asp);
}
- p->flags |= flags;
+ p->flags |= flags & F_RIB_MASK;
PREFIX_COUNT(p->aspath, flags, 1);
PREFIX_COUNT(peer, flags, 1);
@@ -136,7 +136,7 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp,
}
/* Do not try to move a prefix that is in the wrong RIB. */
- if (p == NULL || (p->flags & flags) == 0)
+ if (p == NULL || (p->flags & flags & F_RIB_MASK) == 0)
p = oldp;
/*
@@ -477,12 +477,12 @@ prefix_move(struct rde_aspath *asp, struct prefix *p, u_int32_t flags)
* to flags the old prefix p may not be removed but instead p->flags
* needs to be adjusted.
*/
- if (p->flags != flags) {
- if ((p->flags & flags) == 0)
+ if ((p->flags & F_RIB_MASK) != (flags & F_RIB_MASK)) {
+ if ((p->flags & flags & F_RIB_MASK) == 0)
fatalx("prefix_move: "
"prefix is not part of desired RIB");
- p->flags &= ~flags;
+ p->flags &= ~(flags & F_RIB_MASK);
PREFIX_COUNT(p->aspath, flags, -1);
/* as before peer count needs no update because of move */
@@ -557,8 +557,8 @@ prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen,
}
/* if prefix belongs to more than one RIB just remove one instance */
- if (p->flags != flags) {
- p->flags &= ~flags;
+ if ((p->flags & F_RIB_MASK) != (flags & F_RIB_MASK)) {
+ p->flags &= ~(flags & F_RIB_MASK);
PREFIX_COUNT(p->aspath, flags, -1);
PREFIX_COUNT(peer, flags, -1);
@@ -609,8 +609,13 @@ 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 && p->flags & flags)
- return (p);
+ if (p->aspath->peer != peer ||
+ (p->flags & flags & F_RIB_MASK) == 0)
+ continue;
+ if (flags & F_PREFIX_ANNOUNCED &&
+ (flags & F_ANN_DYNAMIC) != (p->flags & F_ANN_DYNAMIC))
+ continue;
+ return (p);
}
return (NULL);
}
@@ -679,7 +684,7 @@ prefix_destroy(struct prefix *p)
* helper function to clean up the connected networks after a reload
*/
void
-prefix_network_clean(struct rde_peer *peer, time_t reloadtime)
+prefix_network_clean(struct rde_peer *peer, time_t reloadtime, u_int32_t flags)
{
struct rde_aspath *asp, *xasp;
struct prefix *p, *xp;
@@ -689,7 +694,8 @@ prefix_network_clean(struct rde_peer *peer, time_t reloadtime)
xasp = LIST_NEXT(asp, peer_l);
for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) {
xp = LIST_NEXT(p, path_l);
- if (reloadtime > p->lastchange) {
+ if (reloadtime > p->lastchange &&
+ (p->flags & F_ANN_DYNAMIC) == flags) {
pte = p->prefix;
prefix_unlink(p);
prefix_free(p);