mirror of
https://github.com/openbsd/src.git
synced 2025-01-10 06:47:55 -08:00
Rewrite the internals of the RDE reload logic.
This is the first step to make bgpd reload non blocking in the RDE. It also speeds up the reload time a fair bit in some cases (mainly if you run with multiple RIBs and have larger filtersets) and it should also fix a few edge cases on reloads. Testing done by benno@, florian@ and sthen@ OK henning@ and benno@
This commit is contained in:
parent
3499042cfa
commit
28b060e1f1
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: bgpd.h,v 1.277 2013/05/11 14:42:28 benno Exp $ */
|
||||
/* $OpenBSD: bgpd.h,v 1.278 2013/08/14 20:34:25 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
@ -103,6 +103,7 @@ enum reconf_action {
|
||||
RECONF_NONE,
|
||||
RECONF_KEEP,
|
||||
RECONF_REINIT,
|
||||
RECONF_RELOAD,
|
||||
RECONF_DELETE
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: rde.c,v 1.324 2013/07/17 14:09:13 benno Exp $ */
|
||||
/* $OpenBSD: rde.c,v 1.325 2013/08/14 20:34:26 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
@ -85,12 +85,11 @@ void rde_dump_mrt_new(struct mrt *, pid_t, int);
|
||||
void rde_dump_done(void *);
|
||||
|
||||
int rde_rdomain_import(struct rde_aspath *, struct rdomain *);
|
||||
void rde_up_dump_upcall(struct rib_entry *, void *);
|
||||
void rde_reload_done(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_up_dump_upcall(struct rib_entry *, void *);
|
||||
void rde_update_queue_runner(void);
|
||||
void rde_update6_queue_runner(u_int8_t);
|
||||
|
||||
@ -119,7 +118,7 @@ struct bgpd_config *conf, *nconf;
|
||||
time_t reloadtime;
|
||||
struct rde_peer_head peerlist;
|
||||
struct rde_peer *peerself;
|
||||
struct filter_head *rules_l, *newrules;
|
||||
struct filter_head *out_rules, *out_rules_tmp;
|
||||
struct rdomain_head *rdomains_l, *newdomains;
|
||||
struct imsgbuf *ibuf_se;
|
||||
struct imsgbuf *ibuf_se_ctl;
|
||||
@ -224,10 +223,10 @@ rde_main(int pipe_m2r[2], int pipe_s2r[2], int pipe_m2s[2], int pipe_s2rctl[2],
|
||||
nexthop_init(nexthophashsize);
|
||||
peer_init(peerhashsize);
|
||||
|
||||
rules_l = calloc(1, sizeof(struct filter_head));
|
||||
if (rules_l == NULL)
|
||||
out_rules = calloc(1, sizeof(struct filter_head));
|
||||
if (out_rules == NULL)
|
||||
fatal(NULL);
|
||||
TAILQ_INIT(rules_l);
|
||||
TAILQ_INIT(out_rules);
|
||||
rdomains_l = calloc(1, sizeof(struct rdomain_head));
|
||||
if (rdomains_l == NULL)
|
||||
fatal(NULL);
|
||||
@ -637,12 +636,11 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
|
||||
struct imsg imsg;
|
||||
struct mrt xmrt;
|
||||
struct rde_rib rn;
|
||||
struct rde_peer *peer;
|
||||
struct filter_head *nr;
|
||||
struct filter_rule *r;
|
||||
struct filter_set *s;
|
||||
struct nexthop *nh;
|
||||
int n, fd, reconf_in = 0, reconf_out = 0,
|
||||
reconf_rib = 0;
|
||||
int n, fd;
|
||||
u_int16_t rid;
|
||||
|
||||
if ((n = imsg_read(ibuf)) == -1)
|
||||
@ -686,10 +684,10 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
|
||||
sizeof(struct bgpd_config))
|
||||
fatalx("IMSG_RECONF_CONF bad len");
|
||||
reloadtime = time(NULL);
|
||||
newrules = calloc(1, sizeof(struct filter_head));
|
||||
if (newrules == NULL)
|
||||
out_rules_tmp = calloc(1, sizeof(struct filter_head));
|
||||
if (out_rules_tmp == NULL)
|
||||
fatal(NULL);
|
||||
TAILQ_INIT(newrules);
|
||||
TAILQ_INIT(out_rules_tmp);
|
||||
newdomains = calloc(1, sizeof(struct rdomain_head));
|
||||
if (newdomains == NULL)
|
||||
fatal(NULL);
|
||||
@ -698,8 +696,11 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
|
||||
NULL)
|
||||
fatal(NULL);
|
||||
memcpy(nconf, imsg.data, sizeof(struct bgpd_config));
|
||||
for (rid = 0; rid < rib_size; rid++)
|
||||
for (rid = 0; rid < rib_size; rid++) {
|
||||
if (*ribs[rid].name == '\0')
|
||||
break;
|
||||
ribs[rid].state = RECONF_DELETE;
|
||||
}
|
||||
break;
|
||||
case IMSG_RECONF_RIB:
|
||||
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
|
||||
@ -712,10 +713,18 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
|
||||
else if (ribs[rid].rtableid != rn.rtableid ||
|
||||
(ribs[rid].flags & F_RIB_HASNOFIB) !=
|
||||
(rn.flags & F_RIB_HASNOFIB)) {
|
||||
/* Big hammer in the F_RIB_NOFIB case but
|
||||
* not often enough used to optimise it more. */
|
||||
struct filter_head *in_rules;
|
||||
/*
|
||||
* Big hammer in the F_RIB_HASNOFIB case but
|
||||
* not often enough used to optimise it more.
|
||||
* Need to save the filters so that they're not
|
||||
* lost.
|
||||
*/
|
||||
in_rules = ribs[rid].in_rules;
|
||||
ribs[rid].in_rules = NULL;
|
||||
rib_free(&ribs[rid]);
|
||||
rib_new(rn.name, rn.rtableid, rn.flags);
|
||||
ribs[rid].in_rules = in_rules;
|
||||
} else
|
||||
ribs[rid].state = RECONF_KEEP;
|
||||
break;
|
||||
@ -727,9 +736,27 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
|
||||
fatal(NULL);
|
||||
memcpy(r, imsg.data, sizeof(struct filter_rule));
|
||||
TAILQ_INIT(&r->set);
|
||||
r->peer.ribid = rib_find(r->rib);
|
||||
if ((r->peer.ribid = rib_find(r->rib)) == RIB_FAILED) {
|
||||
log_warnx("IMSG_RECONF_FILTER: filter rule "
|
||||
"for not existsing rib %s", r->rib);
|
||||
parent_set = NULL;
|
||||
free(r);
|
||||
break;
|
||||
}
|
||||
parent_set = &r->set;
|
||||
TAILQ_INSERT_TAIL(newrules, r, entry);
|
||||
if (r->dir == DIR_IN) {
|
||||
nr = ribs[r->peer.ribid].in_rules_tmp;
|
||||
if (nr == NULL) {
|
||||
nr = calloc(1,
|
||||
sizeof(struct filter_head));
|
||||
if (nr == NULL)
|
||||
fatal(NULL);
|
||||
TAILQ_INIT(nr);
|
||||
ribs[r->peer.ribid].in_rules_tmp = nr;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(nr, r, entry);
|
||||
} else
|
||||
TAILQ_INSERT_TAIL(out_rules_tmp, r, entry);
|
||||
break;
|
||||
case IMSG_RECONF_RDOMAIN:
|
||||
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
|
||||
@ -764,110 +791,9 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
|
||||
case IMSG_RECONF_DONE:
|
||||
if (nconf == NULL)
|
||||
fatalx("got IMSG_RECONF_DONE but no config");
|
||||
if ((nconf->flags & BGPD_FLAG_NO_EVALUATE)
|
||||
!= (conf->flags & BGPD_FLAG_NO_EVALUATE)) {
|
||||
log_warnx("change to/from route-collector "
|
||||
"mode ignored");
|
||||
if (conf->flags & BGPD_FLAG_NO_EVALUATE)
|
||||
nconf->flags |= BGPD_FLAG_NO_EVALUATE;
|
||||
else
|
||||
nconf->flags &= ~BGPD_FLAG_NO_EVALUATE;
|
||||
}
|
||||
memcpy(conf, nconf, sizeof(struct bgpd_config));
|
||||
conf->listen_addrs = NULL;
|
||||
conf->csock = NULL;
|
||||
conf->rcsock = NULL;
|
||||
free(nconf);
|
||||
nconf = NULL;
|
||||
parent_set = NULL;
|
||||
/* sync peerself with conf */
|
||||
peerself->remote_bgpid = ntohl(conf->bgpid);
|
||||
peerself->conf.local_as = conf->as;
|
||||
peerself->conf.remote_as = conf->as;
|
||||
peerself->short_as = conf->short_as;
|
||||
|
||||
/* apply new set of rdomain, sync will be done later */
|
||||
while ((rd = SIMPLEQ_FIRST(rdomains_l)) != NULL) {
|
||||
SIMPLEQ_REMOVE_HEAD(rdomains_l, entry);
|
||||
filterset_free(&rd->import);
|
||||
filterset_free(&rd->export);
|
||||
free(rd);
|
||||
}
|
||||
free(rdomains_l);
|
||||
rdomains_l = newdomains;
|
||||
|
||||
/* check if filter changed */
|
||||
LIST_FOREACH(peer, &peerlist, peer_l) {
|
||||
if (peer->conf.id == 0)
|
||||
continue;
|
||||
peer->reconf_out = 0;
|
||||
peer->reconf_in = 0;
|
||||
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++) {
|
||||
if (ribs[rid].state == RECONF_DELETE)
|
||||
rib_free(&ribs[rid]);
|
||||
else if (ribs[rid].state == RECONF_REINIT)
|
||||
rib_dump(&ribs[0],
|
||||
rde_softreconfig_load, &ribs[rid],
|
||||
AID_UNSPEC);
|
||||
}
|
||||
/* sync local-RIBs first */
|
||||
if (reconf_in)
|
||||
rib_dump(&ribs[0], rde_softreconfig_in, NULL,
|
||||
AID_UNSPEC);
|
||||
/* then sync peers */
|
||||
if (reconf_out) {
|
||||
int i;
|
||||
for (i = 1; i < rib_size; i++) {
|
||||
if (ribs[i].state == RECONF_REINIT)
|
||||
/* already synced by _load */
|
||||
continue;
|
||||
rib_dump(&ribs[i], rde_softreconfig_out,
|
||||
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);
|
||||
filterset_free(&r->set);
|
||||
free(r);
|
||||
}
|
||||
free(rules_l);
|
||||
rules_l = newrules;
|
||||
|
||||
log_info("RDE reconfigured");
|
||||
imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
|
||||
-1, NULL, 0);
|
||||
rde_reload_done();
|
||||
break;
|
||||
case IMSG_NEXTHOP_UPDATE:
|
||||
nexthop_update(imsg.data);
|
||||
@ -1342,8 +1268,6 @@ done:
|
||||
return (error);
|
||||
}
|
||||
|
||||
extern u_int16_t rib_size;
|
||||
|
||||
void
|
||||
rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
|
||||
struct bgpd_addr *prefix, u_int8_t prefixlen)
|
||||
@ -1359,9 +1283,11 @@ rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
|
||||
r += path_update(&ribs[0], peer, asp, prefix, prefixlen);
|
||||
|
||||
for (i = 1; i < rib_size; i++) {
|
||||
if (*ribs[i].name == '\0')
|
||||
break;
|
||||
/* input filter */
|
||||
action = rde_filter(i, &fasp, rules_l, peer, asp, prefix,
|
||||
prefixlen, peer, DIR_IN);
|
||||
action = rde_filter(ribs[i].in_rules, &fasp, peer, asp, prefix,
|
||||
prefixlen, peer);
|
||||
|
||||
if (fasp == NULL)
|
||||
fasp = asp;
|
||||
@ -1399,6 +1325,8 @@ rde_update_withdraw(struct rde_peer *peer, struct bgpd_addr *prefix,
|
||||
peer->prefix_rcvd_withdraw++;
|
||||
|
||||
for (i = rib_size - 1; ; i--) {
|
||||
if (*ribs[i].name == '\0')
|
||||
break;
|
||||
if (prefix_remove(&ribs[i], peer, prefix, prefixlen, 0)) {
|
||||
rde_update_log("withdraw", i, peer, NULL, prefix,
|
||||
prefixlen);
|
||||
@ -2293,8 +2221,8 @@ rde_dump_filterout(struct rde_peer *peer, struct prefix *p,
|
||||
return;
|
||||
|
||||
pt_getaddr(p->prefix, &addr);
|
||||
a = rde_filter(1 /* XXX */, &asp, rules_l, peer, p->aspath, &addr,
|
||||
p->prefix->prefixlen, p->aspath->peer, DIR_OUT);
|
||||
a = rde_filter(out_rules, &asp, peer, p->aspath, &addr,
|
||||
p->prefix->prefixlen, p->aspath->peer);
|
||||
if (asp)
|
||||
asp->peer = p->aspath->peer;
|
||||
else
|
||||
@ -2630,196 +2558,235 @@ rde_send_nexthop(struct bgpd_addr *next, int valid)
|
||||
* soft reconfig specific functions
|
||||
*/
|
||||
void
|
||||
rde_softreconfig_out(struct rib_entry *re, void *ptr)
|
||||
rde_reload_done(void)
|
||||
{
|
||||
struct prefix *p = re->active;
|
||||
struct pt_entry *pt;
|
||||
struct rdomain *rd;
|
||||
struct rde_peer *peer;
|
||||
struct rde_aspath *oasp, *nasp;
|
||||
enum filter_actions oa, na;
|
||||
struct bgpd_addr addr;
|
||||
struct filter_head *fh;
|
||||
u_int16_t rid;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
/* first merge the main config */
|
||||
if ((nconf->flags & BGPD_FLAG_NO_EVALUATE)
|
||||
!= (conf->flags & BGPD_FLAG_NO_EVALUATE)) {
|
||||
log_warnx("change to/from route-collector "
|
||||
"mode ignored");
|
||||
if (conf->flags & BGPD_FLAG_NO_EVALUATE)
|
||||
nconf->flags |= BGPD_FLAG_NO_EVALUATE;
|
||||
else
|
||||
nconf->flags &= ~BGPD_FLAG_NO_EVALUATE;
|
||||
}
|
||||
memcpy(conf, nconf, sizeof(struct bgpd_config));
|
||||
conf->listen_addrs = NULL;
|
||||
conf->csock = NULL;
|
||||
conf->rcsock = NULL;
|
||||
free(nconf);
|
||||
nconf = NULL;
|
||||
|
||||
pt = re->prefix;
|
||||
pt_getaddr(pt, &addr);
|
||||
/* sync peerself with conf */
|
||||
peerself->remote_bgpid = ntohl(conf->bgpid);
|
||||
peerself->conf.local_as = conf->as;
|
||||
peerself->conf.remote_as = conf->as;
|
||||
peerself->short_as = conf->short_as;
|
||||
|
||||
/* apply new set of rdomain, sync will be done later */
|
||||
while ((rd = SIMPLEQ_FIRST(rdomains_l)) != NULL) {
|
||||
SIMPLEQ_REMOVE_HEAD(rdomains_l, entry);
|
||||
filterset_free(&rd->import);
|
||||
filterset_free(&rd->export);
|
||||
free(rd);
|
||||
}
|
||||
free(rdomains_l);
|
||||
rdomains_l = newdomains;
|
||||
/* XXX WHERE IS THE SYNC ??? */
|
||||
|
||||
/*
|
||||
* make the new filter rules the active one but keep the old for
|
||||
* softrconfig. This is needed so that changes happening are using
|
||||
* the right filters.
|
||||
*/
|
||||
fh = out_rules;
|
||||
out_rules = out_rules_tmp;
|
||||
out_rules_tmp = fh;
|
||||
|
||||
/* check if filter changed */
|
||||
LIST_FOREACH(peer, &peerlist, peer_l) {
|
||||
if (peer->conf.id == 0)
|
||||
continue;
|
||||
if (peer->ribid != re->ribid)
|
||||
peer->reconf_out = 0;
|
||||
peer->reconf_rib = 0;
|
||||
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);
|
||||
if (peer->ribid == RIB_FAILED)
|
||||
fatalx("King Bula's peer met an unknown RIB");
|
||||
peer->reconf_rib = 1;
|
||||
continue;
|
||||
if (peer->reconf_out == 0)
|
||||
continue;
|
||||
if (up_test_update(peer, p) != 1)
|
||||
continue;
|
||||
|
||||
oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath,
|
||||
&addr, pt->prefixlen, p->aspath->peer, DIR_OUT);
|
||||
na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath,
|
||||
&addr, pt->prefixlen, p->aspath->peer, DIR_OUT);
|
||||
oasp = oasp != NULL ? oasp : p->aspath;
|
||||
nasp = nasp != NULL ? nasp : p->aspath;
|
||||
|
||||
if (oa == ACTION_DENY && na == ACTION_DENY)
|
||||
/* nothing todo */
|
||||
goto done;
|
||||
if (oa == ACTION_DENY && na == ACTION_ALLOW) {
|
||||
/* send update */
|
||||
up_generate(peer, nasp, &addr, pt->prefixlen);
|
||||
goto done;
|
||||
}
|
||||
if (oa == ACTION_ALLOW && na == ACTION_DENY) {
|
||||
/* send withdraw */
|
||||
up_generate(peer, NULL, &addr, pt->prefixlen);
|
||||
goto done;
|
||||
if (peer->conf.softreconfig_out &&
|
||||
!rde_filter_equal(out_rules, out_rules_tmp, peer)) {
|
||||
peer->reconf_out = 1;
|
||||
}
|
||||
if (oa == ACTION_ALLOW && na == ACTION_ALLOW) {
|
||||
if (path_compare(nasp, oasp) == 0)
|
||||
goto done;
|
||||
/* send update */
|
||||
up_generate(peer, nasp, &addr, pt->prefixlen);
|
||||
}
|
||||
|
||||
done:
|
||||
if (oasp != p->aspath)
|
||||
path_put(oasp);
|
||||
if (nasp != p->aspath)
|
||||
path_put(nasp);
|
||||
}
|
||||
/* bring ribs in sync */
|
||||
for (rid = 0; rid < rib_size; rid++) {
|
||||
if (*ribs[rid].name == '\0')
|
||||
continue;
|
||||
/* flip rules, make new active */
|
||||
fh = ribs[rid].in_rules;
|
||||
ribs[rid].in_rules = ribs[rid].in_rules_tmp;
|
||||
ribs[rid].in_rules_tmp = fh;
|
||||
|
||||
switch (ribs[rid].state) {
|
||||
case RECONF_DELETE:
|
||||
rib_free(&ribs[rid]);
|
||||
break;
|
||||
case RECONF_KEEP:
|
||||
if (rde_filter_equal(ribs[rid].in_rules,
|
||||
ribs[rid].in_rules_tmp, NULL))
|
||||
/* rib is in sync */
|
||||
break;
|
||||
ribs[rid].state = RECONF_RELOAD;
|
||||
/* FALLTHROUGH */
|
||||
case RECONF_REINIT:
|
||||
rib_dump(&ribs[0], rde_softreconfig_in, &ribs[rid],
|
||||
AID_UNSPEC);
|
||||
break;
|
||||
case RECONF_RELOAD:
|
||||
log_warnx("Bad rib reload state");
|
||||
/* FALLTHROUGH */
|
||||
case RECONF_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
LIST_FOREACH(peer, &peerlist, peer_l) {
|
||||
if (peer->reconf_out)
|
||||
rib_dump(&ribs[peer->ribid], rde_softreconfig_out,
|
||||
peer, AID_UNSPEC);
|
||||
else if (peer->reconf_rib)
|
||||
/* dump the full table to neighbors that changed rib */
|
||||
peer_dump(peer->conf.id, AID_UNSPEC);
|
||||
}
|
||||
rde_free_filter(out_rules_tmp);
|
||||
out_rules_tmp = NULL;
|
||||
for (rid = 0; rid < rib_size; rid++) {
|
||||
if (*ribs[rid].name == '\0')
|
||||
continue;
|
||||
rde_free_filter(ribs[rid].in_rules_tmp);
|
||||
ribs[rid].in_rules_tmp = NULL;
|
||||
ribs[rid].state = RECONF_NONE;
|
||||
}
|
||||
|
||||
log_info("RDE reconfigured");
|
||||
imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
|
||||
-1, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
rde_softreconfig_in(struct rib_entry *re, void *ptr)
|
||||
{
|
||||
struct rib *rib = ptr;
|
||||
struct prefix *p, *np;
|
||||
struct pt_entry *pt;
|
||||
struct rde_peer *peer;
|
||||
struct rde_aspath *asp, *oasp, *nasp;
|
||||
enum filter_actions oa, na;
|
||||
struct bgpd_addr addr;
|
||||
u_int16_t i;
|
||||
|
||||
pt = re->prefix;
|
||||
pt_getaddr(pt, &addr);
|
||||
for (p = LIST_FIRST(&re->prefix_h); p != NULL; p = np) {
|
||||
/*
|
||||
* prefix_remove() and path_update() may change the object
|
||||
* so cache the values.
|
||||
*/
|
||||
np = LIST_NEXT(p, rib_l);
|
||||
|
||||
/* store aspath as prefix may change till we're done */
|
||||
asp = p->aspath;
|
||||
peer = asp->peer;
|
||||
|
||||
/* XXX how can this happen ??? */
|
||||
if (peer->reconf_in == 0)
|
||||
continue;
|
||||
|
||||
for (i = 1; i < rib_size; i++) {
|
||||
/* only active ribs need a softreconfig rerun */
|
||||
if (ribs[i].state != RECONF_KEEP)
|
||||
continue;
|
||||
|
||||
/* check if prefix changed */
|
||||
oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr,
|
||||
pt->prefixlen, peer, DIR_IN);
|
||||
na = rde_filter(i, &nasp, newrules, peer, asp, &addr,
|
||||
pt->prefixlen, peer, DIR_IN);
|
||||
/* check if prefix changed */
|
||||
if (rib->state == RECONF_RELOAD) {
|
||||
oa = rde_filter(rib->in_rules_tmp, &oasp, peer,
|
||||
asp, &addr, pt->prefixlen, peer);
|
||||
oasp = oasp != NULL ? oasp : asp;
|
||||
nasp = nasp != NULL ? nasp : asp;
|
||||
|
||||
if (oa == ACTION_DENY && na == ACTION_DENY)
|
||||
/* nothing todo */
|
||||
goto done;
|
||||
if (oa == ACTION_DENY && na == ACTION_ALLOW) {
|
||||
/* update Local-RIB */
|
||||
path_update(&ribs[i], peer, nasp, &addr,
|
||||
pt->prefixlen);
|
||||
goto done;
|
||||
}
|
||||
if (oa == ACTION_ALLOW && na == ACTION_DENY) {
|
||||
/* remove from Local-RIB */
|
||||
prefix_remove(&ribs[i], peer, &addr,
|
||||
pt->prefixlen, 0);
|
||||
goto done;
|
||||
}
|
||||
if (oa == ACTION_ALLOW && na == ACTION_ALLOW) {
|
||||
if (path_compare(nasp, oasp) == 0)
|
||||
goto done;
|
||||
/* send update */
|
||||
path_update(&ribs[i], peer, nasp, &addr,
|
||||
pt->prefixlen);
|
||||
}
|
||||
|
||||
done:
|
||||
if (oasp != asp)
|
||||
path_put(oasp);
|
||||
if (nasp != asp)
|
||||
path_put(nasp);
|
||||
} else {
|
||||
/* make sure we update everything for RECONF_REINIT */
|
||||
oa = ACTION_DENY;
|
||||
oasp = asp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rde_softreconfig_load(struct rib_entry *re, void *ptr)
|
||||
{
|
||||
struct rib *rib = ptr;
|
||||
struct prefix *p, *np;
|
||||
struct pt_entry *pt;
|
||||
struct rde_peer *peer;
|
||||
struct rde_aspath *asp, *nasp;
|
||||
enum filter_actions action;
|
||||
struct bgpd_addr addr;
|
||||
|
||||
pt = re->prefix;
|
||||
pt_getaddr(pt, &addr);
|
||||
for (p = LIST_FIRST(&re->prefix_h); p != NULL; p = np) {
|
||||
np = LIST_NEXT(p, rib_l);
|
||||
|
||||
/* store aspath as prefix may change till we're done */
|
||||
asp = p->aspath;
|
||||
peer = asp->peer;
|
||||
|
||||
action = rde_filter(rib->id, &nasp, newrules, peer, asp, &addr,
|
||||
pt->prefixlen, peer, DIR_IN);
|
||||
na = rde_filter(rib->in_rules, &nasp, peer, asp,
|
||||
&addr, pt->prefixlen, peer);
|
||||
nasp = nasp != NULL ? nasp : asp;
|
||||
|
||||
if (action == ACTION_ALLOW) {
|
||||
/* go through all 4 possible combinations */
|
||||
/* if (oa == ACTION_DENY && na == ACTION_DENY) */
|
||||
/* nothing todo */
|
||||
if (oa == ACTION_DENY && na == ACTION_ALLOW) {
|
||||
/* update Local-RIB */
|
||||
path_update(rib, peer, nasp, &addr, pt->prefixlen);
|
||||
} else if (oa == ACTION_ALLOW && na == ACTION_DENY) {
|
||||
/* remove from Local-RIB */
|
||||
prefix_remove(rib, peer, &addr, pt->prefixlen, 0);
|
||||
} else if (oa == ACTION_ALLOW && na == ACTION_ALLOW) {
|
||||
if (path_compare(nasp, oasp) != 0)
|
||||
/* send update */
|
||||
path_update(rib, peer, nasp, &addr,
|
||||
pt->prefixlen);
|
||||
}
|
||||
|
||||
if (oasp != asp)
|
||||
path_put(oasp);
|
||||
if (nasp != asp)
|
||||
path_put(nasp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rde_softreconfig_load_peer(struct rib_entry *re, void *ptr)
|
||||
rde_softreconfig_out(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 rde_peer *peer = ptr;
|
||||
struct rde_aspath *oasp, *nasp;
|
||||
enum filter_actions oa, na;
|
||||
struct bgpd_addr addr;
|
||||
|
||||
if (peer->conf.id == 0)
|
||||
fatalx("King Bula troubled by bad peer");
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
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);
|
||||
oa = rde_filter(out_rules_tmp, &oasp, peer, p->aspath,
|
||||
&addr, pt->prefixlen, p->aspath->peer);
|
||||
na = rde_filter(out_rules, &nasp, peer, p->aspath,
|
||||
&addr, pt->prefixlen, p->aspath->peer);
|
||||
oasp = oasp != NULL ? oasp : p->aspath;
|
||||
nasp = nasp != NULL ? nasp : p->aspath;
|
||||
|
||||
if (na == ACTION_DENY)
|
||||
/* go through all 4 possible combinations */
|
||||
/* if (oa == ACTION_DENY && na == ACTION_DENY) */
|
||||
/* nothing todo */
|
||||
goto done;
|
||||
if (oa == ACTION_DENY && na == ACTION_ALLOW) {
|
||||
/* send update */
|
||||
up_generate(peer, nasp, &addr, pt->prefixlen);
|
||||
} else if (oa == ACTION_ALLOW && na == ACTION_DENY) {
|
||||
/* send withdraw */
|
||||
up_generate(peer, NULL, &addr, pt->prefixlen);
|
||||
} else if (oa == ACTION_ALLOW && na == ACTION_ALLOW) {
|
||||
/* send update if path attributes changed */
|
||||
if (path_compare(nasp, oasp) != 0)
|
||||
up_generate(peer, nasp, &addr, pt->prefixlen);
|
||||
}
|
||||
|
||||
/* send update */
|
||||
up_generate(peer, nasp, &addr, pt->prefixlen);
|
||||
done:
|
||||
if (oasp != p->aspath)
|
||||
path_put(oasp);
|
||||
if (nasp != p->aspath)
|
||||
path_put(nasp);
|
||||
}
|
||||
@ -2841,8 +2808,8 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr)
|
||||
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);
|
||||
oa = rde_filter(out_rules_tmp, &oasp, peer, p->aspath,
|
||||
&addr, pt->prefixlen, p->aspath->peer);
|
||||
oasp = oasp != NULL ? oasp : p->aspath;
|
||||
|
||||
if (oa == ACTION_DENY)
|
||||
@ -2870,7 +2837,7 @@ rde_up_dump_upcall(struct rib_entry *re, void *ptr)
|
||||
fatalx("King Bula: monstrous evil horror.");
|
||||
if (re->active == NULL)
|
||||
return;
|
||||
up_generate_updates(rules_l, peer, re->active, NULL);
|
||||
up_generate_updates(out_rules, peer, re->active, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2893,7 +2860,7 @@ rde_generate_updates(u_int16_t ribid, struct prefix *new, struct prefix *old)
|
||||
continue;
|
||||
if (peer->state != PEER_UP)
|
||||
continue;
|
||||
up_generate_updates(rules_l, peer, new, old);
|
||||
up_generate_updates(out_rules, peer, new, old);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3140,6 +3107,8 @@ peer_add(u_int32_t id, struct peer_config *p_conf)
|
||||
memcpy(&peer->conf, p_conf, sizeof(struct peer_config));
|
||||
peer->remote_bgpid = 0;
|
||||
peer->ribid = rib_find(peer->conf.rib);
|
||||
if (peer->ribid == RIB_FAILED)
|
||||
fatalx("King Bula's new peer met an unknown RIB");
|
||||
peer->state = PEER_NONE;
|
||||
up_init(peer);
|
||||
|
||||
@ -3334,7 +3303,7 @@ peer_dump(u_int32_t id, u_int8_t aid)
|
||||
}
|
||||
|
||||
if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE)
|
||||
up_generate_default(rules_l, peer, aid);
|
||||
up_generate_default(out_rules, peer, aid);
|
||||
else
|
||||
rib_dump(&ribs[peer->ribid], rde_up_dump_upcall, peer, aid);
|
||||
if (peer->capa.grestart.restart)
|
||||
@ -3455,9 +3424,12 @@ network_add(struct network_config *nc, int flagstatic)
|
||||
rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself);
|
||||
if (vpnset)
|
||||
rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself);
|
||||
for (i = 1; i < rib_size; i++)
|
||||
for (i = 1; i < rib_size; i++) {
|
||||
if (*ribs[i].name == '\0')
|
||||
break;
|
||||
path_update(&ribs[i], peerself, asp, &nc->prefix,
|
||||
nc->prefixlen);
|
||||
}
|
||||
path_put(asp);
|
||||
filterset_free(&nc->attrset);
|
||||
}
|
||||
@ -3500,9 +3472,12 @@ network_delete(struct network_config *nc, int flagstatic)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = rib_size - 1; i > 0; i--)
|
||||
for (i = rib_size - 1; i > 0; i--) {
|
||||
if (*ribs[i].name == '\0')
|
||||
break;
|
||||
prefix_remove(&ribs[i], peerself, &nc->prefix, nc->prefixlen,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -3542,7 +3517,6 @@ void
|
||||
rde_shutdown(void)
|
||||
{
|
||||
struct rde_peer *p;
|
||||
struct filter_rule *r;
|
||||
u_int32_t i;
|
||||
|
||||
/*
|
||||
@ -3558,12 +3532,12 @@ rde_shutdown(void)
|
||||
peer_down(p->conf.id);
|
||||
|
||||
/* free filters */
|
||||
while ((r = TAILQ_FIRST(rules_l)) != NULL) {
|
||||
TAILQ_REMOVE(rules_l, r, entry);
|
||||
filterset_free(&r->set);
|
||||
free(r);
|
||||
rde_free_filter(out_rules);
|
||||
for (i = 0; i < rib_size; i++) {
|
||||
if (*ribs[i].name == '\0')
|
||||
break;
|
||||
rde_free_filter(ribs[i].in_rules);
|
||||
}
|
||||
free(rules_l);
|
||||
|
||||
nexthop_shutdown();
|
||||
path_shutdown();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: rde.h,v 1.146 2013/07/17 14:09:13 benno Exp $ */
|
||||
/* $OpenBSD: rde.h,v 1.147 2013/08/14 20:34:26 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
|
||||
@ -76,7 +76,6 @@ struct rde_peer {
|
||||
u_int16_t ribid;
|
||||
u_int16_t short_as;
|
||||
u_int16_t mrt_idx;
|
||||
u_int8_t reconf_in; /* in filter changed */
|
||||
u_int8_t reconf_out; /* out filter changed */
|
||||
u_int8_t reconf_rib; /* rib changed */
|
||||
};
|
||||
@ -287,6 +286,8 @@ struct rib_entry {
|
||||
struct rib {
|
||||
char name[PEER_DESCR_LEN];
|
||||
struct rib_tree rib;
|
||||
struct filter_head *in_rules;
|
||||
struct filter_head *in_rules_tmp;
|
||||
u_int rtableid;
|
||||
u_int16_t flags;
|
||||
u_int16_t id;
|
||||
@ -325,6 +326,7 @@ u_int32_t rde_local_as(void);
|
||||
int rde_noevaluate(void);
|
||||
int rde_decisionflags(void);
|
||||
int rde_as4byte(struct rde_peer *);
|
||||
void rde_free_filter(struct filter_head *);
|
||||
|
||||
/* rde_attr.c */
|
||||
int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *,
|
||||
@ -379,14 +381,13 @@ int community_ext_conv(struct filter_extcommunity *, u_int16_t,
|
||||
void prefix_evaluate(struct prefix *, struct rib_entry *);
|
||||
|
||||
/* rde_filter.c */
|
||||
enum filter_actions rde_filter(u_int16_t, struct rde_aspath **,
|
||||
struct filter_head *, struct rde_peer *,
|
||||
struct rde_aspath *, struct bgpd_addr *, u_int8_t,
|
||||
struct rde_peer *, enum directions);
|
||||
enum filter_actions rde_filter(struct filter_head *, struct rde_aspath **,
|
||||
struct rde_peer *, struct rde_aspath *,
|
||||
struct bgpd_addr *, u_int8_t, struct rde_peer *);
|
||||
void rde_apply_set(struct rde_aspath *, struct filter_set_head *,
|
||||
u_int8_t, struct rde_peer *, struct rde_peer *);
|
||||
int rde_filter_equal(struct filter_head *, struct filter_head *,
|
||||
struct rde_peer *, enum directions);
|
||||
struct rde_peer *);
|
||||
|
||||
/* rde_prefix.c */
|
||||
#define pt_empty(pt) ((pt)->refcnt == 0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: rde_filter.c,v 1.68 2012/11/13 09:47:20 claudio Exp $ */
|
||||
/* $OpenBSD: rde_filter.c,v 1.69 2013/08/14 20:34:27 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
|
||||
@ -30,9 +30,9 @@ int rde_filter_match(struct filter_rule *, struct rde_aspath *,
|
||||
int filterset_equal(struct filter_set_head *, struct filter_set_head *);
|
||||
|
||||
enum filter_actions
|
||||
rde_filter(u_int16_t ribid, struct rde_aspath **new, struct filter_head *rules,
|
||||
rde_filter(struct filter_head *rules, struct rde_aspath **new,
|
||||
struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *prefix,
|
||||
u_int8_t prefixlen, struct rde_peer *from, enum directions dir)
|
||||
u_int8_t prefixlen, struct rde_peer *from)
|
||||
{
|
||||
struct filter_rule *f;
|
||||
enum filter_actions action = ACTION_ALLOW; /* default allow */
|
||||
@ -47,11 +47,10 @@ rde_filter(u_int16_t ribid, struct rde_aspath **new, struct filter_head *rules,
|
||||
*/
|
||||
return (ACTION_DENY);
|
||||
|
||||
if (rules == NULL)
|
||||
return (action);
|
||||
|
||||
TAILQ_FOREACH(f, rules, entry) {
|
||||
if (dir != f->dir)
|
||||
continue;
|
||||
if (dir == DIR_IN && f->peer.ribid != ribid)
|
||||
continue;
|
||||
if (f->peer.groupid != 0 &&
|
||||
f->peer.groupid != peer->conf.groupid)
|
||||
continue;
|
||||
@ -420,42 +419,32 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
|
||||
|
||||
int
|
||||
rde_filter_equal(struct filter_head *a, struct filter_head *b,
|
||||
struct rde_peer *peer, enum directions dir)
|
||||
struct rde_peer *peer)
|
||||
{
|
||||
struct filter_rule *fa, *fb;
|
||||
|
||||
fa = TAILQ_FIRST(a);
|
||||
fb = TAILQ_FIRST(b);
|
||||
fa = a ? TAILQ_FIRST(a) : NULL;
|
||||
fb = b ? TAILQ_FIRST(b) : NULL;
|
||||
|
||||
while (fa != NULL || fb != NULL) {
|
||||
/* skip all rules with wrong direction */
|
||||
if (fa != NULL && dir != fa->dir) {
|
||||
fa = TAILQ_NEXT(fa, entry);
|
||||
continue;
|
||||
}
|
||||
if (fb != NULL && dir != fb->dir) {
|
||||
fb = TAILQ_NEXT(fb, entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip all rules with wrong peer */
|
||||
if (fa != NULL && fa->peer.groupid != 0 &&
|
||||
if (peer != NULL && fa != NULL && fa->peer.groupid != 0 &&
|
||||
fa->peer.groupid != peer->conf.groupid) {
|
||||
fa = TAILQ_NEXT(fa, entry);
|
||||
continue;
|
||||
}
|
||||
if (fa != NULL && fa->peer.peerid != 0 &&
|
||||
if (peer != NULL && fa != NULL && fa->peer.peerid != 0 &&
|
||||
fa->peer.peerid != peer->conf.id) {
|
||||
fa = TAILQ_NEXT(fa, entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fb != NULL && fb->peer.groupid != 0 &&
|
||||
if (peer != NULL && fb != NULL && fb->peer.groupid != 0 &&
|
||||
fb->peer.groupid != peer->conf.groupid) {
|
||||
fb = TAILQ_NEXT(fb, entry);
|
||||
continue;
|
||||
}
|
||||
if (fb != NULL && fb->peer.peerid != 0 &&
|
||||
if (peer != NULL && fb != NULL && fb->peer.peerid != 0 &&
|
||||
fb->peer.peerid != peer->conf.id) {
|
||||
fb = TAILQ_NEXT(fb, entry);
|
||||
continue;
|
||||
@ -481,6 +470,22 @@ rde_filter_equal(struct filter_head *a, struct filter_head *b,
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
rde_free_filter(struct filter_head *fh)
|
||||
{
|
||||
struct filter_rule *r;
|
||||
|
||||
if (fh == NULL)
|
||||
return;
|
||||
|
||||
while ((r = TAILQ_FIRST(fh)) != NULL) {
|
||||
TAILQ_REMOVE(fh, r, entry);
|
||||
filterset_free(&r->set);
|
||||
free(r);
|
||||
}
|
||||
free(fh);
|
||||
}
|
||||
|
||||
/* free a filterset and take care of possible name2id references */
|
||||
void
|
||||
filterset_free(struct filter_set_head *sh)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: rde_rib.c,v 1.137 2013/07/17 14:09:13 benno Exp $ */
|
||||
/* $OpenBSD: rde_rib.c,v 1.138 2013/08/14 20:34:27 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
|
||||
@ -82,6 +82,11 @@ rib_new(char *name, u_int rtableid, u_int16_t flags)
|
||||
ribs[id].flags = flags;
|
||||
ribs[id].rtableid = rtableid;
|
||||
|
||||
ribs[id].in_rules = calloc(1, sizeof(struct filter_head));
|
||||
if (ribs[id].in_rules == NULL)
|
||||
fatal(NULL);
|
||||
TAILQ_INIT(ribs[id].in_rules);
|
||||
|
||||
return (id);
|
||||
}
|
||||
|
||||
@ -91,7 +96,7 @@ rib_find(char *name)
|
||||
u_int16_t id;
|
||||
|
||||
if (name == NULL || *name == '\0')
|
||||
return (1); /* XXX */
|
||||
return (1); /* no name returns the Loc-RIB */
|
||||
|
||||
for (id = 0; id < rib_size; id++) {
|
||||
if (!strcmp(ribs[id].name, name))
|
||||
@ -108,6 +113,7 @@ rib_free(struct rib *rib)
|
||||
struct rib_entry *re, *xre;
|
||||
struct prefix *p, *np;
|
||||
|
||||
/* abort pending rib_dumps */
|
||||
for (ctx = LIST_FIRST(&rib_dump_h); ctx != NULL; ctx = next) {
|
||||
next = LIST_NEXT(ctx, entry);
|
||||
if (ctx->ctx_rib == rib) {
|
||||
@ -126,8 +132,8 @@ rib_free(struct rib *rib)
|
||||
|
||||
/*
|
||||
* Removing the prefixes is tricky because the last one
|
||||
* will remove the rib_entry as well and at because we do
|
||||
* a empty check in prefix_destroy() it is not possible to
|
||||
* will remove the rib_entry as well and because we do
|
||||
* an empty check in prefix_destroy() it is not possible to
|
||||
* use the default for loop.
|
||||
*/
|
||||
while ((p = LIST_FIRST(&re->prefix_h))) {
|
||||
@ -145,6 +151,8 @@ rib_free(struct rib *rib)
|
||||
break;
|
||||
}
|
||||
}
|
||||
rde_free_filter(rib->in_rules_tmp);
|
||||
rde_free_filter(rib->in_rules);
|
||||
bzero(rib, sizeof(struct rib));
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: rde_update.c,v 1.80 2012/04/12 17:31:05 claudio Exp $ */
|
||||
/* $OpenBSD: rde_update.c,v 1.81 2013/08/14 20:34:27 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
|
||||
@ -411,9 +411,8 @@ up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
|
||||
return;
|
||||
|
||||
pt_getaddr(old->prefix, &addr);
|
||||
if (rde_filter(peer->ribid, NULL, rules, peer, old->aspath,
|
||||
&addr, old->prefix->prefixlen, old->aspath->peer,
|
||||
DIR_OUT) == ACTION_DENY)
|
||||
if (rde_filter(rules, NULL, peer, old->aspath, &addr,
|
||||
old->prefix->prefixlen, old->aspath->peer) == ACTION_DENY)
|
||||
return;
|
||||
|
||||
/* withdraw prefix */
|
||||
@ -430,9 +429,8 @@ up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
|
||||
}
|
||||
|
||||
pt_getaddr(new->prefix, &addr);
|
||||
if (rde_filter(peer->ribid, &asp, rules, peer, new->aspath,
|
||||
&addr, new->prefix->prefixlen, new->aspath->peer,
|
||||
DIR_OUT) == ACTION_DENY) {
|
||||
if (rde_filter(rules, &asp, peer, new->aspath, &addr,
|
||||
new->prefix->prefixlen, new->aspath->peer) == ACTION_DENY) {
|
||||
path_put(asp);
|
||||
up_generate_updates(rules, peer, NULL, old);
|
||||
return;
|
||||
@ -474,8 +472,8 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer,
|
||||
bzero(&addr, sizeof(addr));
|
||||
addr.aid = aid;
|
||||
|
||||
if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL,
|
||||
DIR_OUT) == ACTION_DENY) {
|
||||
if (rde_filter(rules, &fasp, peer, asp, &addr, 0, NULL) ==
|
||||
ACTION_DENY) {
|
||||
path_put(fasp);
|
||||
path_put(asp);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user