summaryrefslogtreecommitdiffstats
path: root/babeld/source.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
commite2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch)
treef0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /babeld/source.c
parentInitial commit. (diff)
downloadfrr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz
frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'babeld/source.c')
-rw-r--r--babeld/source.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/babeld/source.c b/babeld/source.c
new file mode 100644
index 0000000..049fa32
--- /dev/null
+++ b/babeld/source.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: MIT
+/*
+Copyright (c) 2007, 2008 by Juliusz Chroboczek
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "babel_main.h"
+#include "babeld.h"
+#include "util.h"
+#include "source.h"
+#include "babel_interface.h"
+#include "route.h"
+#include "babel_errors.h"
+
+struct source *srcs = NULL;
+
+struct source*
+find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
+ int create, unsigned short seqno)
+{
+ struct source *src;
+
+ for(src = srcs; src; src = src->next) {
+ /* This should really be a hash table. For now, check the
+ last byte first. */
+ if(src->id[7] != id[7])
+ continue;
+ if(memcmp(src->id, id, 8) != 0)
+ continue;
+ if(src->plen != plen)
+ continue;
+ if(memcmp(src->prefix, p, 16) == 0)
+ return src;
+ }
+
+ if(!create)
+ return NULL;
+
+ src = malloc(sizeof(struct source));
+ if(src == NULL) {
+ flog_err(EC_BABEL_MEMORY, "malloc(source): %s", safe_strerror(errno));
+ return NULL;
+ }
+
+ memcpy(src->id, id, 8);
+ memcpy(src->prefix, p, 16);
+ src->plen = 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)
+{
+ if(src->route_count > 0)
+ /* The source is in use by a route. */
+ return 0;
+
+ if(srcs == src) {
+ srcs = src->next;
+ } else {
+ struct source *previous = srcs;
+ while(previous->next != src)
+ previous = previous->next;
+ previous->next = src->next;
+ }
+
+ free(src);
+ return 1;
+}
+
+void
+update_source(struct source *src,
+ unsigned short seqno, unsigned short metric)
+{
+ 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)) {
+ src->seqno = seqno;
+ src->metric = metric;
+ }
+ src->time = babel_now.tv_sec;
+}
+
+void
+expire_sources(void)
+{
+ struct source *src;
+
+ src = srcs;
+ while(src) {
+ if(src->time > babel_now.tv_sec)
+ /* clock stepped */
+ src->time = babel_now.tv_sec;
+ if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) {
+ struct source *old = src;
+ src = src->next;
+ flush_source(old);
+ continue;
+ }
+ 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);
+ }
+}