diff options
Diffstat (limited to 'src/ipcpd/normal/pol/flat.c')
-rw-r--r-- | src/ipcpd/normal/pol/flat.c | 292 |
1 files changed, 88 insertions, 204 deletions
diff --git a/src/ipcpd/normal/pol/flat.c b/src/ipcpd/normal/pol/flat.c index abcb1ad4..31fcd4e8 100644 --- a/src/ipcpd/normal/pol/flat.c +++ b/src/ipcpd/normal/pol/flat.c @@ -3,7 +3,8 @@ * * Policy for flat addresses in a distributed way * - * Sander Vrijders <[email protected]> + * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -25,11 +26,9 @@ #include <ouroboros/logs.h> #include <ouroboros/errno.h> #include <ouroboros/time_utils.h> +#include <ouroboros/rib.h> -#include "shm_pci.h" -#include "ribmgr.h" -#include "ro.h" -#include "pathname.h" +#include "ipcp.h" #include <time.h> #include <stdlib.h> @@ -37,235 +36,120 @@ #include <string.h> #include <assert.h> -#define POL_RO_ROOT "flat_addr" +#define NAME_LEN 8 +#define REC_DIF_SIZE 10000 -#define TIMEOUT 100 /* ms */ -#define STR_SIZE 100 - -#define FLAT_ADDR_REQ 0 -#define FLAT_ADDR_REPLY 1 - -struct flat_addr_msg { - uint8_t code; - uint64_t addr; -}; - -struct { - int sid; - uint64_t addr; - bool addr_in_use; - - pthread_cond_t cond; - pthread_mutex_t lock; -} flat; - -static char * addr_name(void) +/* convert 32 bit addr to a hex string */ +static void addr_name(char * name, + uint32_t addr) { - char * name; - /* uint64_t as a string has 25 chars */ - char addr_name[30]; - - sprintf(addr_name, "%lu", (unsigned long) flat.addr); - - name = pathname_create(POL_RO_ROOT); - if (name == NULL) - return NULL; - - name = pathname_append(name, addr_name); - return name; + sprintf(name, "%8x", (uint32_t) (addr)); } -static void ro_created(const char * name, - uint8_t * data, - size_t len) +#define freepp(type, ptr, len) \ + do { \ + if (len == 0) \ + break; \ + while (len > 0) \ + free(((type **) ptr)[--len]); \ + free(ptr); \ + } while (0); + +static int addr_taken(char * name, + char ** members, + size_t len) { - struct flat_addr_msg * msg; - - assert(name); - assert(data); - assert(len >= sizeof(*msg)); - - msg = (struct flat_addr_msg *) data; - if (msg->code == FLAT_ADDR_REQ && msg->addr == flat.addr) { - msg->code = FLAT_ADDR_REPLY; - ro_write(name, data, len); + size_t i; + char path[RIB_MAX_PATH_LEN + 1]; + + size_t reset; + strcpy(path, "/" MEMBERS_NAME); + + reset = strlen(path); + + for (i = 0; i < len; ++i) { + ssize_t j; + ssize_t c; + char ** addrs; + rib_path_append(path, members[i]); + c = rib_children(path, &addrs); + for (j = 0; j < c; ++j) + if (strcmp(addrs[j], name) == 0) { + freepp(char, addrs, c); + return 1; + } + freepp(char, addrs, c); + path[reset] = '\0'; } -} -static void ro_updated(const char * name, - uint8_t * data, - size_t len) -{ - struct flat_addr_msg * msg; - char * ro_name; - - assert(name); - assert(data); - assert(len >= sizeof(*msg)); - (void) len; - - ro_name = addr_name(); - if (ro_name == NULL) { - free(data); - return; - } - - msg = (struct flat_addr_msg *) data; - if (msg->code == FLAT_ADDR_REPLY && - strcmp(name, ro_name) == 0) { - pthread_mutex_lock(&flat.lock); - flat.addr_in_use = true; - pthread_cond_broadcast(&flat.cond); - pthread_mutex_unlock(&flat.lock); - } - - free(data); - free(ro_name); + return 0; } -static struct ro_sub_ops flat_sub_ops = { - .ro_created = ro_created, - .ro_updated = ro_updated, - .ro_deleted = NULL -}; +#define INVALID_ADDRESS 0 -int flat_init(void) +uint64_t flat_address(void) { - struct ro_attr rattr; - pthread_condattr_t cattr; - struct timespec t; - char * name; + struct timespec t; - clock_gettime(CLOCK_REALTIME, &t); + char path[RIB_MAX_PATH_LEN]; + char name[NAME_LEN + 1]; + uint32_t addr; + uint8_t addr_size; - srand(t.tv_nsec); - flat.addr_in_use = false; + char ** members; + ssize_t n_members; - ro_attr_init(&rattr); - pthread_mutex_init(&flat.lock, NULL); - pthread_condattr_init(&cattr); -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - pthread_cond_init(&flat.cond, &cattr); + strcpy(path, "/" MEMBERS_NAME); - flat.sid = ro_subscribe(POL_RO_ROOT, &flat_sub_ops); - if (flat.sid < 0) { - LOG_ERR("Could not subscribe to RIB."); - pthread_cond_destroy(&flat.cond); - pthread_mutex_destroy(&flat.lock); - return -1; + if (!rib_has(path)) { + LOG_ERR("Could not read members from RIB."); + return INVALID_ADDRESS; } - name = pathname_create(POL_RO_ROOT); - if (name == NULL) { - pthread_cond_destroy(&flat.cond); - pthread_mutex_destroy(&flat.lock); - ro_unsubscribe(flat.sid); - return -1; + if (rib_read("/" BOOT_NAME "/dt/const/addr_size", + &addr_size, sizeof(addr_size)) != sizeof(addr_size)) { + LOG_ERR("Failed to read address size."); + return INVALID_ADDRESS; } - if (!ro_exists(name)) { - rattr.enrol_sync = true; - if (ro_create(name, &rattr, NULL, 0)) { - LOG_ERR("Could not create RO."); - pathname_destroy(name); - pthread_cond_destroy(&flat.cond); - pthread_mutex_destroy(&flat.lock); - ro_unsubscribe(flat.sid); - return -1; - } + if (addr_size != 4) { + LOG_ERR("Flat address policy mandates 4 byte addresses."); + return INVALID_ADDRESS; } - pathname_destroy(name); - - return 0; -} - -int flat_fini(void) -{ - pthread_cond_destroy(&flat.cond); - pthread_mutex_destroy(&flat.lock); - ro_unsubscribe(flat.sid); - return 0; -} -uint64_t flat_address(void) -{ - int ret = 0; - uint64_t max_addr; - struct dt_const * dtc; - struct timespec timeout = {(TIMEOUT / 1000), - (TIMEOUT % 1000) * MILLION}; - struct timespec abstime; - struct ro_attr attr; - struct flat_addr_msg * msg; - uint8_t * buf; - char * ro_name; + n_members = rib_children(path, &members); + if (n_members > REC_DIF_SIZE) + LOG_WARN("DIF exceeding recommended size for flat addresses."); - dtc = ribmgr_dt_const(); - if (dtc == NULL) - return INVALID_ADDR; + rib_path_append(path, ipcpi.name); - if (dtc->addr_size == 8) { - LOG_ERR("Policy cannot be used with 64 bit addresses."); - return INVALID_ADDR; + if (!rib_has(path)) { + LOG_ERR("This ipcp is not a member."); + freepp(char, members, n_members); + return INVALID_ADDRESS; } - while (ret != -ETIMEDOUT) { - clock_gettime(PTHREAD_COND_CLOCK, &abstime); - ts_add(&abstime, &timeout, &abstime); - - max_addr = (1 << (8 * dtc->addr_size)) - 1; - flat.addr = (rand() % (max_addr - 1)) + 1; - - ro_attr_init(&attr); - attr.recv_set = ALL_MEMBERS; - attr.expiry.tv_sec = TIMEOUT / 1000; - attr.expiry.tv_nsec = (TIMEOUT % 1000) * MILLION; - - buf = malloc(sizeof(*msg)); - if (buf == NULL) - return INVALID_ADDR; - - msg = (struct flat_addr_msg *) buf; - msg->code = FLAT_ADDR_REQ; - msg->addr = flat.addr; - - ro_name = addr_name(); - if (ro_name == NULL) { - free(buf); - return INVALID_ADDR; - } - - pthread_mutex_lock(&flat.lock); - - if (ro_exists(ro_name)) { - pthread_mutex_unlock(&flat.lock); - free(ro_name); - free(buf); - continue; - } + clock_gettime(CLOCK_REALTIME, &t); + srand(t.tv_nsec); + assert(n_members > 0); - if (ro_create(ro_name, &attr, buf, sizeof(*msg))) { - pthread_mutex_unlock(&flat.lock); - free(ro_name); - free(buf); - return INVALID_ADDR; - } + do { + addr = (rand() % (RAND_MAX - 1) + 1) & 0xFFFFFFFF; + addr_name(name, addr); + } while (addr_taken(name, members, n_members)); - free(ro_name); + freepp(char, members, n_members); - while (flat.addr_in_use == false) { - ret = -pthread_cond_timedwait(&flat.cond, - &flat.lock, - &abstime); - if (ret == -ETIMEDOUT) - break; - } + if (rib_add(path, name)) { + LOG_ERR("Failed to add address to RIB."); + return INVALID_ADDRESS; + } - pthread_mutex_unlock(&flat.lock); + if (rib_write(path, &addr, sizeof(addr))) { + LOG_ERR("Failed to write address in RIB."); + return INVALID_ADDRESS; } - return flat.addr; + return addr; } |