summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nest/route.h1
-rw-r--r--nest/rt-fib.c1
-rw-r--r--nest/rt-table.c2
-rw-r--r--sysdep/unix/krt.c175
-rw-r--r--sysdep/unix/krt.h10
5 files changed, 77 insertions, 112 deletions
diff --git a/nest/route.h b/nest/route.h
index eaaa5c3f..d2a07f09 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -37,7 +37,6 @@ struct cli;
struct fib_node {
struct fib_node *next; /* Next in hash chain */
struct fib_iterator *readers; /* List of readers of this node */
- byte flags; /* User-defined, will be removed */
net_addr addr[0];
};
diff --git a/nest/rt-fib.c b/nest/rt-fib.c
index a8800b65..76a86e6e 100644
--- a/nest/rt-fib.c
+++ b/nest/rt-fib.c
@@ -327,7 +327,6 @@ fib_get(struct fib *f, const net_addr *a)
struct fib_node *e = fib_user_to_node(f, b);
e->readers = NULL;
- e->flags = 0;
fib_insert(f, a, e);
memset(b, 0, f->node_offset);
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 4adc278e..f95afccd 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1687,7 +1687,7 @@ rte_dump(rte *e)
{
net *n = e->net;
debug("%-1N ", n->n.addr);
- debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
+ debug("PF=%02x pref=%d ", e->pflags, e->pref);
rta_dump(e->attrs);
if (e->attrs->src->proto->proto->dump_attrs)
e->attrs->src->proto->proto->dump_attrs(e);
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 84207251..42dd12f6 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -625,19 +625,17 @@ krt_same_dest(rte *k, rte *e)
void
krt_got_route(struct krt_proto *p, rte *e)
{
- net *net = e->net;
- int verdict;
+ rte *new = NULL, *rt_free = NULL;
+ net *n = e->net;
#ifdef KRT_ALLOW_LEARN
switch (e->u.krt.src)
{
case KRT_SRC_KERNEL:
- verdict = KRF_IGNORE;
- goto sentenced;
+ goto ignore;
case KRT_SRC_REDIRECT:
- verdict = KRF_DELETE;
- goto sentenced;
+ goto delete;
case KRT_SRC_ALIEN:
if (KRT_CF->learn)
@@ -652,58 +650,68 @@ krt_got_route(struct krt_proto *p, rte *e)
#endif
/* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
- if (net->n.flags & KRF_VERDICT_MASK)
- {
- /* Route to this destination was already seen. Strange, but it happens... */
- krt_trace_in(p, e, "already seen");
- rte_free(e);
- return;
- }
+ /* We wait for the initial feed to have correct installed state */
if (!p->ready)
- {
- /* We wait for the initial feed to have correct installed state */
- verdict = KRF_IGNORE;
- goto sentenced;
- }
+ goto ignore;
- if (krt_is_installed(p, net))
- {
- rte *new, *rt_free;
+ if (!krt_is_installed(p, n))
+ goto delete;
- new = krt_export_net(p, net, &rt_free);
+ new = krt_export_net(p, n, &rt_free);
- /* TODO: There also may be changes in route eattrs, we ignore that for now. */
+ /* Rejected by filters */
+ if (!new)
+ goto delete;
- if (!new)
- verdict = KRF_DELETE;
- else if (!bmap_test(&p->sync_map, new->id) || !krt_same_dest(e, new))
- verdict = KRF_UPDATE;
- else
- verdict = KRF_SEEN;
+ /* Route to this destination was already seen. Strange, but it happens... */
+ if (bmap_test(&p->seen_map, new->id))
+ goto aseen;
- if (rt_free)
- rte_free(rt_free);
+ /* Mark route as seen */
+ bmap_set(&p->seen_map, new->id);
- lp_flush(krt_filter_lp);
- }
- else
- verdict = KRF_DELETE;
+ /* TODO: There also may be changes in route eattrs, we ignore that for now. */
+ if (!bmap_test(&p->sync_map, new->id) || !krt_same_dest(e, new))
+ goto update;
- sentenced:
- krt_trace_in(p, e, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict]);
- net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict;
- if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
- {
- /* Get a cached copy of attributes and temporarily link the route */
- rta *a = e->attrs;
- a->source = RTS_DUMMY;
- e->attrs = rta_lookup(a);
- e->next = net->routes;
- net->routes = e;
- }
- else
- rte_free(e);
+ goto seen;
+
+seen:
+ krt_trace_in(p, e, "seen");
+ goto done;
+
+aseen:
+ krt_trace_in(p, e, "already seen");
+ goto done;
+
+ignore:
+ krt_trace_in(p, e, "ignored");
+ goto done;
+
+update:
+ krt_trace_in(p, new, "updating");
+ krt_replace_rte(p, n, new, e);
+ goto done;
+
+delete:
+ krt_trace_in(p, e, "deleting");
+ krt_replace_rte(p, n, NULL, e);
+ goto done;
+
+done:
+ rte_free(e);
+
+ if (rt_free)
+ rte_free(rt_free);
+
+ lp_flush(krt_filter_lp);
+}
+
+static void
+krt_init_scan(struct krt_proto *p)
+{
+ bmap_reset(&p->seen_map, 1024);
}
static void
@@ -713,59 +721,24 @@ krt_prune(struct krt_proto *p)
KRT_TRACE(p, D_EVENTS, "Pruning table %s", t->name);
FIB_WALK(&t->fib, net, n)
+ {
+ if (p->ready && krt_is_installed(p, n) && !bmap_test(&p->seen_map, n->routes->id))
{
- int verdict = n->n.flags & KRF_VERDICT_MASK;
- rte *new, *old, *rt_free = NULL;
+ rte *rt_free = NULL;
+ rte *new = krt_export_net(p, n, &rt_free);
- if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
- {
- /* Get a dummy route from krt_got_route() */
- old = n->routes;
- n->routes = old->next;
- }
- else
- old = NULL;
-
- if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
- {
- /* We have to run export filter to get proper 'new' route */
- new = krt_export_net(p, n, &rt_free);
-
- if (!new)
- verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
- }
- else
- new = NULL;
-
- switch (verdict)
- {
- case KRF_CREATE:
- krt_trace_in(p, new, "reinstalling");
- krt_replace_rte(p, n, new, NULL);
- break;
- case KRF_SEEN:
- case KRF_IGNORE:
- /* Nothing happens */
- break;
- case KRF_UPDATE:
- krt_trace_in(p, new, "updating");
- krt_replace_rte(p, n, new, old);
- break;
- case KRF_DELETE:
- krt_trace_in(p, old, "deleting");
- krt_replace_rte(p, n, NULL, old);
- break;
- default:
- bug("krt_prune: invalid route status");
- }
+ if (new)
+ {
+ krt_trace_in(p, new, "installing");
+ krt_replace_rte(p, n, new, NULL);
+ }
- if (old)
- rte_free(old);
if (rt_free)
rte_free(rt_free);
+
lp_flush(krt_filter_lp);
- n->n.flags &= ~KRF_VERDICT_MASK;
}
+ }
FIB_WALK_END;
#ifdef KRT_ALLOW_LEARN
@@ -823,6 +796,7 @@ static void
krt_scan(timer *t UNUSED)
{
struct krt_proto *p;
+ node *n;
kif_force_scan();
@@ -830,14 +804,13 @@ krt_scan(timer *t UNUSED)
p = SKIP_BACK(struct krt_proto, krt_node, HEAD(krt_proto_list));
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
+ WALK_LIST2(p, n, krt_proto_list, krt_node)
+ krt_init_scan(p);
+
krt_do_scan(NULL);
- void *q;
- WALK_LIST(q, krt_proto_list)
- {
- p = SKIP_BACK(struct krt_proto, krt_node, q);
+ WALK_LIST2(p, n, krt_proto_list, krt_node)
krt_prune(p);
- }
}
static void
@@ -879,6 +852,7 @@ krt_scan(timer *t)
kif_force_scan();
KRT_TRACE(p, D_EVENTS, "Scanning routing table");
+ krt_init_scan(p);
krt_do_scan(p);
krt_prune(p);
}
@@ -1095,6 +1069,7 @@ krt_start(struct proto *P)
}
bmap_init(&p->sync_map, p->p.pool, 1024);
+ bmap_init(&p->seen_map, p->p.pool, 1024);
add_tail(&krt_proto_list, &p->krt_node);
#ifdef KRT_ALLOW_LEARN
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index c5b565f5..6066f2f1 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -19,15 +19,6 @@ struct kif_proto;
#include "sysdep/config.h"
#include CONFIG_INCLUDE_KRTSYS_H
-/* Flags stored in net->n.flags, rest are in nest/route.h */
-
-#define KRF_VERDICT_MASK 0x0f
-#define KRF_CREATE 0 /* Not seen in kernel table */
-#define KRF_SEEN 1 /* Seen in kernel table during last scan */
-#define KRF_UPDATE 2 /* Need to update this entry */
-#define KRF_DELETE 3 /* Should be deleted */
-#define KRF_IGNORE 4 /* To be ignored */
-
#define KRT_DEFAULT_ECMP_LIMIT 16
#define EA_KRT_SOURCE EA_CODE(PROTOCOL_KERNEL, 0)
@@ -66,6 +57,7 @@ struct krt_proto {
#endif
struct bmap sync_map; /* Keeps track which exported routes were successfully written to kernel */
+ struct bmap seen_map; /* Routes seen during last periodic scan */
node krt_node; /* Node in krt_proto_list */
byte af; /* Kernel address family (AF_*) */
byte ready; /* Initial feed has been finished */