summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/rde.c123
-rw-r--r--usr.sbin/bgpd/rde.h10
-rw-r--r--usr.sbin/bgpd/rde_rib.c48
3 files changed, 88 insertions, 93 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 1ca29f3b4ff..fa423adabf6 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.245 2009/05/17 14:45:25 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.246 2009/05/27 06:58:15 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -44,6 +44,10 @@ void rde_sighdlr(int);
void rde_dispatch_imsg_session(struct imsgbuf *);
void rde_dispatch_imsg_parent(struct imsgbuf *);
int rde_update_dispatch(struct imsg *);
+void rde_update_update(struct rde_peer *, struct rde_aspath *,
+ struct bgpd_addr *, u_int8_t);
+void rde_update_withdraw(struct rde_peer *, struct bgpd_addr *,
+ u_int8_t);
int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *,
struct rde_aspath *, struct mpattr *);
u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t);
@@ -727,7 +731,7 @@ int
rde_update_dispatch(struct imsg *imsg)
{
struct rde_peer *peer;
- struct rde_aspath *asp = NULL, *fasp;
+ struct rde_aspath *asp = NULL;
u_char *p, *mpp = NULL;
int error = -1, pos = 0;
u_int16_t afi, len, mplen;
@@ -848,10 +852,7 @@ rde_update_dispatch(struct imsg *imsg)
goto done;
}
- peer->prefix_rcvd_withdraw++;
- rde_update_log("withdraw", peer, NULL, &prefix, prefixlen);
- prefix_remove(&ribs[1], peer, &prefix, prefixlen, 0);
- prefix_remove(&ribs[0], peer, &prefix, prefixlen, 0);
+ rde_update_withdraw(peer, &prefix, prefixlen);
}
if (attrpath_len == 0) {
@@ -906,13 +907,7 @@ rde_update_dispatch(struct imsg *imsg)
mpp += pos;
mplen -= pos;
- peer->prefix_rcvd_withdraw++;
- rde_update_log("withdraw", peer, NULL,
- &prefix, prefixlen);
- prefix_remove(&ribs[1], peer, &prefix,
- prefixlen, 0);
- prefix_remove(&ribs[0], peer, &prefix,
- prefixlen, 0);
+ rde_update_withdraw(peer, &prefix, prefixlen);
}
break;
default:
@@ -960,17 +955,7 @@ rde_update_dispatch(struct imsg *imsg)
goto done;
}
- peer->prefix_rcvd_update++;
- /* add original path to the Adj-RIB-In */
- if (peer->conf.softreconfig_in)
- path_update(&ribs[0], peer, asp, &prefix, prefixlen);
-
- /* input filter */
- if (rde_filter(&fasp, rules_l, peer, asp, &prefix, prefixlen,
- peer, DIR_IN) == ACTION_DENY) {
- path_put(fasp);
- continue;
- }
+ rde_update_update(peer, asp, &prefix, prefixlen);
/* max prefix checker */
if (peer->conf.max_prefix &&
@@ -978,20 +963,9 @@ rde_update_dispatch(struct imsg *imsg)
log_peer_warnx(&peer->conf, "prefix limit reached");
rde_update_err(peer, ERR_CEASE, ERR_CEASE_MAX_PREFIX,
NULL, 0);
- path_put(fasp);
goto done;
}
- if (fasp == NULL)
- fasp = asp;
-
- rde_update_log("update", peer, &fasp->nexthop->exit_nexthop,
- &prefix, prefixlen);
- path_update(&ribs[1], peer, fasp, &prefix, prefixlen);
-
- /* free modified aspath */
- if (fasp != asp)
- path_put(fasp);
}
/* add MP_REACH_NLRI if available */
@@ -1053,19 +1027,8 @@ rde_update_dispatch(struct imsg *imsg)
mpp += pos;
mplen -= pos;
- peer->prefix_rcvd_update++;
- /* add original path to the Adj-RIB-In */
- if (peer->conf.softreconfig_in)
- path_update(&ribs[0], peer, asp,
- &prefix, prefixlen);
-
- /* input filter */
- if (rde_filter(&fasp, rules_l, peer, asp,
- &prefix, prefixlen, peer, DIR_IN) ==
- ACTION_DENY) {
- path_put(fasp);
- continue;
- }
+ rde_update_update(peer, asp, &prefix,
+ prefixlen);
/* max prefix checker */
if (peer->conf.max_prefix &&
@@ -1074,22 +1037,9 @@ rde_update_dispatch(struct imsg *imsg)
"prefix limit reached");
rde_update_err(peer, ERR_CEASE,
ERR_CEASE_MAX_PREFIX, NULL, 0);
- path_put(fasp);
goto done;
}
- if (fasp == NULL)
- fasp = asp;
-
- rde_update_log("update", peer,
- &asp->nexthop->exit_nexthop,
- &prefix, prefixlen);
- path_update(&ribs[1], peer, fasp, &prefix,
- prefixlen);
-
- /* free modified aspath */
- if (fasp != asp)
- path_put(fasp);
}
break;
default:
@@ -1112,6 +1062,55 @@ done:
return (error);
}
+void
+rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
+ struct bgpd_addr *prefix, u_int8_t prefixlen)
+{
+ struct rde_aspath *fasp;
+ int r = 0;
+
+ peer->prefix_rcvd_update++;
+ /* add original path to the Adj-RIB-In */
+ if (peer->conf.softreconfig_in)
+ r += path_update(&ribs[0], peer, asp, prefix, prefixlen);
+
+ /* input filter */
+ if (rde_filter(&fasp, rules_l, peer, asp, prefix, prefixlen,
+ peer, DIR_IN) == ACTION_DENY)
+ goto done;
+
+ if (fasp == NULL)
+ fasp = asp;
+
+ rde_update_log("update", peer, &fasp->nexthop->exit_nexthop,
+ prefix, prefixlen);
+ r += path_update(&ribs[1], peer, fasp, prefix, prefixlen);
+
+done:
+ /* free modified aspath */
+ if (fasp != asp)
+ path_put(fasp);
+
+ if (r)
+ peer->prefix_cnt++;
+}
+
+void
+rde_update_withdraw(struct rde_peer *peer, struct bgpd_addr *prefix,
+ u_int8_t prefixlen)
+{
+ int r = 0;
+
+ peer->prefix_rcvd_withdraw++;
+ rde_update_log("withdraw", peer, NULL, prefix, prefixlen);
+
+ r += prefix_remove(&ribs[1], peer, prefix, prefixlen, 0);
+ r += prefix_remove(&ribs[0], peer, prefix, prefixlen, 0);
+
+ if (r)
+ peer->prefix_cnt--;
+}
+
/*
* BGP UPDATE parser functions
*/
@@ -1709,7 +1708,6 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags)
rib.med = asp->med;
rib.prefix_cnt = asp->prefix_cnt;
rib.active_cnt = asp->active_cnt;
- rib.rib_cnt = asp->rib_cnt;
strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr));
memcpy(&rib.remote_addr, &asp->peer->remote_addr,
sizeof(rib.remote_addr));
@@ -2609,6 +2607,7 @@ peer_down(u_int32_t id)
path_remove(asp);
}
LIST_INIT(&peer->path_h);
+ peer->prefix_cnt = 0;
/* Deletions are performed in path_remove() */
rde_send_pftable_commit();
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 7f2905db780..c84f7ecf880 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.109 2009/05/21 15:47:03 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.110 2009/05/27 06:58:15 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -67,7 +67,6 @@ struct rde_peer {
u_int64_t prefix_sent_update;
u_int64_t prefix_sent_withdraw;
u_int32_t prefix_cnt; /* # of prefixes */
- u_int32_t rib_cnt; /* # of p. in Adj-RIB-In */
u_int32_t remote_bgpid; /* host byte order! */
u_int32_t up_pcnt;
u_int32_t up_acnt;
@@ -184,7 +183,6 @@ struct rde_aspath {
u_int32_t weight; /* low prio lpref */
u_int32_t prefix_cnt; /* # of prefixes */
u_int32_t active_cnt; /* # of active prefixes */
- u_int32_t rib_cnt; /* # of p. in Adj-RIB-In */
u_int32_t flags; /* internally used */
u_int16_t rtlabelid; /* route label id */
u_int16_t pftableid; /* pf table id */
@@ -355,7 +353,7 @@ void rib_dump_r(struct rib_context *);
void path_init(u_int32_t);
void path_shutdown(void);
-void path_update(struct rib *, struct rde_peer *,
+int path_update(struct rib *, struct rde_peer *,
struct rde_aspath *, struct bgpd_addr *, int);
int path_compare(struct rde_aspath *, struct rde_aspath *);
struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *);
@@ -371,10 +369,10 @@ int prefix_compare(const struct bgpd_addr *,
const struct bgpd_addr *, int);
struct prefix *prefix_get(struct rib *, struct rde_peer *,
struct bgpd_addr *, int, u_int32_t);
-void prefix_add(struct rib *, struct rde_aspath *,
+int prefix_add(struct rib *, struct rde_aspath *,
struct bgpd_addr *, int);
void prefix_move(struct rde_aspath *, struct prefix *);
-void prefix_remove(struct rib *, struct rde_peer *,
+int prefix_remove(struct rib *, struct rde_peer *,
struct bgpd_addr *, int, u_int32_t);
int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t);
struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *,
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 5ee64aedbfb..a4bd6b4a3f7 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.102 2009/05/21 15:47:03 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.103 2009/05/27 06:58:15 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -292,12 +292,9 @@ done:
}
/* used to bump correct prefix counters */
-#define PREFIX_COUNT(x, id, op) \
- do { \
- if (id == 1) \
- (x)->prefix_cnt += (op); \
- else \
- (x)->rib_cnt += (op); \
+#define PREFIX_COUNT(x, op) \
+ do { \
+ (x)->prefix_cnt += (op); \
} while (0)
/* path specific functions */
@@ -340,7 +337,7 @@ path_shutdown(void)
free(pathtable.path_hashtbl);
}
-void
+int
path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp,
struct bgpd_addr *prefix, int prefixlen)
{
@@ -359,7 +356,7 @@ path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp,
if (path_compare(nasp, p->aspath) == 0) {
/* no change, update last change */
p->lastchange = time(NULL);
- return;
+ return (0);
}
}
@@ -378,7 +375,8 @@ path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp,
if (p != NULL)
prefix_move(asp, p);
else
- prefix_add(rib, asp, prefix, prefixlen);
+ return (prefix_add(rib, asp, prefix, prefixlen));
+ return (0);
}
int
@@ -466,8 +464,7 @@ void
path_destroy(struct rde_aspath *asp)
{
/* path_destroy can only unlink and free empty rde_aspath */
- if (asp->prefix_cnt != 0 || asp->active_cnt != 0 ||
- asp->rib_cnt != 0)
+ if (asp->prefix_cnt != 0 || asp->active_cnt != 0)
log_warnx("path_destroy: prefix count out of sync");
nexthop_unlink(asp);
@@ -644,7 +641,7 @@ prefix_get(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix,
/*
* Adds or updates a prefix.
*/
-void
+int
prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix,
int prefixlen)
@@ -660,13 +657,14 @@ prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix,
if (p == NULL) {
p = prefix_alloc();
prefix_link(p, re, asp);
+ return (1);
} else {
if (p->aspath != asp) {
/* prefix belongs to a different aspath so move */
prefix_move(asp, p);
- return;
- }
- p->lastchange = time(NULL);
+ } else
+ p->lastchange = time(NULL);
+ return (0);
}
}
@@ -692,7 +690,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
/* add to new as path */
LIST_INSERT_HEAD(&asp->prefix_h, np, path_l);
- PREFIX_COUNT(asp, p->rib->rib->id, 1);
+ PREFIX_COUNT(asp, 1);
/*
* no need to update the peer prefix count because we are only moving
* the prefix without changing the peer.
@@ -712,7 +710,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
/* remove old prefix node */
oasp = p->aspath;
LIST_REMOVE(p, path_l);
- PREFIX_COUNT(oasp, p->rib->rib->id, -1);
+ PREFIX_COUNT(oasp, -1);
/* as before peer count needs no update because of move */
/* destroy all references to other objects and free the old prefix */
@@ -730,7 +728,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
* Removes a prefix from all lists. If the parent objects -- path or
* pt_entry -- become empty remove them too.
*/
-void
+int
prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix,
int prefixlen, u_int32_t flags)
{
@@ -740,11 +738,11 @@ prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix,
re = rib_get(rib, prefix, prefixlen);
if (re == NULL) /* Got a dummy withdrawn request */
- return;
+ return (0);
p = prefix_bypeer(re, peer, flags);
if (p == NULL) /* Got a dummy withdrawn request. */
- return;
+ return (0);
asp = p->aspath;
@@ -761,6 +759,8 @@ prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix,
rib_remove(re);
if (path_empty(asp))
path_destroy(asp);
+
+ return (1);
}
/* dump a prefix into specified buffer */
@@ -895,8 +895,7 @@ static void
prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp)
{
LIST_INSERT_HEAD(&asp->prefix_h, pref, path_l);
- PREFIX_COUNT(asp, re->rib->id, 1);
- PREFIX_COUNT(asp->peer, re->rib->id, 1);
+ PREFIX_COUNT(asp, 1);
pref->aspath = asp;
pref->rib = re;
@@ -921,8 +920,7 @@ prefix_unlink(struct prefix *pref)
}
LIST_REMOVE(pref, path_l);
- PREFIX_COUNT(pref->aspath, pref->rib->rib->id, -1);
- PREFIX_COUNT(pref->aspath->peer, pref->rib->rib->id, -1);
+ PREFIX_COUNT(pref->aspath, -1);
pt_unref(pref->prefix);
if (pt_empty(pref->prefix))