diff options
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 19 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 111 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 3 |
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 |