summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/rde.c5
-rw-r--r--usr.sbin/bgpd/rde.h6
-rw-r--r--usr.sbin/bgpd/rde_update.c63
3 files changed, 66 insertions, 8 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 871e6f822fc..21d40c97614 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.427 2018/09/25 08:08:38 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.428 2018/09/29 07:43:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -3147,9 +3147,11 @@ rde_softreconfig_out_peer(struct rib_entry *re, struct rde_peer *peer)
/* nothing todo */
if (oa == ACTION_DENY && na == ACTION_ALLOW) {
/* send update */
+ up_rib_add(peer, re);
up_generate(peer, &nstate, &addr, pt->prefixlen);
} else if (oa == ACTION_ALLOW && na == ACTION_DENY) {
/* send withdraw */
+ up_rib_remove(peer, re);
up_generate(peer, NULL, &addr, pt->prefixlen);
} else if (oa == ACTION_ALLOW && na == ACTION_ALLOW) {
/* send update if anything changed */
@@ -3197,6 +3199,7 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr)
prefix_nhflags(p));
if (rde_filter(out_rules_tmp, peer, p, &ostate) != ACTION_DENY) {
/* send withdraw */
+ up_rib_remove(peer, re);
up_generate(peer, NULL, &addr, pt->prefixlen);
}
rde_filterstate_clean(&ostate);
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 74417487d6a..83ede7b83e3 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.193 2018/09/20 11:45:59 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.194 2018/09/29 07:43:36 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -55,6 +55,7 @@ LIST_HEAD(aspath_head, rde_aspath);
TAILQ_HEAD(aspath_queue, rde_aspath);
RB_HEAD(uptree_prefix, update_prefix);
RB_HEAD(uptree_attr, update_attr);
+RB_HEAD(uptree_rib, update_rib);
struct rib_desc;
struct rib;
@@ -70,6 +71,7 @@ struct rde_peer {
struct bgpd_addr remote_addr;
struct bgpd_addr local_v4_addr;
struct bgpd_addr local_v6_addr;
+ struct uptree_rib up_rib;
struct uptree_prefix up_prefix;
struct uptree_attr up_attrs;
struct uplist_attr updates[AID_MAX];
@@ -566,6 +568,8 @@ int nexthop_compare(struct nexthop *, struct nexthop *);
/* rde_update.c */
void up_init(struct rde_peer *);
void up_down(struct rde_peer *);
+int up_rib_remove(struct rde_peer *, struct rib_entry *);
+void up_rib_add(struct rde_peer *, struct rib_entry *);
int up_test_update(struct rde_peer *, struct prefix *);
int up_generate(struct rde_peer *, struct filterstate *,
struct bgpd_addr *, u_int8_t);
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c
index 63f11294208..a42d6f88381 100644
--- a/usr.sbin/bgpd/rde_update.c
+++ b/usr.sbin/bgpd/rde_update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_update.c,v 1.99 2018/09/18 16:54:01 sthen Exp $ */
+/* $OpenBSD: rde_update.c,v 1.100 2018/09/29 07:43:36 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -53,9 +53,15 @@ struct update_attr {
u_int16_t mpattr_len;
};
+struct update_rib {
+ RB_ENTRY(update_rib) entry;
+ struct rib_entry *re;
+};
+
void up_clear(struct uplist_attr *, struct uplist_prefix *);
int up_prefix_cmp(struct update_prefix *, struct update_prefix *);
int up_attr_cmp(struct update_attr *, struct update_attr *);
+int up_rib_cmp(struct update_rib *, struct update_rib *);
int up_add(struct rde_peer *, struct update_prefix *, struct update_attr *);
RB_PROTOTYPE(uptree_prefix, update_prefix, entry, up_prefix_cmp)
@@ -64,6 +70,9 @@ RB_GENERATE(uptree_prefix, update_prefix, entry, up_prefix_cmp)
RB_PROTOTYPE(uptree_attr, update_attr, entry, up_attr_cmp)
RB_GENERATE(uptree_attr, update_attr, entry, up_attr_cmp)
+RB_PROTOTYPE(uptree_rib, update_rib, entry, up_rib_cmp)
+RB_GENERATE(uptree_rib, update_rib, entry, up_rib_cmp)
+
SIPHASH_KEY uptree_key;
void
@@ -77,6 +86,7 @@ up_init(struct rde_peer *peer)
}
RB_INIT(&peer->up_prefix);
RB_INIT(&peer->up_attrs);
+ RB_INIT(&peer->up_rib);
peer->up_pcnt = 0;
peer->up_acnt = 0;
peer->up_nlricnt = 0;
@@ -110,13 +120,18 @@ up_clear(struct uplist_attr *updates, struct uplist_prefix *withdraws)
void
up_down(struct rde_peer *peer)
{
- u_int8_t i;
+ struct update_rib *ur, *nur;
+ u_int8_t i;
for (i = 0; i < AID_MAX; i++)
up_clear(&peer->updates[i], &peer->withdraws[i]);
RB_INIT(&peer->up_prefix);
RB_INIT(&peer->up_attrs);
+ RB_FOREACH_SAFE(ur, uptree_rib, &peer->up_rib, nur) {
+ RB_REMOVE(uptree_rib, &peer->up_rib, ur);
+ free(ur);
+ }
peer->up_pcnt = 0;
peer->up_acnt = 0;
@@ -195,6 +210,42 @@ up_attr_cmp(struct update_attr *a, struct update_attr *b)
}
int
+up_rib_cmp(struct update_rib *a, struct update_rib *b)
+{
+ if (a->re != b->re)
+ return (a->re > b->re ? 1 : -1);
+ return 0;
+}
+
+int
+up_rib_remove(struct rde_peer *peer, struct rib_entry *re)
+{
+ struct update_rib *ur, u;
+ u.re = re;
+
+ ur = RB_FIND(uptree_rib, &peer->up_rib, &u);
+ if (ur != NULL) {
+ RB_REMOVE(uptree_rib, &peer->up_rib, ur);
+ free(ur);
+ return 1;
+ } else
+ return 0;
+}
+
+void
+up_rib_add(struct rde_peer *peer, struct rib_entry *re)
+{
+ struct update_rib *ur;
+
+ if ((ur = calloc(1, sizeof(*ur))) == NULL)
+ fatal("%s", __func__);
+ ur->re = re;
+
+ if (RB_INSERT(uptree_rib, &peer->up_rib, ur) != NULL)
+ free(ur);
+}
+
+int
up_add(struct rde_peer *peer, struct update_prefix *p, struct update_attr *a)
{
struct update_attr *na = NULL;
@@ -409,11 +460,11 @@ withdraw:
if (up_test_update(peer, old) != 1)
return;
- pt_getaddr(old->re->prefix, &addr);
- if (rde_filter(rules, peer, old, NULL) == ACTION_DENY)
+ if (!up_rib_remove(peer, old->re))
return;
/* withdraw prefix */
+ pt_getaddr(old->re->prefix, &addr);
up_generate(peer, NULL, &addr, old->re->prefix->prefixlen);
} else {
switch (up_test_update(peer, new)) {
@@ -433,8 +484,8 @@ withdraw:
}
pt_getaddr(new->re->prefix, &addr);
- up_generate(peer, &state, &addr,
- new->re->prefix->prefixlen);
+ up_generate(peer, &state, &addr, new->re->prefix->prefixlen);
+ up_rib_add(peer, new->re);
rde_filterstate_clean(&state);
}