summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-02-27 16:00:07 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2010-02-27 16:00:07 +0100
commit53434e44a95fe9334f4bdf5e0da987929addffb1 (patch)
tree75317dd53e6059b7c6fe0941312adc2e317c46eb
parent3075824dbd4bb654e98614dfd9992ceec0428beb (diff)
downloadbird-53434e44a95fe9334f4bdf5e0da987929addffb1.tar
bird-53434e44a95fe9334f4bdf5e0da987929addffb1.zip
Better flushing of interfaces.
When device protocol goes down, interfaces should be flushed asynchronously (in the same way like routes from protocols are flushed), when protocol goes to DOWN/HUNGRY. This fixes the problem with static routes staying in kernel routing table after BIRD shutdown.
-rw-r--r--nest/iface.c9
-rw-r--r--nest/iface.h3
-rw-r--r--nest/proto.c7
-rw-r--r--proto/static/static.c9
-rw-r--r--sysdep/unix/krt.c9
5 files changed, 23 insertions, 14 deletions
diff --git a/nest/iface.c b/nest/iface.c
index 5e88b21..82dead3 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -336,6 +336,15 @@ if_end_update(void)
}
}
+void
+if_flush_ifaces(struct proto *p)
+{
+ if (p->debug & D_EVENTS)
+ log(L_TRACE "%s: Flushing interfaces", p->name);
+ if_start_update();
+ if_end_update();
+}
+
/**
* if_feed_baby - advertise interfaces to a new protocol
* @p: protocol to feed
diff --git a/nest/iface.h b/nest/iface.h
index 02129ac..8fc2567 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -75,8 +75,9 @@ struct iface *if_update(struct iface *);
struct ifa *ifa_update(struct ifa *);
void ifa_delete(struct ifa *);
void if_start_update(void);
-void if_end_update(void);
void if_end_partial_update(struct iface *);
+void if_end_update(void);
+void if_flush_ifaces(struct proto *p);
void if_feed_baby(struct proto *);
struct iface *if_find_by_index(unsigned);
struct iface *if_find_by_name(char *);
diff --git a/nest/proto.c b/nest/proto.c
index db6bf9b..78fca99 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -740,6 +740,8 @@ proto_notify_state(struct proto *p, unsigned ps)
}
}
+extern struct protocol proto_unix_iface;
+
static void
proto_flush_all(void *unused UNUSED)
{
@@ -748,6 +750,11 @@ proto_flush_all(void *unused UNUSED)
rt_prune_all();
while ((p = HEAD(flush_proto_list))->n.next)
{
+ /* This will flush interfaces in the same manner
+ like rt_prune_all() flushes routes */
+ if (p->proto == &proto_unix_iface)
+ if_flush_ifaces(p);
+
DBG("Flushing protocol %s\n", p->name);
p->core_state = FS_HUNGRY;
proto_relink(p);
diff --git a/proto/static/static.c b/proto/static/static.c
index c71d1da..9308c59 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -125,11 +125,12 @@ static_shutdown(struct proto *p)
struct static_config *c = (void *) p->cf;
struct static_route *r;
- DBG("Static: prepare for landing!\n");
+ /* Just reset the flag, the routes will be flushed by the nest */
WALK_LIST(r, c->iface_routes)
- static_remove(p, r);
+ r->installed = 0;
WALK_LIST(r, c->other_routes)
- static_remove(p, r);
+ r->installed = 0;
+
return PS_DOWN;
}
@@ -294,7 +295,7 @@ static_show_rt(struct static_route *r)
switch (r->dest)
{
case RTD_ROUTER: bsprintf(via, "via %I", r->via); break;
- case RTD_DEVICE: bsprintf(via, "to %s", r->if_name); break;
+ case RTD_DEVICE: bsprintf(via, "dev %s", r->if_name); break;
case RTD_BLACKHOLE: bsprintf(via, "blackhole"); break;
case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 47b9621..c8887b7 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -139,15 +139,6 @@ kif_shutdown(struct proto *P)
krt_if_shutdown(p);
kif_proto = NULL;
- if_start_update(); /* Remove all interfaces */
- if_end_update();
- /*
- * FIXME: Is it really a good idea? It causes routes to be flushed,
- * but at the same time it avoids sending of these deletions to the kernel,
- * because krt thinks the kernel itself has already removed the route
- * when downing the interface. Sad.
- */
-
return PS_DOWN;
}