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;  }  | 
