summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>1999-03-04 18:36:18 +0000
committerMartin Mares <mj@ucw.cz>1999-03-04 18:36:18 +0000
commite16155ae4aaee5d9ba7b6940f8312b36707718e4 (patch)
treede2bbd930af01a8620871688e8ba36ba9d0111be /sysdep/unix
parent2253c9e239253d2094b4b1cabd97d296af885afb (diff)
KRT: Implemented asynchronous route / interface state notifications
(via Netlink). Tweaked kernel synchronization rules a bit. Discovered locking bug in kernel Netlink :-) Future plans: Hunt all the bugs and solve all the FIXME's.
Diffstat (limited to 'sysdep/unix')
-rw-r--r--sysdep/unix/krt-set.c3
-rw-r--r--sysdep/unix/krt.c38
-rw-r--r--sysdep/unix/krt.h7
3 files changed, 46 insertions, 2 deletions
diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c
index dae01f46..2165255e 100644
--- a/sysdep/unix/krt-set.c
+++ b/sysdep/unix/krt-set.c
@@ -43,7 +43,7 @@ krt_capable_op(rte *e)
rta *a = e->attrs;
#ifdef CONFIG_AUTO_ROUTES
- if (a->dest == RTD_ROUTER && a->source == RTS_DEVICE)
+ if (a->source == RTS_DEVICE)
return 0;
#endif
return krt_capable(e);
@@ -115,6 +115,7 @@ krt_add_route(rte *new)
void
krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
{
+ /* FIXME: Fold remove/add route here */
if (old)
krt_remove_route(old);
if (new)
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 5fbd52c7..aa875ccf 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -78,6 +78,7 @@ krt_got_route(struct krt_proto *p, rte *e)
{
rte *old;
net *net = e->net;
+ int src = e->u.krt_sync.src;
int verdict;
if (net->n.flags)
@@ -97,7 +98,7 @@ krt_got_route(struct krt_proto *p, rte *e)
else
verdict = KRF_UPDATE;
}
- else if (KRT_CF->learn && !net->routes)
+ else if (KRT_CF->learn && !net->routes && (src == KRT_SRC_ALIEN || src < 0))
verdict = KRF_LEARN;
else
verdict = KRF_DELETE;
@@ -188,6 +189,41 @@ krt_prune(struct krt_proto *p)
FIB_WALK_END;
}
+void
+krt_got_route_async(struct krt_proto *p, rte *e, int new)
+{
+ net *net = e->net;
+ rte *old = net->routes;
+ int src = e->u.krt_sync.src;
+
+ switch (src)
+ {
+ case KRT_SRC_BIRD:
+ ASSERT(0);
+ case KRT_SRC_REDIRECT:
+ DBG("It's a redirect, kill him! Kill! Kill!\n");
+ krt_set_notify(&p->p, net, NULL, e);
+ break;
+ default: /* Alien or unspecified */
+ if (KRT_CF->learn && new)
+ {
+ /*
+ * FIXME: This is limited to one inherited route per destination as we
+ * use single protocol for all inherited routes. Probably leave it
+ * as-is (and document it :)), because the correct solution is to
+ * multiple kernel tables anyway.
+ */
+ DBG("Learning\n");
+ rte_update(net, &p->p, e);
+ }
+ else
+ {
+ DBG("Discarding\n");
+ rte_update(net, &p->p, NULL);
+ }
+ }
+}
+
/*
* Periodic scanning
*/
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 1c59799f..02814c68 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -52,6 +52,13 @@ extern struct proto_config *cf_krt;
#define KRT_CF ((struct krt_config *)p->p.cf)
void krt_got_route(struct krt_proto *p, struct rte *e);
+void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
+
+/* Values for rte->u.krt_sync.src */
+#define KRT_SRC_UNKNOWN -1 /* Nobody knows */
+#define KRT_SRC_BIRD 0 /* Our route (not passed in async mode) */
+#define KRT_SRC_REDIRECT 1 /* Redirect route, delete it */
+#define KRT_SRC_ALIEN 2 /* Route installed by someone else */
/* krt-scan.c */