summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/rde_rib.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2008-11-21 17:41:23 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2008-11-21 17:41:23 +0000
commit776465e20b9519ed27260d43d3197d36725f5b9c (patch)
tree7393cfbc932bc94a85894354d266b1ca3d530366 /usr.sbin/bgpd/rde_rib.c
parent76896b893429a73b9185282e75299828ce0ce9df (diff)
Track nexthops when the underlying route is changing. Until now true nexthops
were only resolved when they were added. This calls for troubles if something like ospfd starts to change the underlying routes. Tested by gollo@, OK henning@
Diffstat (limited to 'usr.sbin/bgpd/rde_rib.c')
-rw-r--r--usr.sbin/bgpd/rde_rib.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 609660f69c4..6e3410cb31a 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.96 2007/06/01 04:17:30 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.97 2008/11/21 17:41:22 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -616,7 +616,8 @@ prefix_bypeer(struct pt_entry *pte, struct rde_peer *peer, u_int32_t flags)
}
void
-prefix_updateall(struct rde_aspath *asp, enum nexthop_state state)
+prefix_updateall(struct rde_aspath *asp, enum nexthop_state state,
+ enum nexthop_state oldstate)
{
struct prefix *p;
@@ -632,6 +633,18 @@ prefix_updateall(struct rde_aspath *asp, enum nexthop_state state)
if (!(p->flags & F_LOCAL))
continue;
+ if (oldstate == state && state == NEXTHOP_REACH) {
+ /*
+ * The state of the nexthop did not change. The only
+ * thing that may have changed is the true_nexthop
+ * or other internal infos. This will not change
+ * the routing decision so shortcut here.
+ */
+ if (p == p->prefix->active)
+ rde_send_kroute(p, NULL);
+ continue;
+ }
+
/* redo the route decision */
LIST_REMOVE(p, prefix_l);
/*
@@ -817,6 +830,7 @@ nexthop_update(struct kroute_nexthop *msg)
{
struct nexthop *nh;
struct rde_aspath *asp;
+ enum nexthop_state oldstate;
nh = nexthop_lookup(&msg->nexthop);
if (nh == NULL) {
@@ -825,15 +839,16 @@ nexthop_update(struct kroute_nexthop *msg)
return;
}
+ if (nexthop_delete(nh))
+ /* nexthop no longer used */
+ return;
+
+ oldstate = nh->state;
if (msg->valid)
nh->state = NEXTHOP_REACH;
else
nh->state = NEXTHOP_UNREACH;
- if (nexthop_delete(nh))
- /* nexthop no longer used */
- return;
-
if (msg->connected) {
nh->flags |= NEXTHOP_CONNECTED;
memcpy(&nh->true_nexthop, &nh->exit_nexthop,
@@ -866,7 +881,7 @@ nexthop_update(struct kroute_nexthop *msg)
return;
LIST_FOREACH(asp, &nh->path_h, nexthop_l) {
- prefix_updateall(asp, nh->state);
+ prefix_updateall(asp, nh->state, oldstate);
}
}