diff options
-rw-r--r-- | include/ouroboros/rib.h | 5 | ||||
-rw-r--r-- | src/ipcpd/normal/pol/link_state.c | 109 | ||||
-rw-r--r-- | src/lib/rib.c | 70 |
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; } |