summaryrefslogtreecommitdiff
path: root/babeld/source.c
diff options
context:
space:
mode:
Diffstat (limited to 'babeld/source.c')
-rw-r--r--babeld/source.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/babeld/source.c b/babeld/source.c
index cc4ed445..772112d4 100644
--- a/babeld/source.c
+++ b/babeld/source.c
@@ -63,8 +63,10 @@ find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
continue;
if(memcmp(src->id, id, 8) != 0)
continue;
- if(source_match(src, p, plen))
- return src;
+ if(src->plen != plen)
+ continue;
+ if(memcmp(src->prefix, p, 16) == 0)
+ return src;
}
if(!create)
@@ -82,18 +84,32 @@ find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
src->seqno = seqno;
src->metric = INFINITY;
src->time = babel_now.tv_sec;
+ src->route_count = 0;
src->next = srcs;
srcs = src;
return src;
}
+struct source *
+retain_source(struct source *src)
+{
+ assert(src->route_count < 0xffff);
+ src->route_count++;
+ return src;
+}
+
+void
+release_source(struct source *src)
+{
+ assert(src->route_count > 0);
+ src->route_count--;
+}
+
int
flush_source(struct source *src)
{
- /* This is absolutely horrible -- it makes expire_sources quadratic.
- But it's not called very often. */
-
- if (babel_route_get_by_source(src) != NULL)
+ if(src->route_count > 0)
+ /* The source is in use by a route. */
return 0;
if(srcs == src) {
@@ -109,19 +125,6 @@ flush_source(struct source *src)
return 1;
}
-int
-source_match(struct source *src,
- const unsigned char *p, unsigned char plen)
-{
- if(src->plen != plen)
- return 0;
- if(src->prefix[15] != p[15])
- return 0;
- if(memcmp(src->prefix, p, 16) != 0)
- return 0;
- return 1;
-}
-
void
update_source(struct source *src,
unsigned short seqno, unsigned short metric)
@@ -129,6 +132,10 @@ update_source(struct source *src,
if(metric >= INFINITY)
return;
+ /* If a source is expired, pretend that it doesn't exist and update
+ it unconditionally. This makes ensures that old data will
+ eventually be overridden, and prevents us from getting stuck if
+ a router loses its sequence number. */
if(src->time < babel_now.tv_sec - SOURCE_GC_TIME ||
seqno_compare(src->seqno, seqno) < 0 ||
(src->seqno == seqno && src->metric > metric)) {
@@ -157,3 +164,17 @@ expire_sources()
src = src->next;
}
}
+
+void
+check_sources_released(void)
+{
+ struct source *src;
+
+ for(src = srcs; src; src = src->next) {
+ if(src->route_count != 0)
+ fprintf(stderr, "Warning: source %s %s has refcount %d.\n",
+ format_eui64(src->id),
+ format_prefix(src->prefix, src->plen),
+ (int)src->route_count);
+ }
+}