From 373efaf24d3600fe4dadf6bfaaee8d19e2ec32d7 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Mon, 6 Feb 2017 16:05:44 +0100 Subject: ipcpd, lib: Revise normal IPCP This PR updates the normal IPCP to use the new RIB. The old ribmgr is removed and replaced by a stub that needs to be implemented. All components (dir, fmgr, frct) were adapted to the new RIB API. A lot of functionality was moved outside of the ribmgr, such as the addr_auth, which is now a component of the IPCP. The address is also stored to the ipcpi struct. The irm tool has an option to set the gam policy of the rib manager. --- src/ipcpd/normal/pol/complete.c | 103 +++++++------- src/ipcpd/normal/pol/complete.h | 6 + src/ipcpd/normal/pol/flat.c | 292 ++++++++++++---------------------------- 3 files changed, 141 insertions(+), 260 deletions(-) (limited to 'src/ipcpd/normal/pol') diff --git a/src/ipcpd/normal/pol/complete.c b/src/ipcpd/normal/pol/complete.c index 89e1b91f..f85fd749 100644 --- a/src/ipcpd/normal/pol/complete.c +++ b/src/ipcpd/normal/pol/complete.c @@ -26,16 +26,14 @@ #include #include #include +#include -#include "pathname.h" -#include "ro.h" #include "ipcp.h" #include "gam.h" #include #include - -#define RO_DIR "neighbors" +#include struct neighbor { struct list_head next; @@ -56,73 +54,39 @@ static void * allocator(void * o) qosspec_t qs; ssize_t len; char ** children; - int i; - char * ro_name; + ssize_t i; struct complete * complete = (struct complete *) o; + assert(complete); + assert(complete->gam); + qs.delay = 0; qs.jitter = 0; - ro_name = pathname_create(RO_DIR); - if (ro_name == NULL) - return (void *) -1; - - len = ro_children(ro_name, &children); - if (len > 0) { - for (i = 0; i < len; i++) { - if (strcmp(children[i], ipcpi.name) == 0) - continue; + /* FIXME: subscribe to members to keep the graph complete. */ + len = rib_children("/" MEMBERS_NAME, &children); + for (i = 0; i < len; ++i) { + if (strcmp(children[i], ipcpi.name) < 0) gam_flow_alloc(complete->gam, children[i], qs); - } + free(children[i]); } - pathname_destroy(ro_name); + if (len > 0) + free(children); return (void *) 0; } void * complete_create(struct gam * gam) { - struct ro_attr attr; - char * ro_name; struct complete * complete; - ro_attr_init(&attr); - attr.enrol_sync = true; - attr.recv_set = ALL_MEMBERS; + assert(gam); complete = malloc(sizeof(*complete)); if (complete == NULL) return NULL; - ro_name = pathname_create(RO_DIR); - if (ro_name == NULL) { - free(complete); - return NULL; - } - - if (!ro_exists(RO_DIR)) { - if (ro_create(ro_name, &attr, NULL, 0)) { - free(complete); - pathname_destroy(ro_name); - return NULL; - } - } - - ro_name = pathname_append(ro_name, ipcpi.name); - if (ro_name == NULL) { - free(complete); - pathname_destroy(ro_name); - return NULL; - } - - if (ro_create(ro_name, &attr, NULL, 0)) { - free(complete); - pathname_destroy(ro_name); - return NULL; - } - pathname_destroy(ro_name); - list_head_init(&complete->neighbors); complete->gam = gam; @@ -131,14 +95,34 @@ void * complete_create(struct gam * gam) return NULL; } + return (void *) complete; +} + +int complete_start(void * o) +{ + struct complete * complete = (struct complete *) o; + + assert(complete); + assert(complete->gam); + if (pthread_create(&complete->allocator, NULL, allocator, (void *) complete)) { - free(complete); pthread_mutex_destroy(&complete->neighbors_lock); - return NULL; + free(complete); + return -1; } - return (void *) complete; + /* FIXME: Handle flooding of the flow allocator before detaching.*/ + pthread_join(complete->allocator, NULL); + + return 0; +} + +int complete_stop(void * o) +{ + (void) o; + + return 0; } void complete_destroy(void * o) @@ -147,15 +131,16 @@ void complete_destroy(void * o) struct list_head * n = NULL; struct complete * complete = (struct complete *) o; - pthread_cancel(complete->allocator); - pthread_join(complete->allocator, NULL); - list_for_each_safe(p, n, &complete->neighbors) { struct neighbor * e = list_entry(p, struct neighbor, next); list_del(&e->next); free(e->neighbor); free(e); } + + pthread_mutex_destroy(&complete->neighbors_lock); + + free(complete); } int complete_accept_new_flow(void * o) @@ -175,6 +160,8 @@ int complete_accept_flow(void * o, (void) qs; + assert(complete); + pthread_mutex_lock(&complete->neighbors_lock); list_for_each(pos, &complete->neighbors) { @@ -183,6 +170,10 @@ int complete_accept_flow(void * o, pthread_mutex_unlock(&complete->neighbors_lock); return -1; } + + assert(complete); + assert(&complete->neighbors_lock); + assert(pos->nxt); } n = malloc(sizeof(*n)); diff --git a/src/ipcpd/normal/pol/complete.h b/src/ipcpd/normal/pol/complete.h index 8fcc87ba..3f08c2e5 100644 --- a/src/ipcpd/normal/pol/complete.h +++ b/src/ipcpd/normal/pol/complete.h @@ -30,6 +30,10 @@ void * complete_create(struct gam * instance); void complete_destroy(void * o); +int complete_start(void * o); + +int complete_stop(void * o); + int complete_accept_new_flow(void * o); int complete_accept_flow(void * o, @@ -39,6 +43,8 @@ int complete_accept_flow(void * o, struct pol_gam_ops complete_ops = { .create = complete_create, .destroy = complete_destroy, + .start = complete_start, + .stop = complete_stop, .accept_new_flow = complete_accept_new_flow, .accept_flow = complete_accept_flow }; 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 + * Sander Vrijders + * Dimitri Staessens * * 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 #include #include +#include -#include "shm_pci.h" -#include "ribmgr.h" -#include "ro.h" -#include "pathname.h" +#include "ipcp.h" #include #include @@ -37,235 +36,120 @@ #include #include -#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; } -- cgit v1.2.3