summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ouroboros/rib.h5
-rw-r--r--src/ipcpd/normal/pol/link_state.c109
-rw-r--r--src/lib/rib.c70
3 files changed, 132 insertions, 52 deletions
diff --git a/include/ouroboros/rib.h b/include/ouroboros/rib.h
index fda36ead..5a3d66dc 100644
--- a/include/ouroboros/rib.h
+++ b/include/ouroboros/rib.h
@@ -25,6 +25,9 @@
#define RIB_PATH_LEN 128
+#include <sys/stat.h>
+#include <sys/types.h>
+
struct rib;
struct rib_ops {
@@ -32,6 +35,8 @@ struct rib_ops {
char * buf,
size_t len);
int (* readdir)(char *** entries);
+ int (* getattr)(const char * path,
+ struct stat * st);
};
int rib_init(const char * prefix);
diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c
index 520e2952..179a3448 100644
--- a/src/ipcpd/normal/pol/link_state.c
+++ b/src/ipcpd/normal/pol/link_state.c
@@ -52,6 +52,7 @@
#define RECALC_TIME 4
#define LS_UPDATE_TIME 15
#define LS_TIMEO 60
+#define LS_ENTRY_SIZE 78
#define LSDB "lsdb"
#ifndef CLOCK_REALTIME_COARSE
@@ -131,51 +132,96 @@ static int str_adj(struct adjacency * adj,
size_t len)
{
char tmbuf[64];
+ char srcbuf[64];
+ char dstbuf[64];
struct tm * tm;
- if (len < 256)
+ if (len < LS_ENTRY_SIZE)
return -1;
tm = localtime(&adj->stamp);
- strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", tm);
+ strftime(tmbuf, sizeof(tmbuf), "%F %T", tm); /* 19 chars */
- sprintf(buf,
- "src: %" PRIu64 "\n"
- "dst: %" PRIu64 "\n"
- "upd: %s\n",
- adj->src,
- adj->dst,
- tmbuf);
+ sprintf(srcbuf, "%" PRIu64, adj->src);
+ sprintf(dstbuf, "%" PRIu64, adj->dst);
- return strlen(buf);
+ sprintf(buf, "src: %20s\ndst: %20s\nupd: %20s\n",
+ srcbuf, dstbuf, tmbuf);
+
+ return LS_ENTRY_SIZE;
}
-static int lsdb_read(const char * path,
- char * buf,
- size_t len)
+static struct adjacency * get_adj(const char * path)
{
struct list_head * p;
char entry[RIB_PATH_LEN + 1];
- pthread_rwlock_rdlock(&ls.db_lock);
-
- if (ls.db_len + ls.nbs_len == 0) {
- pthread_rwlock_unlock(&ls.db_lock);
- return -EPERM;
- }
+ assert(path);
list_for_each(p, &ls.db) {
struct adjacency * a = list_entry(p, struct adjacency, next);
sprintf(entry, "%" PRIu64 ".%" PRIu64, a->src, a->dst);
- if (strcmp(entry, path) == 0) {
- len = str_adj(a, buf, len);
- pthread_rwlock_unlock(&ls.db_lock);
- return len;
- }
+ if (strcmp(entry, path) == 0)
+ return a;
+ }
+
+ return NULL;
+}
+
+static int lsdb_getattr(const char * path,
+ struct stat * st)
+{
+ struct adjacency * adj;
+ struct timespec now;
+
+ clock_gettime(CLOCK_REALTIME_COARSE, &now);
+
+ pthread_rwlock_rdlock(&ls.db_lock);
+
+ adj = get_adj(path);
+ if (adj != NULL) {
+ st->st_mtime = adj->stamp;
+ st->st_size = LS_ENTRY_SIZE;
+ } else {
+ st->st_mtime = now.tv_sec;
+ st->st_size = 0;
}
+ st->st_mode = S_IFREG | 0755;
+ st->st_nlink = 1;
+ st->st_uid = getuid();
+ st->st_gid = getgid();
+
+ pthread_rwlock_unlock(&ls.db_lock);
+
+ return 0;
+}
+
+static int lsdb_read(const char * path,
+ char * buf,
+ size_t len)
+{
+ struct adjacency * a;
+ int size;
+
+ pthread_rwlock_rdlock(&ls.db_lock);
+
+ if (ls.db_len + ls.nbs_len == 0)
+ goto fail;
+
+ a = get_adj(path);
+ if (a == NULL)
+ goto fail;
+
+ size = str_adj(a, buf, len);
+ if (size < 0)
+ goto fail;
+
pthread_rwlock_unlock(&ls.db_lock);
+ return size;
+ fail:
+ pthread_rwlock_unlock(&ls.db_lock);
return -1;
}
@@ -204,8 +250,8 @@ static int lsdb_readdir(char *** buf)
sprintf(entry, "%s%" PRIu64, str, nb->addr);
(*buf)[idx] = malloc(strlen(entry) + 1);
if ((*buf)[idx] == NULL) {
- while (--idx >= 0)
- free(*buf[idx]);
+ while (idx-- > 0)
+ free((*buf)[idx]);
free(buf);
pthread_rwlock_unlock(&ls.db_lock);
return -ENOMEM;
@@ -241,7 +287,8 @@ static int lsdb_readdir(char *** buf)
static struct rib_ops r_ops = {
.read = lsdb_read,
- .readdir = lsdb_readdir
+ .readdir = lsdb_readdir,
+ .getattr = lsdb_getattr
};
static int lsdb_add_nb(uint64_t addr,
@@ -801,13 +848,17 @@ int link_state_init(enum pol_routing pr)
if (pthread_create(&ls.listener, NULL, ls_conn_handle, NULL))
goto fail_pthread_create_listener;
+ if (rib_reg(LSDB, &r_ops))
+ goto fail_rib_reg;
+
ls.db_len = 0;
ls.nbs_len = 0;
- rib_reg(LSDB, &r_ops);
-
return 0;
+ fail_rib_reg:
+ pthread_cancel(ls.listener);
+ pthread_join(ls.listener, NULL);
fail_pthread_create_listener:
pthread_cancel(ls.lsreader);
pthread_join(ls.lsreader, NULL);
diff --git a/src/lib/rib.c b/src/lib/rib.c
index 5bb8c1c3..947226a9 100644
--- a/src/lib/rib.c
+++ b/src/lib/rib.c
@@ -29,6 +29,7 @@
#include <ouroboros/rib.h>
#include <ouroboros/utils.h>
+#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -155,9 +156,11 @@ static int rib_readdir(const char * path,
ssize_t i;
struct reg_comp * c;
c = list_entry(p, struct reg_comp, next);
- if (strcmp(path + 1, c->path) == 0)
- if (c->ops->readdir == NULL)
- break;
+
+ if (strcmp(path + 1, c->path) != 0)
+ continue;
+
+ assert(c->ops->readdir != NULL);
len = c->ops->readdir(&dir_entries);
if (len < 0)
@@ -173,49 +176,70 @@ static int rib_readdir(const char * path,
return 0;
}
+static size_t __getattr(const char * path,
+ struct stat * st)
+{
+ struct list_head * p;
+ char comp[RIB_PATH_LEN + 1];
+ char * c;
+
+ strcpy(comp, path + 1);
+
+ c = strstr(comp, "/");
+
+ if (c != NULL)
+ *c = '\0';
+
+ pthread_rwlock_rdlock(&rib.lock);
+
+ list_for_each(p, &rib.reg_comps) {
+ struct reg_comp * r = list_entry(p, struct reg_comp, next);
+ if (strcmp(comp, r->path) == 0) {
+ size_t ret = r->ops->getattr(c + 1, st);
+ pthread_rwlock_unlock(&rib.lock);
+ return ret;
+ }
+ }
+
+ pthread_rwlock_unlock(&rib.lock);
+
+ return -1;
+}
+
static int rib_getattr(const char * path,
struct stat * st)
{
struct list_head * p;
struct timespec now;
- clock_gettime(CLOCK_REALTIME_COARSE, &now);
-
memset(st, 0, sizeof(*st));
- if (strcmp(path, RT) == 0) {
- st->st_mode = S_IFDIR | 0755;
- st->st_nlink = 2;
- st->st_uid = getuid();
- st->st_gid = getgid();
- st->st_mtime = now.tv_sec;
- return 0;
- }
+ if (strcmp(path, RT) == 0)
+ goto finish_dir;
pthread_rwlock_rdlock(&rib.lock);
list_for_each(p, &rib.reg_comps) {
struct reg_comp * rc = list_entry(p, struct reg_comp, next);
if (strcmp(path + 1, rc->path) == 0) {
- st->st_mode = S_IFDIR | 0755;
- st->st_nlink = 2;
- break;
+ pthread_rwlock_unlock(&rib.lock);
+ goto finish_dir;
}
}
pthread_rwlock_unlock(&rib.lock);
- if (st->st_mode == 0) {
- char buf[4096];
- st->st_nlink = 2;
- st->st_mode = S_IFREG | 0755;
- st->st_size = rib_read(path, buf, 4096, 0, NULL);
- }
+ assert(st->st_mode == 0);
+
+ return __getattr(path, st);
+ finish_dir:
+ clock_gettime(CLOCK_REALTIME_COARSE, &now);
+ st->st_mode = S_IFDIR | 0755;
+ st->st_nlink = 2;
st->st_uid = getuid();
st->st_gid = getgid();
st->st_mtime = now.tv_sec;
-
return 0;
}