summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.c19
-rw-r--r--usr.sbin/bgpd/bgpd.h3
-rw-r--r--usr.sbin/bgpd/rde.c111
-rw-r--r--usr.sbin/bgpd/rde.h3
4 files changed, 118 insertions, 18 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 0c3c610a172..dd294fb4a51 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.162 2010/05/17 15:49:29 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.163 2010/05/19 12:44:14 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -441,13 +441,6 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
conf, sizeof(struct bgpd_config)) == -1)
return (-1);
- /* send peer list and listeners to the SE */
- for (p = *peer_l; p != NULL; p = p->next) {
- if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
- &p->conf, sizeof(struct peer_config)) == -1)
- return (-1);
- }
-
TAILQ_FOREACH(la, conf->listen_addrs, entry) {
if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd,
la, sizeof(struct listen_addr)) == -1)
@@ -473,6 +466,16 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
free(rr);
}
+ /* send peer list and listeners to the SE and RDE */
+ for (p = *peer_l; p != NULL; p = p->next) {
+ if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
+ &p->conf, sizeof(struct peer_config)) == -1)
+ return (-1);
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_PEER, p->conf.id, 0, -1,
+ &p->conf, sizeof(struct peer_config)) == -1)
+ return (-1);
+ }
+
/* networks go via kroute to the RDE */
if (kr_net_reload(0, &net_l))
return (-1);
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 9e4ccd8b80f..ea4c4bfc5f3 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.260 2010/05/17 16:08:20 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.261 2010/05/19 12:44:14 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
+#include <sys/tree.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index c1a3462f6ad..4daea46e753 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.294 2010/05/17 15:49:29 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.295 2010/05/19 12:44:14 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -87,6 +87,8 @@ void rde_up_dump_upcall(struct rib_entry *, void *);
void rde_softreconfig_out(struct rib_entry *, void *);
void rde_softreconfig_in(struct rib_entry *, void *);
void rde_softreconfig_load(struct rib_entry *, void *);
+void rde_softreconfig_load_peer(struct rib_entry *, void *);
+void rde_softreconfig_unload_peer(struct rib_entry *, void *);
void rde_update_queue_runner(void);
void rde_update6_queue_runner(u_int8_t);
@@ -545,10 +547,12 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
struct mrt xmrt;
struct rde_rib rn;
struct rde_peer *peer;
+ struct peer_config *pconf;
struct filter_rule *r;
struct filter_set *s;
struct nexthop *nh;
- int n, fd, reconf_in = 0, reconf_out = 0;
+ int n, fd, reconf_in = 0, reconf_out = 0,
+ reconf_rib = 0;
u_int16_t rid;
if ((n = imsg_read(ibuf)) == -1)
@@ -625,6 +629,16 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
} else
ribs[rid].state = RECONF_KEEP;
break;
+ case IMSG_RECONF_PEER:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
+ sizeof(struct peer_config))
+ fatalx("IMSG_RECONF_PEER bad len");
+ if ((peer = peer_get(imsg.hdr.peerid)) == NULL)
+ break;
+ pconf = imsg.data;
+ strlcpy(peer->conf.rib, pconf->rib,
+ sizeof(peer->conf.rib));
+ break;
case IMSG_RECONF_FILTER:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
sizeof(struct filter_rule))
@@ -708,18 +722,28 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
continue;
peer->reconf_out = 0;
peer->reconf_in = 0;
- if (peer->conf.softreconfig_out &&
- !rde_filter_equal(rules_l, newrules, peer,
- DIR_OUT)) {
- peer->reconf_out = 1;
- reconf_out = 1;
- }
+ peer->reconf_rib = 0;
if (peer->conf.softreconfig_in &&
!rde_filter_equal(rules_l, newrules, peer,
DIR_IN)) {
peer->reconf_in = 1;
reconf_in = 1;
}
+ if (peer->ribid != rib_find(peer->conf.rib)) {
+ rib_dump(&ribs[peer->ribid],
+ rde_softreconfig_unload_peer, peer,
+ AID_UNSPEC);
+ peer->ribid = rib_find(peer->conf.rib);
+ peer->reconf_rib = 1;
+ reconf_rib = 1;
+ continue;
+ }
+ if (peer->conf.softreconfig_out &&
+ !rde_filter_equal(rules_l, newrules, peer,
+ DIR_OUT)) {
+ peer->reconf_out = 1;
+ reconf_out = 1;
+ }
}
/* bring ribs in sync before softreconfig dance */
for (rid = 0; rid < rib_size; rid++) {
@@ -745,6 +769,13 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
NULL, AID_UNSPEC);
}
}
+ if (reconf_rib) {
+ LIST_FOREACH(peer, &peerlist, peer_l) {
+ rib_dump(&ribs[peer->ribid],
+ rde_softreconfig_load_peer,
+ peer, AID_UNSPEC);
+ }
+ }
while ((r = TAILQ_FIRST(rules_l)) != NULL) {
TAILQ_REMOVE(rules_l, r, entry);
@@ -2596,6 +2627,70 @@ rde_softreconfig_load(struct rib_entry *re, void *ptr)
}
}
+void
+rde_softreconfig_load_peer(struct rib_entry *re, void *ptr)
+{
+ struct rde_peer *peer = ptr;
+ struct prefix *p = re->active;
+ struct pt_entry *pt;
+ struct rde_aspath *nasp;
+ enum filter_actions na;
+ struct bgpd_addr addr;
+
+ pt = re->prefix;
+ pt_getaddr(pt, &addr);
+
+ /* check if prefix was announced */
+ if (up_test_update(peer, p) != 1)
+ return;
+
+ na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath,
+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT);
+ nasp = nasp != NULL ? nasp : p->aspath;
+
+ if (na == ACTION_DENY)
+ /* nothing todo */
+ goto done;
+
+ /* send update */
+ up_generate(peer, nasp, &addr, pt->prefixlen);
+done:
+ if (nasp != p->aspath)
+ path_put(nasp);
+}
+
+void
+rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr)
+{
+ struct rde_peer *peer = ptr;
+ struct prefix *p = re->active;
+ struct pt_entry *pt;
+ struct rde_aspath *oasp;
+ enum filter_actions oa;
+ struct bgpd_addr addr;
+
+ pt = re->prefix;
+ pt_getaddr(pt, &addr);
+
+ /* check if prefix was announced */
+ if (up_test_update(peer, p) != 1)
+ return;
+
+ oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath,
+ &addr, pt->prefixlen, p->aspath->peer, DIR_OUT);
+ oasp = oasp != NULL ? oasp : p->aspath;
+
+ if (oa == ACTION_DENY)
+ /* nothing todo */
+ goto done;
+
+ /* send withdraw */
+ up_generate(peer, NULL, &addr, pt->prefixlen);
+done:
+ if (oasp != p->aspath)
+ path_put(oasp);
+}
+
/*
* update specific functions
*/
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 21e98c90f5c..687b44d3998 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.135 2010/05/17 16:08:20 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.136 2010/05/19 12:44:15 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -74,6 +74,7 @@ struct rde_peer {
u_int16_t short_as;
u_int8_t reconf_in; /* in filter changed */
u_int8_t reconf_out; /* out filter changed */
+ u_int8_t reconf_rib; /* rib changed */
};
#define AS_SET 1