diff options
author | Sander Vrijders <sander.vrijders@intec.ugent.be> | 2017-02-07 10:35:49 +0000 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@intec.ugent.be> | 2017-02-07 10:35:49 +0000 |
commit | 1bf2dd6aef3af6c81794c0551278373e44310b5c (patch) | |
tree | 2c5bb331021e0b15eb43827d05cd06082b6c8edb | |
parent | 129d5e06d627346cb30ce60cdf43f8a1ae023dcb (diff) | |
parent | d64f05e8bf1277132b648bda2e1175ad8c1d2d5c (diff) | |
download | ouroboros-1bf2dd6aef3af6c81794c0551278373e44310b5c.tar.gz ouroboros-1bf2dd6aef3af6c81794c0551278373e44310b5c.zip |
Merged in dstaesse/ouroboros/be-wip (pull request #362)
ipcpd, lib: Revise normal IPCP
33 files changed, 1103 insertions, 2658 deletions
diff --git a/include/ouroboros/config.h.in b/include/ouroboros/config.h.in index 5597bb0b..b95fe927 100644 --- a/include/ouroboros/config.h.in +++ b/include/ouroboros/config.h.in @@ -47,7 +47,7 @@ #define SHM_RBUFF_PREFIX "/ouroboros.rbuff." #define SHM_FLOW_SET_PREFIX "/ouroboros.sets." #define IRMD_MAX_FLOWS 4096 -#define IRMD_THREADPOOL_SIZE 5 +#define IRMD_THREADPOOL_SIZE 16 #define IPCPD_THREADPOOL_SIZE 3 #define IPCPD_MAX_CONNS IRMD_MAX_FLOWS #define LOG_DIR "/@LOG_DIR@/" @@ -61,6 +61,11 @@ #define SOCKET_TIMEOUT 4000 #define CDAP_REPLY_TIMEOUT 1000 #define ENROLL_TIMEOUT 2000 +/* RIB configuration for normal */ #define RIB_MAX_PATH_LEN 256 +#define BOOT_NAME "boot" +#define MEMBERS_NAME "members" +#define DIF_NAME "dif_name" +#define DIR_NAME "directory" -#endif +#endif /* OUROBOROS_CONFIG */ diff --git a/include/ouroboros/irm_config.h b/include/ouroboros/irm_config.h index c4a81c23..2be4273e 100644 --- a/include/ouroboros/irm_config.h +++ b/include/ouroboros/irm_config.h @@ -47,6 +47,10 @@ enum pol_gam { COMPLETE = 0 }; +enum pol_cacep { + NO_AUTH = 0 +}; + struct dif_config { char * dif_name; enum ipcp_type type; @@ -57,7 +61,6 @@ struct dif_config { uint8_t addr_size; uint8_t cep_id_size; uint8_t pdu_length_size; - uint8_t qos_id_size; uint8_t seqno_size; bool has_ttl; @@ -68,6 +71,7 @@ struct dif_config { enum pol_addr_auth addr_auth_type; enum pol_gam dt_gam_type; + enum pol_gam rm_gam_type; }; /* Shim UDP */ struct { diff --git a/include/ouroboros/shm_rdrbuff.h b/include/ouroboros/shm_rdrbuff.h index cdac51f0..2e23381b 100644 --- a/include/ouroboros/shm_rdrbuff.h +++ b/include/ouroboros/shm_rdrbuff.h @@ -78,9 +78,9 @@ uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb, uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb, size_t size); -int shm_du_buff_head_release(struct shm_du_buff * sdb, +void shm_du_buff_head_release(struct shm_du_buff * sdb, size_t size); -int shm_du_buff_tail_release(struct shm_du_buff * sdb, +void shm_du_buff_tail_release(struct shm_du_buff * sdb, size_t size); #endif /* OUROBOROS_SHM_RDRBUFF_H */ diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 2115f7c1..fe87fbd9 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -119,7 +119,6 @@ static void * ipcp_main_loop(void * o) conf.cep_id_size = conf_msg->cep_id_size; conf.pdu_length_size = conf_msg->pdu_length_size; - conf.qos_id_size = conf_msg->qos_id_size; conf.seqno_size = conf_msg->seqno_size; conf.has_ttl = conf_msg->has_ttl; conf.has_chk = conf_msg->has_chk; @@ -127,6 +126,7 @@ static void * ipcp_main_loop(void * o) conf.max_pdu_size = conf_msg->max_pdu_size; conf.addr_auth_type = conf_msg->addr_auth_type; conf.dt_gam_type = conf_msg->dt_gam_type; + conf.rm_gam_type = conf_msg->rm_gam_type; } if (conf_msg->ipcp_type == IPCP_SHIM_UDP) { conf.ip_addr = conf_msg->ip_addr; diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index a75186ba..8b590cc2 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -41,6 +41,8 @@ struct ipcp { int irmd_api; char * name; + uint64_t address; + struct ipcp_data * data; struct ipcp_ops * ops; int irmd_fd; diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index bae2f69a..f2e48cbc 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -14,23 +14,18 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(IPCP_NORMAL_TARGET ipcpd-normal CACHE STRING "IPCP_NORMAL_TARGET") -protobuf_generate_c(STATIC_INFO_SRCS STATIC_INFO_HDRS - static_info.proto) - protobuf_generate_c(FLOW_ALLOC_SRCS FLOW_ALLOC_HDRS flow_alloc.proto) -protobuf_generate_c(RO_SRCS RO_HDRS ro.proto) - set(SOURCE_FILES # Add source files here addr_auth.c dir.c + enroll.c fmgr.c frct.c gam.c main.c - pathname.c pff.c ribmgr.c shm_pci.c @@ -40,7 +35,7 @@ set(SOURCE_FILES ) add_executable (ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES} - ${STATIC_INFO_SRCS} ${FLOW_ALLOC_SRCS} ${RO_SRCS}) + ${FLOW_ALLOC_SRCS}) target_link_libraries (ipcpd-normal LINK_PUBLIC ouroboros) include(MacroAddCompileFlags) diff --git a/src/ipcpd/normal/addr_auth.c b/src/ipcpd/normal/addr_auth.c index a4084ac5..c41ffcd2 100644 --- a/src/ipcpd/normal/addr_auth.c +++ b/src/ipcpd/normal/addr_auth.c @@ -35,16 +35,13 @@ struct addr_auth * addr_auth_create(enum pol_addr_auth type) struct addr_auth * tmp; tmp = malloc(sizeof(*tmp)); - if (tmp == NULL) + if (tmp == NULL) { + LOG_ERR("Failed to malloc addr auth."); return NULL; + } switch (type) { case FLAT_RANDOM: - if (flat_init()) { - free(tmp); - return NULL; - } - tmp->address = flat_address; tmp->type = type; break; @@ -63,9 +60,6 @@ int addr_auth_destroy(struct addr_auth * instance) switch (instance->type) { case FLAT_RANDOM: - if (flat_fini()) { - return -1; - } break; default: LOG_ERR("Unknown address authority type."); diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h index 229ff4aa..882625dd 100644 --- a/src/ipcpd/normal/ae.h +++ b/src/ipcpd/normal/ae.h @@ -23,7 +23,8 @@ #ifndef OUROBOROS_IPCPD_NORMAL_AE_H #define OUROBOROS_IPCPD_NORMAL_AE_H -#define MGMT_AE "Management" -#define DT_AE "Data transfer" +#define MGMT_AE "Management" +#define DT_AE "Data transfer" +#define ENROLL_AE "Enrollment" #endif /* OUROBOROS_IPCPD_NORMAL_AE_H */ diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index 49283529..d30b9ec0 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -3,7 +3,8 @@ * * DIF directory * - * Sander Vrijders <sander.vrijders@intec.ugent.be> + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * Sander Vrijders <sander.vrijders@intec.ugent.be> * * 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 @@ -19,164 +20,119 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define OUROBOROS_PREFIX "directory" - #include <ouroboros/config.h> -#include <ouroboros/logs.h> #include <ouroboros/errno.h> +#include <ouroboros/rib.h> #include "dir.h" -#include "ro.h" -#include "pathname.h" -#include "ribmgr.h" +#include "ipcp.h" #include <stdlib.h> #include <string.h> #include <assert.h> -char * create_path(char * name) -{ - char * path; - - path = pathname_create(RO_DIR); - if (path == NULL) - return NULL; - - path = pathname_append(path, name); - if (path == NULL) { - pathname_destroy(path); - return NULL; - } +static char dir_path[RIB_MAX_PATH_LEN + 1]; - return path; +static void dir_path_reset(void) { + dir_path[strlen("/" DIR_NAME)]= '\0'; + assert(strcmp("/" DIR_NAME, dir_path) == 0); } int dir_init(void) { - char * path; - struct ro_attr attr; + /*FIXME: set ribmgr dissemination here */ - ro_attr_init(&attr); - attr.enrol_sync = true; - attr.recv_set = ALL_MEMBERS; - - path = pathname_create(RO_DIR); - if (path == NULL) - return -1; - - if (ro_create(path, &attr, NULL, 0)) { - pathname_destroy(path); - LOG_ERR("Failed to create RIB object."); + if (rib_add(RIB_ROOT, DIR_NAME)) return -1; - } - pathname_destroy(path); + strcpy(dir_path, "/" DIR_NAME); return 0; } int dir_fini(void) { - char * path; + /* FIXME: remove ribmgr dissemination here*/ - path = pathname_create(RO_DIR); - if (path == NULL) - return -1; - - ro_delete(path); - pathname_destroy(path); + dir_path_reset(); + rib_del(dir_path); return 0; } int dir_name_reg(char * name) { - struct ro_attr attr; - char * path; - uint64_t * addr; + int ret; assert(name); - ro_attr_init(&attr); - attr.enrol_sync = true; - attr.recv_set = ALL_MEMBERS; + dir_path_reset(); - path = create_path(name); - if (path == NULL) + ret = rib_add(dir_path, name); + if (ret == -ENOMEM) return -ENOMEM; - addr = malloc(sizeof(*addr)); - if (addr == NULL) { - pathname_destroy(path); + rib_path_append(dir_path, name); + ret = rib_add(dir_path, ipcpi.name); + if (ret == -EPERM) + return -EPERM; + if (ret == -ENOMEM) { + if (rib_children(dir_path, NULL) == 0) + rib_del(dir_path); return -ENOMEM; } - *addr = ribmgr_address(); - - if (ro_create(path, &attr, (uint8_t *) addr, sizeof(*addr))) { - pathname_destroy(path); - free(addr); - LOG_ERR("Failed to create RIB object."); - return -1; - } - - LOG_DBG("Registered %s.", name); - pathname_destroy(path); - return 0; } int dir_name_unreg(char * name) { - char * path; + size_t len; assert(name); - path = create_path(name); - if (path == NULL) - return -ENOMEM; + dir_path_reset(); - if (ro_delete(path)) { - pathname_destroy(path); - LOG_ERR("No such RIB object exists."); - return -1; - } + rib_path_append(dir_path, name); + + if (!rib_has(dir_path)) + return 0; + + len = strlen(dir_path); + + rib_path_append(dir_path, ipcpi.name); - pathname_destroy(path); + rib_del(dir_path); + + dir_path[len] = '\0'; + + if (rib_children(dir_path, NULL) == 0) + rib_del(dir_path); return 0; } int dir_name_query(char * name) { - char * path; - int ret = -1; - uint8_t * ro_data; - uint64_t addr; - struct dt_const * dtc; - - path = create_path(name); - if (path == NULL) - return -ENOMEM; + size_t len; - if (ro_exists(path)) { - if (ro_read(path, &ro_data) < 0) { - pathname_destroy(path); - return -1; - } - addr = *((uint64_t *) ro_data); - free(ro_data); + dir_path_reset(); - dtc = ribmgr_dt_const(); - if (dtc == NULL) { - pathname_destroy(path); - return -1; - } + rib_path_append(dir_path, name); - ret = (addr == ribmgr_address()) ? -1 : 0; - } + if (!rib_has(dir_path)) + return -1; + + /* FIXME: assert after local IPCP is deprecated */ + len = strlen(dir_path); - pathname_destroy(path); + rib_path_append(dir_path, ipcpi.name); - return ret; + if (rib_has(dir_path)) { + dir_path[len] = '\0'; + if (rib_children(dir_path, NULL) == 1) + return -1; + } + + return 0; } diff --git a/src/ipcpd/normal/dir.h b/src/ipcpd/normal/dir.h index 867cb87a..925fc823 100644 --- a/src/ipcpd/normal/dir.h +++ b/src/ipcpd/normal/dir.h @@ -22,8 +22,6 @@ #ifndef OUROBOROS_IPCPD_NORMAL_DIR_H #define OUROBOROS_IPCPD_NORMAL_DIR_H -#define RO_DIR "directory" - int dir_init(void); int dir_fini(void); diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c new file mode 100644 index 00000000..695ceb1d --- /dev/null +++ b/src/ipcpd/normal/enroll.c @@ -0,0 +1,263 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Enrollment Task + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#define OUROBOROS_PREFIX "enrollment" + +#include <ouroboros/config.h> +#include <ouroboros/cdap.h> +#include <ouroboros/dev.h> +#include <ouroboros/logs.h> +#include <ouroboros/rib.h> + +#include "ae.h" + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#define DLR "/" +#define DIF_PATH DLR DIF_NAME +#define BOOT_PATH DLR BOOT_NAME +#define MEMBERS_PATH DLR MEMBERS_NAME + +int enroll_handle(int fd) +{ + struct cdap * ci; + cdap_key_t key; + enum cdap_opcode oc; + char * name; + uint8_t * buf; + uint8_t * data; + ssize_t len; + uint32_t flags; + + bool boot_r = false; + bool members_r = false; + bool dif_name_r = false; + + char * boot_ro = BOOT_PATH; + char * members_ro = MEMBERS_PATH; + char * dif_ro = DIF_PATH; + + if (flow_alloc_resp(fd, 0) < 0) { + flow_dealloc(fd); + LOG_ERR("Could not respond to request."); + return -1; + } + + ci = cdap_create(fd); + if (ci == NULL) { + flow_dealloc(fd); + LOG_ERR("Failed to create CDAP instance."); + return -1; + } + + while (!(boot_r && members_r && dif_name_r)) { + key = cdap_request_wait(ci, &oc, &name, &data, + (size_t *) &len , &flags); + + assert(key >= 0); + assert(name); + + if (data != NULL) { + free(data); + LOG_WARN("Received data with enrollment request."); + } + + if (oc != CDAP_READ) { + LOG_WARN("Invalid request."); + cdap_reply_send(ci, key, -1, NULL, 0); + cdap_destroy(ci); + flow_dealloc(fd); + free(name); + return -1; + } + + if (strcmp(name, boot_ro) == 0) { + boot_r = true; + } else if (strcmp(name, members_ro) == 0) { + members_r = true; + } else if (strcmp(name, dif_ro) == 0) { + dif_name_r = true; + } else { + LOG_WARN("Illegal read: %s.", name); + cdap_reply_send(ci, key, -1, NULL, 0); + cdap_destroy(ci); + flow_dealloc(fd); + free(name); + return -1; + } + + len = rib_pack(name, &buf, PACK_HASH_ROOT); + if (len < 0) { + LOG_ERR("Failed to pack %s.", name); + cdap_reply_send(ci, key, -1, NULL, 0); + cdap_destroy(ci); + flow_dealloc(fd); + free(name); + return -1; + } + + LOG_DBG("Packed %s (%lu bytes).", name, len); + + free(name); + + if (cdap_reply_send(ci, key, 0, buf, len)) { + LOG_ERR("Failed to send CDAP reply."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + free(buf); + } + + LOG_DBG("Sent boot info to new member."); + + cdap_destroy(ci); + + flow_dealloc(fd); + + return 0; +} + +int enroll_boot(char * dst_name) +{ + struct cdap * ci; + cdap_key_t key; + uint8_t * data; + size_t len; + int fd; + + char * boot_ro = BOOT_PATH; + char * members_ro = MEMBERS_PATH; + char * dif_ro = DIF_PATH; + + fd = flow_alloc(dst_name, ENROLL_AE, NULL); + if (fd < 0) { + LOG_ERR("Failed to allocate flow."); + return -1; + } + + if (flow_alloc_res(fd)) { + LOG_ERR("Flow allocation failed."); + flow_dealloc(fd); + return -1; + } + + ci = cdap_create(fd); + if (ci == NULL) { + LOG_ERR("Failed to create CDAP instance."); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Getting boot information from %s.", dst_name); + + key = cdap_request_send(ci, CDAP_READ, boot_ro, NULL, 0, 0); + if (key < 0) { + LOG_ERR("Failed to send CDAP request."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + if (cdap_reply_wait(ci, key, &data, &len)) { + LOG_ERR("Failed to get CDAP reply."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Packed information received (%lu bytes).", len); + + if (rib_unpack(data, len, UNPACK_CREATE)) { + LOG_WARN("Error unpacking RIB data."); + rib_del(boot_ro); + free(data); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Packed information inserted into RIB."); + + key = cdap_request_send(ci, CDAP_READ, members_ro, NULL, 0, 0); + if (key < 0) { + LOG_ERR("Failed to send CDAP request."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + if (cdap_reply_wait(ci, key, &data, &len)) { + LOG_ERR("Failed to get CDAP reply."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Packed information received (%lu bytes).", len); + + if (rib_unpack(data, len, UNPACK_CREATE)) { + LOG_WARN("Error unpacking RIB data."); + rib_del(boot_ro); + free(data); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Packed information inserted into RIB."); + + key = cdap_request_send(ci, CDAP_READ, dif_ro, NULL, 0, 0); + if (key < 0) { + LOG_ERR("Failed to send CDAP request."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + if (cdap_reply_wait(ci, key, &data, &len)) { + LOG_ERR("Failed to get CDAP reply."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Packed information received (%lu bytes).", len); + + if (rib_unpack(data, len, UNPACK_CREATE)) { + LOG_WARN("Error unpacking RIB data."); + rib_del(boot_ro); + free(data); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + LOG_DBG("Packed information inserted into RIB."); + + cdap_destroy(ci); + + flow_dealloc(fd); + + return 0; +} diff --git a/src/ipcpd/normal/ro.proto b/src/ipcpd/normal/enroll.h index cceaae7c..2980c380 100644 --- a/src/ipcpd/normal/ro.proto +++ b/src/ipcpd/normal/enroll.h @@ -1,10 +1,9 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * RIB object message + * Enrollment Task * * Dimitri Staessens <dimitri.staessens@intec.ugent.be> - * Sander Vrijders <sander.vrijders@intec.ugent.be> * * 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 @@ -20,14 +19,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -syntax = "proto2"; +#ifndef OUROBOROS_IPCPD_NORMAL_ENROLL_H +#define OUROBOROS_IPCPD_NORMAL_ENROLL_H -message ro_msg { - required uint64 address = 1; - required uint64 seqno = 2; - required int32 recv_set = 3; - required bool enrol_sync = 4; - required uint32 sec = 5; - required uint64 nsec = 6; - required bytes value = 7; -}
\ No newline at end of file +int enroll_handle(int fd); + +int enroll_boot(char * dst_name); + +#endif /* OUROBOROS_IPCPD_NORMAL_ENROLL_H */ diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 6fe6fb60..b79d20b4 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -29,22 +29,19 @@ #include <ouroboros/fqueue.h> #include <ouroboros/errno.h> #include <ouroboros/cacep.h> - -#include <stdlib.h> -#include <stdbool.h> -#include <pthread.h> -#include <string.h> +#include <ouroboros/rib.h> #include "fmgr.h" -#include "ribmgr.h" #include "frct.h" #include "ipcp.h" #include "shm_pci.h" -#include "dir.h" -#include "pathname.h" -#include "ro.h" #include "gam.h" +#include <stdlib.h> +#include <stdbool.h> +#include <pthread.h> +#include <string.h> + #include "flow_alloc.pb-c.h" typedef FlowAllocMsg flow_alloc_msg_t; @@ -132,13 +129,15 @@ void * fmgr_nm1_sdu_reader(void * o) { struct timespec timeout = {0, FD_UPDATE_TIMEOUT}; struct shm_du_buff * sdb; - struct pci * pci; + struct pci pci; int fd; int i = 0; int ret; (void) o; + memset(&pci, 0, sizeof(pci)); + while (true) { /* FIXME: replace with scheduling policy call */ i = (i + 1) % QOS_CUBE_MAX; @@ -160,30 +159,15 @@ void * fmgr_nm1_sdu_reader(void * o) continue; } - pci = shm_pci_des(sdb); - if (pci == NULL) { - LOG_ERR("Failed to get PCI."); - ipcp_flow_del(sdb); - continue; - } + shm_pci_des(sdb, &pci); - if (pci->dst_addr != ribmgr_address()) { + if (pci.dst_addr != ipcpi.address) { LOG_DBG("PDU needs to be forwarded."); - if (ribmgr_dt_const()->has_ttl) { - if (pci->ttl == 0) { - LOG_DBG("TTL was zero."); - ipcp_flow_del(sdb); - free(pci); - continue; - } - - if (shm_pci_dec_ttl(sdb)) { - LOG_ERR("Failed to dec TTL."); - ipcp_flow_del(sdb); - free(pci); - continue; - } + if (pci.ttl == 0) { + LOG_DBG("TTL was zero."); + ipcp_flow_del(sdb); + continue; } /* @@ -191,21 +175,14 @@ void * fmgr_nm1_sdu_reader(void * o) * we don't have a PFF yet */ ipcp_flow_del(sdb); - free(pci); continue; } - if (shm_pci_shrink(sdb)) { - LOG_ERR("Failed to shrink PDU."); - ipcp_flow_del(sdb); - free(pci); - continue; - } + shm_pci_shrink(sdb); - if (frct_nm1_post_sdu(pci, sdb)) { + if (frct_nm1_post_sdu(&pci, sdb)) { LOG_ERR("Failed to hand PDU to FRCT."); ipcp_flow_del(sdb); - free(pci); continue; } } @@ -269,8 +246,11 @@ static void fmgr_destroy_flows(void) } } -int fmgr_init() +int fmgr_init(void) { + enum pol_cacep pc; + enum pol_gam pg; + int i; for (i = 0; i < AP_MAX_FLOWS; ++i) @@ -305,7 +285,22 @@ int fmgr_init() } } - fmgr.gam = gam_create(ribmgr_dt_gam(), DT_AE); + if (rib_read("/" BOOT_NAME "/dt/gam/type", &pg, sizeof(pg)) + != sizeof(pg)) { + LOG_ERR("Failed to read policy for ribmgr gam."); + return -1; + } + + if (rib_read("/" BOOT_NAME "/dt/gam/cacep", &pc, sizeof(pc)) + != sizeof(pc)) { + LOG_ERR("Failed to read CACEP policy for ribmgr gam."); + return -1; + } + + /* FIXME: Implement cacep policies */ + (void) pc; + + fmgr.gam = gam_create(pg, DT_AE); if (fmgr.gam == NULL) { LOG_ERR("Failed to create graph adjacency manager."); fmgr_destroy_flows(); @@ -324,7 +319,7 @@ int fmgr_init() return 0; } -int fmgr_fini() +void fmgr_fini() { struct list_head * pos = NULL; struct list_head * n = NULL; @@ -359,8 +354,6 @@ int fmgr_fini() pthread_rwlock_destroy(&fmgr.np1_flows_lock); fmgr_destroy_flows(); - - return 0; } int fmgr_np1_alloc(int fd, @@ -371,27 +364,43 @@ int fmgr_np1_alloc(int fd, cep_id_t cep_id; buffer_t buf; flow_alloc_msg_t msg = FLOW_ALLOC_MSG__INIT; - char * path; - uint8_t * ro_data; + char path[RIB_MAX_PATH_LEN + 1]; uint64_t addr; + ssize_t ch; + ssize_t i; + char ** children; + char * dst_ipcp = NULL; - path = pathname_create(RO_DIR); - if (path == NULL) - return -1; + assert(strlen(dst_ap_name) + strlen("/" DIR_NAME) + 1 + < RIB_MAX_PATH_LEN); - path = pathname_append(path, dst_ap_name); - if (path == NULL) { - pathname_destroy(path); + strcpy(path, "/" DIR_NAME); + + rib_path_append(path, dst_ap_name); + + ch = rib_children(path, &children); + if (ch <= 0) return -1; - } - if (ro_read(path, &ro_data) < 0) { - pathname_destroy(path); + for (i = 0; i < ch; ++i) + if (dst_ipcp == NULL && strcmp(children[i], ipcpi.name) != 0) + dst_ipcp = children[i]; + else + free(children[i]); + + free(children); + + if (dst_ipcp == NULL) return -1; - } - addr = *((uint64_t *) ro_data); - pathname_destroy(path); + strcpy(path, "/" MEMBERS_NAME); + + rib_path_append(path, dst_ipcp); + + free(dst_ipcp); + + if (rib_read(path, &addr, sizeof(addr)) < 0) + return -1; msg.code = FLOW_ALLOC_CODE__FLOW_REQ; msg.dst_name = dst_ap_name; @@ -400,16 +409,12 @@ int fmgr_np1_alloc(int fd, msg.qoscube = cube; buf.len = flow_alloc_msg__get_packed_size(&msg); - if (buf.len == 0) { - free(ro_data); + if (buf.len == 0) return -1; - } buf.data = malloc(buf.len); - if (buf.data == NULL) { - free(ro_data); + if (buf.data == NULL) return -1; - } flow_alloc_msg__pack(&msg, buf.data); @@ -417,14 +422,11 @@ int fmgr_np1_alloc(int fd, cep_id = frct_i_create(addr, &buf, cube); if (cep_id == INVALID_CEP_ID) { - free(ro_data); free(buf.data); pthread_rwlock_unlock(&fmgr.np1_flows_lock); return -1; } - free(ro_data); - fmgr.np1_fd_to_cep_id[fd] = cep_id; fmgr.np1_cep_id_to_fd[cep_id] = fd; diff --git a/src/ipcpd/normal/fmgr.h b/src/ipcpd/normal/fmgr.h index ae5c8ea8..3c61f55a 100644 --- a/src/ipcpd/normal/fmgr.h +++ b/src/ipcpd/normal/fmgr.h @@ -28,34 +28,34 @@ #include "ae.h" #include "frct.h" -int fmgr_init(void); +int fmgr_init(void); -int fmgr_fini(void); +void fmgr_fini(void); -int fmgr_np1_alloc(int fd, - char * dst_ap_name, - char * src_ae_name, - qoscube_t qos); +int fmgr_np1_alloc(int fd, + char * dst_ap_name, + char * src_ae_name, + qoscube_t qos); -int fmgr_np1_alloc_resp(int fd, - int response); +int fmgr_np1_alloc_resp(int fd, + int response); -int fmgr_np1_dealloc(int fd); +int fmgr_np1_dealloc(int fd); -int fmgr_np1_post_buf(cep_id_t id, - buffer_t * buf); +int fmgr_np1_post_buf(cep_id_t id, + buffer_t * buf); -int fmgr_np1_post_sdu(cep_id_t id, - struct shm_du_buff * sdb); - -int fmgr_nm1_write_sdu(struct pci * pci, +int fmgr_np1_post_sdu(cep_id_t id, struct shm_du_buff * sdb); -int fmgr_nm1_write_buf(struct pci * pci, - buffer_t * buf); +int fmgr_nm1_write_sdu(struct pci * pci, + struct shm_du_buff * sdb); + +int fmgr_nm1_write_buf(struct pci * pci, + buffer_t * buf); -int fmgr_nm1_flow_arr(int fd, - qosspec_t qs); +int fmgr_nm1_flow_arr(int fd, + qosspec_t qs); #endif /* OUROBOROS_IPCPD_NORMAL_FMGR_H */ diff --git a/src/ipcpd/normal/frct.c b/src/ipcpd/normal/frct.c index 6cd68f18..ce316ca2 100644 --- a/src/ipcpd/normal/frct.c +++ b/src/ipcpd/normal/frct.c @@ -26,14 +26,14 @@ #include <ouroboros/bitmap.h> #include <ouroboros/list.h> +#include "frct.h" +#include "fmgr.h" +#include "ipcp.h" + #include <stdlib.h> #include <stdbool.h> #include <pthread.h> -#include "frct.h" -#include "fmgr.h" -#include "ribmgr.h" - enum conn_state { CONN_PENDING = 0, CONN_ESTABLISHED @@ -285,7 +285,7 @@ cep_id_t frct_i_create(uint64_t address, pci.pdu_type = PDU_TYPE_MGMT; pci.dst_addr = address; - pci.src_addr = ribmgr_address(); + pci.src_addr = ipcpi.address; pci.dst_cep_id = 0; pci.src_cep_id = id; pci.seqno = 0; @@ -330,7 +330,7 @@ int frct_i_accept(cep_id_t id, pci.pdu_type = PDU_TYPE_MGMT; pci.dst_addr = instance->r_address; - pci.src_addr = ribmgr_address(); + pci.src_addr = ipcpi.address; pci.dst_cep_id = instance->r_cep_id; pci.src_cep_id = instance->cep_id; pci.seqno = 0; @@ -367,7 +367,7 @@ int frct_i_destroy(cep_id_t id, pci.pdu_type = PDU_TYPE_MGMT; pci.dst_addr = instance->r_address; - pci.src_addr = ribmgr_address(); + pci.src_addr = ipcpi.address; pci.dst_cep_id = instance->r_cep_id; pci.src_cep_id = instance->cep_id; pci.seqno = 0; @@ -413,7 +413,7 @@ int frct_i_write_sdu(cep_id_t id, pci.pdu_type = PDU_TYPE_DTP; pci.dst_addr = instance->r_address; - pci.src_addr = ribmgr_address(); + pci.src_addr = ipcpi.address; pci.dst_cep_id = instance->r_cep_id; pci.src_cep_id = instance->cep_id; pci.seqno = (instance->seqno)++; diff --git a/src/ipcpd/normal/gam.c b/src/ipcpd/normal/gam.c index 0e626115..c337afd0 100644 --- a/src/ipcpd/normal/gam.c +++ b/src/ipcpd/normal/gam.c @@ -27,8 +27,8 @@ #include <ouroboros/logs.h> #include <ouroboros/list.h> #include <ouroboros/errno.h> +#include <ouroboros/rib.h> -#include "ribmgr.h" #include "ipcp.h" #include "gam.h" #include "pol-gam-ops.h" @@ -72,6 +72,7 @@ struct gam * gam_create(enum pol_gam gam_type, tmp->ops = &complete_ops; break; default: + LOG_ERR("Unknown gam policy: %d.", gam_type); free(tmp); return NULL; } @@ -106,6 +107,14 @@ struct gam * gam_create(enum pol_gam gam_type, return NULL; } + if (tmp->ops->start(tmp->ops_o)) { + pthread_cond_destroy(&tmp->gas_cond); + pthread_mutex_destroy(&tmp->gas_lock); + free(tmp->ae_name); + free(tmp); + return NULL; + } + return tmp; } @@ -116,19 +125,25 @@ void gam_destroy(struct gam * instance) assert(instance); - instance->ops->destroy(instance->ops_o); + instance->ops->stop(instance->ops_o); - pthread_mutex_destroy(&instance->gas_lock); - pthread_cond_destroy(&instance->gas_cond); + pthread_mutex_lock(&instance->gas_lock); list_for_each_safe(p, n, &instance->gas) { struct ga * e = list_entry(p, struct ga, next); list_del(&e->next); + free(e->info->name); free(e->info); free(e); } + pthread_mutex_unlock(&instance->gas_lock); + + pthread_mutex_destroy(&instance->gas_lock); + pthread_cond_destroy(&instance->gas_cond); + free(instance->ae_name); + instance->ops->destroy(instance->ops_o); free(instance); } @@ -154,6 +169,8 @@ static int add_ga(struct gam * instance, pthread_cond_signal(&instance->gas_cond); pthread_mutex_unlock(&instance->gas_lock); + LOG_INFO("Added %s flow to %s.", instance->ae_name, info->name); + return 0; } @@ -170,7 +187,7 @@ int gam_flow_arr(struct gam * instance, return -1; } - cacep = cacep_create(fd, ipcpi.name, ribmgr_address()); + cacep = cacep_create(fd, ipcpi.name, ipcpi.address); if (cacep == NULL) { LOG_ERR("Failed to create CACEP instance."); return -1; @@ -187,12 +204,14 @@ int gam_flow_arr(struct gam * instance, if (instance->ops->accept_flow(instance->ops_o, qs, info)) { flow_dealloc(fd); + free(info->name); free(info); return 0; } if (add_ga(instance, fd, qs, info)) { LOG_ERR("Failed to add ga to graph adjacency manager list."); + free(info->name); free(info); return -1; } @@ -208,6 +227,7 @@ int gam_flow_alloc(struct gam * instance, struct cacep_info * info; int fd; + fd = flow_alloc(dst_name, instance->ae_name, NULL); if (fd < 0) { LOG_ERR("Failed to allocate flow to %s.", dst_name); @@ -220,7 +240,7 @@ int gam_flow_alloc(struct gam * instance, return -1; } - cacep = cacep_create(fd, ipcpi.name, ribmgr_address()); + cacep = cacep_create(fd, ipcpi.name, ipcpi.address); if (cacep == NULL) { LOG_ERR("Failed to create CACEP instance."); return -1; diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index c1bae0d6..b9cc6e57 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -3,7 +3,8 @@ * * Normal IPC Process * - * Sander Vrijders <sander.vrijders@intec.ugent.be> + * Sander Vrijders <sander.vrijders@intec.ugent.be> + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> * * 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 @@ -27,12 +28,17 @@ #include <ouroboros/ipcp-dev.h> #include <ouroboros/time_utils.h> #include <ouroboros/irm.h> +#include <ouroboros/rib.h> +#include <ouroboros/irm_config.h> +#include "addr_auth.h" +#include "ae.h" +#include "dir.h" +#include "enroll.h" #include "fmgr.h" -#include "ribmgr.h" -#include "ipcp.h" #include "frct.h" -#include "dir.h" +#include "ipcp.h" +#include "ribmgr.h" #include <stdbool.h> #include <signal.h> @@ -40,13 +46,19 @@ #include <pthread.h> #include <string.h> #include <errno.h> +#include <assert.h> -#define THIS_TYPE IPCP_NORMAL +#define DLR "/" +#define DIF_PATH DLR DIF_NAME +#define BOOT_PATH DLR BOOT_NAME +#define MEMBERS_PATH DLR MEMBERS_NAME -/* global for trapping signal */ -int irmd_api; +#define THIS_TYPE IPCP_NORMAL -pthread_t acceptor; +struct { + pthread_t acceptor; + struct addr_auth * auth; +} normal; void ipcp_sig_handler(int sig, siginfo_t * info, @@ -101,8 +113,10 @@ static void * flow_acceptor(void * o) LOG_DBG("New flow allocation request for AE %s.", ae_name); - if (strcmp(ae_name, MGMT_AE) == 0) { - ribmgr_add_nm1_flow(fd); + if (strcmp(ae_name, ENROLL_AE) == 0) { + enroll_handle(fd); + } else if (strcmp(ae_name, MGMT_AE) == 0) { + ribmgr_flow_arr(fd, qs); } else if (strcmp(ae_name, DT_AE) == 0) { fmgr_nm1_flow_arr(fd, qs); } else { @@ -119,164 +133,269 @@ static void * flow_acceptor(void * o) return (void *) 0; } -static int normal_ipcp_enroll(char * dst_name) +/* + * Boots the IPCP off information in the rib. + * Common function after bootstrap or enroll. + * Call under ipcpi.state_lock + */ +static int boot_components(void) { - int ret; + char buf[256]; + ssize_t len; + enum pol_addr_auth pa; - pthread_rwlock_wrlock(&ipcpi.state_lock); + len = rib_read(DIF_PATH, &buf, 256); + if (len < 0) { + LOG_ERR("Failed to read DIF name: %ld.", len); + return -1; + } - if (ipcp_get_state() != IPCP_INIT) { - pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Won't enroll an IPCP that is not in INIT."); - return -1; /* -ENOTINIT */ + ipcpi.data->dif_name = strdup(buf); + if (ipcpi.data->dif_name == NULL) { + LOG_ERR("Failed to set DIF name."); + return -1; } - if (ribmgr_init()) { - LOG_ERR("Failed to initialise RIB manager."); - pthread_rwlock_unlock(&ipcpi.state_lock); + if (rib_add(MEMBERS_PATH, ipcpi.name)) { + LOG_WARN("Failed to add name to " MEMBERS_PATH); return -1; } - if (ribmgr_nm1_mgt_flow(dst_name)) { - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); - LOG_ERR("Failed to establish management flow."); - pthread_rwlock_unlock(&ipcpi.state_lock); + LOG_DBG("Starting components."); + + if (rib_read(BOOT_PATH "/addr_auth/type", &pa, sizeof(pa)) + != sizeof(pa)) { + LOG_ERR("Failed to read policy for address authority."); return -1; } - ret = ribmgr_enrol(); - if (ret < 0) { - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); - pthread_rwlock_unlock(&ipcpi.state_lock); - if (ret == -ETIMEDOUT) - LOG_ERR("Enrollment timed out."); - else - LOG_ERR("Failed to enrol IPCP: %d.", ret); + normal.auth = addr_auth_create(pa); + if (normal.auth == NULL) { + LOG_ERR("Failed to init address authority."); return -1; } - if (ribmgr_start_policies()) { - pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to start policies."); + ipcpi.address = normal.auth->address(); + if (ipcpi.address == 0) { + LOG_ERR("Failed to get a valid address."); + addr_auth_destroy(normal.auth); + return -1; + } + + LOG_DBG("IPCP got address %lu.", ipcpi.address); + + LOG_DBG("Starting ribmgr."); + + if (ribmgr_init()) { + LOG_ERR("Failed to initialize RIB manager."); + addr_auth_destroy(normal.auth); return -1; } + if (dir_init()) { + LOG_ERR("Failed to initialize directory."); + ribmgr_fini(); + addr_auth_destroy(normal.auth); + return -1; + } + + LOG_DBG("Ribmgr started."); + if (fmgr_init()) { - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); - pthread_rwlock_unlock(&ipcpi.state_lock); + dir_fini(); + ribmgr_fini(); + addr_auth_destroy(normal.auth); LOG_ERR("Failed to start flow manager."); return -1; } if (frct_init()) { - if (fmgr_fini()) - LOG_WARN("Failed to finalize flow manager."); - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); - pthread_rwlock_unlock(&ipcpi.state_lock); + fmgr_fini(); + dir_fini(); + ribmgr_fini(); + addr_auth_destroy(normal.auth); LOG_ERR("Failed to initialize FRCT."); return -1; } ipcp_set_state(IPCP_OPERATIONAL); - if (pthread_create(&acceptor, NULL, flow_acceptor, NULL)) { - if (frct_fini()) - LOG_WARN("Failed to finalize frct."); - if (fmgr_fini()) - LOG_WARN("Failed to finalize flow manager."); - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); + if (pthread_create(&normal.acceptor, NULL, flow_acceptor, NULL)) { ipcp_set_state(IPCP_INIT); - pthread_rwlock_unlock(&ipcpi.state_lock); + fmgr_fini(); + dir_fini(); + ribmgr_fini(); + addr_auth_destroy(normal.auth); LOG_ERR("Failed to create acceptor thread."); return -1; } - pthread_rwlock_unlock(&ipcpi.state_lock); - - LOG_DBG("Enrolled with %s.", dst_name); - return 0; } -static int normal_ipcp_bootstrap(struct dif_config * conf) +static int normal_ipcp_enroll(char * dst_name) { - if (conf == NULL || conf->type != THIS_TYPE) { - LOG_ERR("Bad DIF configuration."); - return -EINVAL; - } - pthread_rwlock_wrlock(&ipcpi.state_lock); if (ipcp_get_state() != IPCP_INIT) { pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Won't bootstrap an IPCP that is not in INIT."); + LOG_ERR("IPCP in wrong state."); return -1; /* -ENOTINIT */ } - ipcpi.data->dif_name = strdup(conf->dif_name); - if (ipcpi.data->dif_name == NULL) { + if (rib_add(RIB_ROOT, MEMBERS_NAME)) { pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to set DIF name."); + LOG_ERR("Failed to create members."); return -1; } - if (ribmgr_init()) { - LOG_ERR("Failed to initialise RIB manager."); + /* Get boot state from peer */ + if (enroll_boot(dst_name)) { pthread_rwlock_unlock(&ipcpi.state_lock); + LOG_ERR("Failed to boot IPCP components."); return -1; } - if (ribmgr_bootstrap(conf)) { - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); + if (boot_components()) { pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to bootstrap RIB manager."); + LOG_ERR("Failed to boot IPCP components."); return -1; } - if (ribmgr_start_policies()) { - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); + pthread_rwlock_unlock(&ipcpi.state_lock); + + LOG_DBG("Enrolled with %s.", dst_name); + + return 0; +} + +const struct ros { + char * parent; + char * child; +} ros[] = { + /* GENERAL IPCP INFO */ + {RIB_ROOT, DIF_NAME}, + /* BOOT INFO */ + {RIB_ROOT, BOOT_NAME}, + /* OTHER RIB STRUCTURES */ + {RIB_ROOT, MEMBERS_NAME}, + /* DT COMPONENT */ + {BOOT_PATH, "dt"}, + + {BOOT_PATH "/dt", "gam"}, + {BOOT_PATH "/dt/gam", "type"}, + {BOOT_PATH "/dt/gam", "cacep"}, + {BOOT_PATH "/dt", "const"}, + {BOOT_PATH "/dt/const", "addr_size"}, + {BOOT_PATH "/dt/const", "cep_id_size"}, + {BOOT_PATH "/dt/const", "pdu_length_size"}, + {BOOT_PATH "/dt/const", "seqno_size"}, + {BOOT_PATH "/dt/const", "has_ttl"}, + {BOOT_PATH "/dt/const", "has_chk"}, + {BOOT_PATH "/dt/const", "min_pdu_size"}, + {BOOT_PATH "/dt/const", "max_pdu_size"}, + + /* RIB MGR COMPONENT */ + {BOOT_PATH, "rm"}, + + {BOOT_PATH "/rm","gam"}, + {BOOT_PATH "/rm/gam", "type"}, + {BOOT_PATH "/rm/gam", "cacep"}, + + /* ADDR AUTH COMPONENT */ + {BOOT_PATH, "addr_auth"}, + {BOOT_PATH "/addr_auth", "type"}, + {NULL, NULL} +}; + +int normal_rib_init(void) +{ + struct ros * r; + + for (r = (struct ros *) ros; r->parent; ++r) { + if (rib_add(r->parent, r->child)) { + LOG_ERR("Failed to create %s/%s", + r->parent, r->child); + return -1; + } + } + + return 0; +} + +static int normal_ipcp_bootstrap(struct dif_config * conf) +{ + /* FIXME: get CACEP policies from conf */ + enum pol_cacep pol = NO_AUTH; + + (void) pol; + + if (conf == NULL || conf->type != THIS_TYPE) { + LOG_ERR("Bad DIF configuration."); + return -EINVAL; + } + + pthread_rwlock_wrlock(&ipcpi.state_lock); + + if (ipcp_get_state() != IPCP_INIT) { pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to start policies."); - return -1; + LOG_ERR("IPCP in wrong state."); + return -1; /* -ENOTINIT */ } - if (fmgr_init()) { - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); + if (normal_rib_init()) { pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to start flow manager."); + LOG_ERR("Failed to write initial structure to the RIB."); return -1; } - if (frct_init()) { - if (fmgr_fini()) - LOG_WARN("Failed to finalize flow manager."); - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); + if (rib_write(DIF_PATH, + conf->dif_name, + strlen(conf->dif_name) + 1) || + rib_write(BOOT_PATH "/dt/const/addr_size", + &conf->addr_size, + sizeof(conf->addr_size)) || + rib_write(BOOT_PATH "/dt/const/cep_id_size", + &conf->cep_id_size, + sizeof(conf->cep_id_size)) || + rib_write(BOOT_PATH "/dt/const/seqno_size", + &conf->seqno_size, + sizeof(conf->seqno_size)) || + rib_write(BOOT_PATH "/dt/const/has_ttl", + &conf->has_ttl, + sizeof(conf->has_ttl)) || + rib_write(BOOT_PATH "/dt/const/has_chk", + &conf->has_chk, + sizeof(conf->has_chk)) || + rib_write(BOOT_PATH "/dt/const/min_pdu_size", + &conf->min_pdu_size, + sizeof(conf->min_pdu_size)) || + rib_write(BOOT_PATH "/dt/const/max_pdu_size", + &conf->max_pdu_size, + sizeof(conf->max_pdu_size)) || + rib_write(BOOT_PATH "/dt/gam/type", + &conf->dt_gam_type, + sizeof(conf->dt_gam_type)) || + rib_write(BOOT_PATH "/rm/gam/type", + &conf->rm_gam_type, + sizeof(conf->rm_gam_type)) || + rib_write(BOOT_PATH "/rm/gam/cacep", + &pol, + sizeof(pol)) || + rib_write(BOOT_PATH "/dt/gam/cacep", + &pol, + sizeof(pol)) || + rib_write(BOOT_PATH "/addr_auth/type", + &conf->addr_auth_type, + sizeof(conf->addr_auth_type))) { + LOG_ERR("Failed to write boot info to RIB."); pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to initialize FRCT."); return -1; } - ipcp_set_state(IPCP_OPERATIONAL); - - if (pthread_create(&acceptor, NULL, flow_acceptor, NULL)) { - if (frct_fini()) - LOG_WARN("Failed to finalize frct."); - if (fmgr_fini()) - LOG_WARN("Failed to finalize flow manager."); - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); - ipcp_set_state(IPCP_INIT); + if (boot_components()) { + LOG_ERR("Failed to boot IPCP components."); pthread_rwlock_unlock(&ipcpi.state_lock); - LOG_ERR("Failed to create acceptor thread."); return -1; } @@ -293,9 +412,9 @@ static struct ipcp_ops normal_ops = { .ipcp_name_reg = dir_name_reg, .ipcp_name_unreg = dir_name_unreg, .ipcp_name_query = dir_name_query, - .ipcp_flow_alloc = fmgr_np1_alloc, - .ipcp_flow_alloc_resp = fmgr_np1_alloc_resp, - .ipcp_flow_dealloc = fmgr_np1_dealloc + .ipcp_flow_alloc = NULL, /* fmgr_np1_alloc, */ + .ipcp_flow_alloc_resp = NULL, /* fmgr_np1_alloc_resp, */ + .ipcp_flow_dealloc = NULL, /* fmgr_np1_dealloc */ }; int main(int argc, @@ -338,8 +457,15 @@ int main(int argc, sigaction(SIGHUP, &sig_act, NULL); sigaction(SIGPIPE, &sig_act, NULL); + if (rib_init()) { + LOG_ERR("Failed to initialize RIB."); + close_logfile(); + exit(EXIT_FAILURE); + } + if (ipcp_init(THIS_TYPE, &normal_ops) < 0) { LOG_ERR("Failed to create instance."); + rib_fini(); close_logfile(); exit(EXIT_FAILURE); } @@ -348,6 +474,8 @@ int main(int argc, if (ipcp_boot() < 0) { LOG_ERR("Failed to boot IPCP."); + ipcp_fini(); + rib_fini(); close_logfile(); exit(EXIT_FAILURE); } @@ -357,6 +485,7 @@ int main(int argc, if (ipcp_create_r(getpid())) { LOG_ERR("Failed to notify IRMd we are initialized."); ipcp_fini(); + rib_fini(); close_logfile(); exit(EXIT_FAILURE); } @@ -364,17 +493,18 @@ int main(int argc, ipcp_shutdown(); if (ipcp_get_state() == IPCP_SHUTDOWN) { - pthread_cancel(acceptor); - pthread_join(acceptor, NULL); - - if (frct_fini()) - LOG_WARN("Failed to finalize FRCT."); - if (fmgr_fini()) - LOG_WARN("Failed to finalize flow manager."); - if (ribmgr_fini()) - LOG_WARN("Failed to finalize RIB manager."); + pthread_cancel(normal.acceptor); + pthread_join(normal.acceptor, NULL); } + ribmgr_fini(); + + dir_fini(); + + addr_auth_destroy(normal.auth); + + rib_fini(); + ipcp_fini(); close_logfile(); diff --git a/src/ipcpd/normal/pathname.c b/src/ipcpd/normal/pathname.c deleted file mode 100644 index d6d4fd79..00000000 --- a/src/ipcpd/normal/pathname.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Functions to construct pathnames - * - * Sander Vrijders <sander.vrijders@intec.ugent.be> - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define OUROBOROS_PREFIX "pathnames" - -#include <ouroboros/config.h> -#include <ouroboros/logs.h> -#include <ouroboros/errno.h> - -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "pathname.h" - -char * pathname_create(const char * name) -{ - char * tmp; - - assert(name); - - tmp = malloc(strlen(name) + strlen(PATH_DELIMITER) + 1); - if (tmp == NULL) - return NULL; - - strcpy(tmp, PATH_DELIMITER); - strcat(tmp, name); - - return tmp; -} - -char * pathname_append(char * pname, - const char * name) -{ - char * tmp; - - assert(pname); - assert(name); - - tmp = malloc(strlen(pname) + - strlen(PATH_DELIMITER) + - strlen(name) + 1); - if (tmp == NULL) - return NULL; - - strcpy(tmp, pname); - strcat(tmp, PATH_DELIMITER); - strcat(tmp, name); - - free(pname); - - return tmp; -} - -void pathname_destroy(char * pname) -{ - free(pname); -} diff --git a/src/ipcpd/normal/pathname.h b/src/ipcpd/normal/pathname.h deleted file mode 100644 index 1d7fffa2..00000000 --- a/src/ipcpd/normal/pathname.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Functions to construct pathnames - * - * Sander Vrijders <sander.vrijders@intec.ugent.be> - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_PATHNAME_H -#define OUROBOROS_IPCPD_NORMAL_PATHNAME_H - -#define PATH_DELIMITER "/" - -char * pathname_create(const char * name); - -char * pathname_append(char * pname, - const char * name); - -void pathname_destroy(char * pname); - -#endif /* OUROBOROS_IPCPD_NORMAL_PATHNAME_H */ diff --git a/src/ipcpd/normal/pol-gam-ops.h b/src/ipcpd/normal/pol-gam-ops.h index eeece8d9..0721136c 100644 --- a/src/ipcpd/normal/pol-gam-ops.h +++ b/src/ipcpd/normal/pol-gam-ops.h @@ -30,6 +30,10 @@ struct pol_gam_ops { void (* destroy)(void * o); + int (* start)(void * o); + + int (* stop)(void * o); + int (* accept_new_flow)(void * o); int (* accept_flow)(void * o, 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 <ouroboros/logs.h> #include <ouroboros/list.h> #include <ouroboros/qos.h> +#include <ouroboros/rib.h> -#include "pathname.h" -#include "ro.h" #include "ipcp.h" #include "gam.h" #include <string.h> #include <stdlib.h> - -#define RO_DIR "neighbors" +#include <assert.h> 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@intec.ugent.be> + * Sander Vrijders <sander.vrijders@intec.ugent.be> + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> * * 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; } diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index 993fe62a..4ff316dc 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -27,1670 +27,103 @@ #include <ouroboros/list.h> #include <ouroboros/time_utils.h> #include <ouroboros/ipcp-dev.h> -#include <ouroboros/bitmap.h> #include <ouroboros/errno.h> #include <ouroboros/dev.h> +#include <ouroboros/fqueue.h> +#include <ouroboros/rib.h> #include "timerwheel.h" #include "addr_auth.h" #include "ribmgr.h" -#include "dt_const.h" -#include "ro.h" -#include "pathname.h" -#include "dir.h" +#include "gam.h" #include "ae.h" #include <stdlib.h> #include <pthread.h> #include <string.h> #include <errno.h> +#include <assert.h> -#include "static_info.pb-c.h" -typedef StaticInfoMsg static_info_msg_t; +#define BOOT_PATH "/" BOOT_NAME -#include "ro.pb-c.h" -typedef RoMsg ro_msg_t; - -#define SUBS_SIZE 25 -#define WHEEL_RESOLUTION 1000 /* ms */ -#define WHEEL_DELAY 3600000 /* ms */ -#define RO_ID_TIMEOUT 1000 /* ms */ - -#define ENROLLMENT "enrollment" - -#define RIBMGR_PREFIX PATH_DELIMITER "ribmgr" -#define STAT_INFO PATH_DELIMITER "statinfo" - -/* RIB objects */ -struct rnode { - char * name; - char * full_name; - uint64_t seqno; - - /* - * NOTE: Naive implementation for now, could be replaced by - * for instance taking a hash of the pathname and using that - * as an index in a B-tree - */ - - /* If there are no children, this is a leaf. */ - struct rnode * child; - struct rnode * sibling; - - struct ro_attr attr; - uint8_t * data; - size_t len; -}; - -struct mgmt_flow { - struct list_head next; - - struct cdap * instance; - int fd; - - pthread_t handler; -}; - -struct ro_sub { - struct list_head next; - - int sid; - - char * name; - struct ro_sub_ops * ops; -}; - -struct ro_id { - struct list_head next; - - uint64_t seqno; - char * full_name; -}; - -enum ribmgr_state { - RIBMGR_NULL, - RIBMGR_INIT, - RIBMGR_OPERATIONAL, - RIBMGR_SHUTDOWN -}; - -/* FIXME: Extract rib from ribmgr. */ struct { - struct rnode * root; - pthread_mutex_t ro_lock; - - struct list_head subs; - struct bmp * sids; - pthread_mutex_t subs_lock; - int ribmgr_sid; - - struct dt_const dtc; - - uint64_t address; - - struct timerwheel * wheel; - - struct list_head ro_ids; - pthread_mutex_t ro_ids_lock; - - struct list_head flows; - pthread_rwlock_t flows_lock; - - struct addr_auth * addr_auth; - enum pol_addr_auth addr_auth_type; - - enum pol_gam dt_gam_type; - - enum ribmgr_state state; - pthread_cond_t state_cond; - pthread_mutex_t state_lock; -} rib; - -void ribmgr_ro_created(const char * name, - uint8_t * data, - size_t len) -{ - static_info_msg_t * stat_msg; - - if (strcmp(name, RIBMGR_PREFIX STAT_INFO) == 0) { - LOG_DBG("Received static DIF information."); - - stat_msg = static_info_msg__unpack(NULL, len, data); - if (stat_msg == NULL) { - LOG_ERR("Failed to unpack static info message."); - return; - } - - rib.dtc.addr_size = stat_msg->addr_size; - rib.dtc.cep_id_size = stat_msg->cep_id_size; - rib.dtc.pdu_length_size = stat_msg->pdu_length_size; - rib.dtc.seqno_size = stat_msg->seqno_size; - rib.dtc.has_ttl = stat_msg->has_ttl; - rib.dtc.has_chk = stat_msg->has_chk; - rib.dtc.min_pdu_size = stat_msg->min_pdu_size; - rib.dtc.max_pdu_size = stat_msg->max_pdu_size; - rib.addr_auth_type = stat_msg->addr_auth_type; - rib.dt_gam_type = stat_msg->dt_gam_type; - - static_info_msg__free_unpacked(stat_msg, NULL); - } -} - -/* We only have a create operation for now. */ -static struct ro_sub_ops ribmgr_sub_ops = { - .ro_created = ribmgr_ro_created, - .ro_updated = NULL, - .ro_deleted = NULL -}; - -static struct rnode * find_rnode_by_name(const char * name) -{ - char * str; - char * str1; - char * token; - struct rnode * node; - - str = strdup(name); - if (str == NULL) - return NULL; - - node = rib.root; - - for (str1 = str; node != NULL; str1 = NULL) { - token = strtok(str1, PATH_DELIMITER); - if (token == NULL) - break; - - node = node->child; - - while (node != NULL) - if (strcmp(node->name, token) == 0) - break; - else - node = node->sibling; - } - - free(str); - return node; -} - -/* Call under RIB object lock. */ -static int ro_msg_create(struct rnode * node, - ro_msg_t * msg) -{ - msg->address = rib.address; - msg->seqno = node->seqno; - msg->recv_set = node->attr.recv_set; - msg->enrol_sync = node->attr.enrol_sync; - msg->sec = node->attr.expiry.tv_sec; - msg->nsec = node->attr.expiry.tv_nsec; - msg->value.data = node->data; - msg->value.len = node->len; - - return 0; -} - -static int ribmgr_ro_delete(const char * name) -{ - char * str; - char * str1; - char * saveptr; - char * token; - struct rnode * node; - struct rnode * prev; - bool sibling = false; - - str = strdup(name); - if (str == NULL) - return -1; - - node = rib.root; - prev = NULL; - - for (str1 = str; ; str1 = NULL) { - token = strtok_r(str1, PATH_DELIMITER, &saveptr); - if (token == NULL) - break; - - prev = node; - node = node->child; - sibling = false; - - while (node != NULL) { - if (strcmp(node->name, token) == 0) { - break; - } else { - prev = node; - node = node->sibling; - sibling = true; - } - } - - if (node == NULL) { - free(str); - return -1; - } - } - - if (node == rib.root) { - LOG_ERR("Won't remove root."); - free(str); - return -1; - } - - free(node->name); - free(node->full_name); - if (node->data != NULL) - free(node->data); - - if (sibling) - prev->sibling = node->sibling; - else - prev->child = node->sibling; - - free(node); - free(str); - - LOG_DBG("Deleted RO with name %s.", name); - - return 0; -} - -static void ro_delete_timer(void * o) -{ - char * name = (char *) o; - - pthread_mutex_lock(&rib.ro_lock); - - if (ribmgr_ro_delete(name)) - LOG_ERR("Failed to delete %s.", name); - - pthread_mutex_unlock(&rib.ro_lock); -} - -static struct rnode * ribmgr_ro_create(const char * name, - struct ro_attr attr, - uint8_t * data, - size_t len) -{ - char * str; - char * str1; - char * saveptr = NULL; - char * token = NULL; - char * token2; - struct rnode * node = NULL; - struct rnode * new = NULL; - struct rnode * prev = NULL; - bool sibling = false; - int timeout; - - str = strdup(name); - if (str == NULL) - return NULL; - - node = rib.root; - - assert(node); - - for (str1 = str; node != NULL; str1 = NULL) { - token = strtok_r(str1, PATH_DELIMITER, &saveptr); - if (token == NULL) { - LOG_ERR("RO already exists."); - free(str); - return NULL; - } - - prev = node; - node = node->child; - sibling = false; - - /* Search horizontally. */ - while (node != NULL) { - if (strcmp(node->name, token) == 0) { - break; - } else { - prev = node; - node = node->sibling; - sibling = true; - } - } - } - - assert(token); - assert(prev); - - token2 = strtok_r(NULL, PATH_DELIMITER, &saveptr); - if (token2 != NULL) { - LOG_ERR("Part of the pathname does not exist."); - free(str); - return NULL; - } - - new = malloc(sizeof(*new)); - if (new == NULL) { - free(str); - return NULL; - } - - new->name = strdup(token); - if (new->name == NULL) { - free(str); - free(new); - return NULL; - } - - free(str); - - new->full_name = strdup(name); - if (new->full_name == NULL) { - free(new); - return NULL; - } - - new->seqno = 0; - new->attr = attr; - - if (sibling) - prev->sibling = new; - else - prev->child = new; - - new->data = data; - new->len = len; - new->child = NULL; - new->sibling = NULL; - - LOG_DBG("Created RO with name %s.", name); - - if (!(attr.expiry.tv_sec == 0 && attr.expiry.tv_nsec == 0)) { - timeout = attr.expiry.tv_sec * 1000 + - attr.expiry.tv_nsec / MILLION; - if (timerwheel_add(rib.wheel, ro_delete_timer, new->full_name, - strlen(new->full_name) + 1, timeout)) - LOG_ERR("Failed to add deletion timer of RO."); - } - - return new; -} - -static struct rnode * ribmgr_ro_write(const char * name, - uint8_t * data, - size_t len) -{ - struct rnode * node; - - node = find_rnode_by_name(name); - if (node == NULL) - return NULL; - - free(node->data); - - node->data = data; - node->len = len; - - LOG_DBG("Updated RO with name %s.", name); - - return node; -} - -static int write_ro_msg(struct cdap * neighbor, - ro_msg_t * msg, - char * name, - enum cdap_opcode code) -{ - uint8_t * data; - size_t len; - cdap_key_t key; - int ret; - - len = ro_msg__get_packed_size(msg); - if (len == 0) - return -1; - - data = malloc(len); - if (data == NULL) - return -ENOMEM; - - ro_msg__pack(msg, data); - - key = cdap_request_send(neighbor, code, name, data, len, 0); - if (key < 0) { - LOG_ERR("Failed to send CDAP request."); - free(data); - return -1; - } - - free(data); - - ret = cdap_reply_wait(neighbor, key, NULL, NULL); - if (ret < 0) { - LOG_ERR("CDAP command with code %d and name %s failed: %d.", - code, name, ret); - return -1; - } - - return 0; -} - -int ribmgr_init() -{ - list_head_init(&rib.flows); - list_head_init(&rib.subs); - list_head_init(&rib.ro_ids); - - rib.root = malloc(sizeof(*(rib.root))); - if (rib.root == NULL) - return -1; - - rib.root->name = "root"; - rib.root->child = NULL; - rib.root->sibling = NULL; - - if (pthread_rwlock_init(&rib.flows_lock, NULL)) { - LOG_ERR("Failed to initialize rwlock."); - free(rib.root); - return -1; - } - - if (pthread_mutex_init(&rib.ro_lock, NULL)) { - LOG_ERR("Failed to initialize mutex."); - pthread_rwlock_destroy(&rib.flows_lock); - free(rib.root); - return -1; - } - - if (pthread_mutex_init(&rib.subs_lock, NULL)) { - LOG_ERR("Failed to initialize mutex."); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - free(rib.root); - return -1; - } - - if (pthread_mutex_init(&rib.ro_ids_lock, NULL)) { - LOG_ERR("Failed to initialize mutex."); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_mutex_destroy(&rib.subs_lock); - free(rib.root); - return -1; - } - - rib.sids = bmp_create(SUBS_SIZE, 0); - if (rib.sids == NULL) { - LOG_ERR("Failed to create bitmap."); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_mutex_destroy(&rib.subs_lock); - pthread_mutex_destroy(&rib.ro_ids_lock); - free(rib.root); - return -1; - } - - rib.wheel = timerwheel_create(WHEEL_RESOLUTION, WHEEL_DELAY); - if (rib.wheel == NULL) { - LOG_ERR("Failed to create timerwheel."); - bmp_destroy(rib.sids); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_mutex_destroy(&rib.subs_lock); - pthread_mutex_destroy(&rib.ro_ids_lock); - free(rib.root); - return -1; - } - - rib.ribmgr_sid = ro_subscribe(RIBMGR_PREFIX, &ribmgr_sub_ops); - if (rib.ribmgr_sid < 0) { - LOG_ERR("Failed to subscribe."); - timerwheel_destroy(rib.wheel); - bmp_destroy(rib.sids); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_mutex_destroy(&rib.subs_lock); - pthread_mutex_destroy(&rib.ro_ids_lock); - free(rib.root); - return -1; - } - - if (pthread_cond_init(&rib.state_cond, NULL)) { - LOG_ERR("Failed to init condvar."); - timerwheel_destroy(rib.wheel); - bmp_destroy(rib.sids); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_mutex_destroy(&rib.subs_lock); - pthread_mutex_destroy(&rib.ro_ids_lock); - free(rib.root); - return -1; - } - - if (pthread_mutex_init(&rib.state_lock, NULL)) { - LOG_ERR("Failed to init mutex."); - pthread_cond_destroy(&rib.state_cond); - timerwheel_destroy(rib.wheel); - bmp_destroy(rib.sids); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_mutex_destroy(&rib.subs_lock); - pthread_mutex_destroy(&rib.ro_ids_lock); - free(rib.root); - return -1; - } - - rib.state = RIBMGR_INIT; - - return 0; -} - -static enum ribmgr_state ribmgr_get_state(void) -{ - enum ribmgr_state state; - - pthread_mutex_lock(&rib.state_lock); - - state = rib.state; - - pthread_mutex_unlock(&rib.state_lock); - - return state; -} - -static void ribmgr_set_state(enum ribmgr_state state) -{ - pthread_mutex_lock(&rib.state_lock); - - rib.state = state; - - pthread_cond_broadcast(&rib.state_cond); - - pthread_mutex_unlock(&rib.state_lock); -} - -static int ribmgr_wait_state(enum ribmgr_state state, - const struct timespec * timeout) -{ - struct timespec abstime; - int ret = 0; - - clock_gettime(PTHREAD_COND_CLOCK, &abstime); - ts_add(&abstime, timeout, &abstime); - - pthread_mutex_lock(&rib.state_lock); - - while (rib.state != state - && rib.state != RIBMGR_SHUTDOWN - && rib.state != RIBMGR_NULL) { - if (timeout == NULL) - ret = -pthread_cond_wait(&rib.state_cond, - &rib.state_lock); - else - ret = -pthread_cond_timedwait(&rib.state_cond, - &rib.state_lock, - &abstime); - } - - pthread_mutex_unlock(&rib.state_lock); - - return ret; -} - -static void rtree_destroy(struct rnode * node) -{ - if (node != NULL) { - rtree_destroy(node->child); - rtree_destroy(node->sibling); - free(node->name); - if (node->data != NULL) - free(node->data); - free(node); - } -} - -int ribmgr_fini() -{ - struct list_head * pos = NULL; - struct list_head * n = NULL; - - pthread_mutex_lock(&rib.state_lock); - rib.state = RIBMGR_SHUTDOWN; - pthread_cond_broadcast(&rib.state_cond); - pthread_mutex_unlock(&rib.state_lock); - - pthread_rwlock_wrlock(&rib.flows_lock); - - list_for_each_safe(pos, n, &rib.flows) { - struct mgmt_flow * flow = - list_entry(pos, struct mgmt_flow, next); - if (cdap_destroy(flow->instance)) - LOG_ERR("Failed to destroy CDAP instance."); - list_del(&flow->next); - free(flow); - } - - pthread_rwlock_unlock(&rib.flows_lock); - - ro_unsubscribe(rib.ribmgr_sid); - - if (rib.addr_auth != NULL) - addr_auth_destroy(rib.addr_auth); - - pthread_mutex_lock(&rib.ro_lock); - - rtree_destroy(rib.root->child); - free(rib.root); - - pthread_mutex_unlock(&rib.ro_lock); - - bmp_destroy(rib.sids); - timerwheel_destroy(rib.wheel); - - pthread_mutex_destroy(&rib.subs_lock); - pthread_mutex_destroy(&rib.ro_lock); - pthread_rwlock_destroy(&rib.flows_lock); - pthread_mutex_destroy(&rib.ro_ids_lock); - - pthread_cond_destroy(&rib.state_cond); - pthread_mutex_destroy(&rib.state_lock); - - return 0; -} - -static int ribmgr_cdap_create(struct cdap * instance, - cdap_key_t key, - char * name, - ro_msg_t * msg) -{ - int ret = 0; - struct list_head * p = NULL; - size_t len_s, len_n; - uint8_t * ro_data; - struct ro_attr attr; - struct rnode * node; - - assert(instance); - - ro_attr_init(&attr); - attr.expiry.tv_sec = msg->sec; - attr.expiry.tv_nsec = msg->nsec; - attr.enrol_sync = msg->enrol_sync; - attr.recv_set = msg->recv_set; - - pthread_mutex_lock(&rib.ro_lock); - - ro_data = malloc(msg->value.len); - if (ro_data == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - cdap_reply_send(instance, key, -1, NULL, 0); - return -1; - } - memcpy(ro_data, msg->value.data, msg->value.len); - - node = ribmgr_ro_create(name, attr, ro_data, msg->value.len); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - cdap_reply_send(instance, key, -1, NULL, 0); - free(ro_data); - return -1; - } - - pthread_mutex_lock(&rib.subs_lock); - list_for_each(p, &rib.subs) { - struct ro_sub * e = list_entry(p, struct ro_sub, next); - len_s = strlen(e->name); - len_n = strlen(name); - - if (len_n < len_s) - continue; - - if (memcmp(name, e->name, len_s) == 0) { - if (e->ops->ro_created == NULL) - continue; - - ro_data = malloc(node->len); - if (ro_data == NULL) - continue; - - memcpy(ro_data, node->data, node->len); - e->ops->ro_created(name, ro_data, node->len); - } - } - - pthread_mutex_unlock(&rib.subs_lock); - pthread_mutex_unlock(&rib.ro_lock); - - if (cdap_reply_send(instance, key, ret, NULL, 0)) { - LOG_ERR("Failed to send reply to create request."); - return -1; - } - - return 0; -} - -static int ribmgr_cdap_delete(struct cdap * instance, - cdap_key_t key, - char * name) -{ - struct list_head * p = NULL; - size_t len_s; - size_t len_n; - - pthread_mutex_lock(&rib.ro_lock); - - if (ribmgr_ro_delete(name)) { - pthread_mutex_unlock(&rib.ro_lock); - cdap_reply_send(instance, key, -1, NULL, 0); - return -1; - } - - pthread_mutex_lock(&rib.subs_lock); - - list_for_each(p, &rib.subs) { - struct ro_sub * e = list_entry(p, struct ro_sub, next); - len_s = strlen(e->name); - len_n = strlen(name); - - if (len_n < len_s) - continue; - - if (memcmp(name, e->name, len_s) == 0) { - if (e->ops->ro_deleted == NULL) - continue; - - e->ops->ro_deleted(name); - } - } - - pthread_mutex_unlock(&rib.subs_lock); - pthread_mutex_unlock(&rib.ro_lock); - - if (cdap_reply_send(instance, key, 0, NULL, 0)) { - LOG_ERR("Failed to send reply to create request."); - return -1; - } - - return 0; -} - -static int ribmgr_cdap_write(struct cdap * instance, - cdap_key_t key, - char * name, - ro_msg_t * msg, - uint32_t flags) -{ - int ret = 0; - struct list_head * p = NULL; - size_t len_s; - size_t len_n; - uint8_t * ro_data; - struct rnode * node; - - (void) flags; - - pthread_mutex_lock(&rib.ro_lock); - - ro_data = malloc(msg->value.len); - if (ro_data == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - cdap_reply_send(instance, key, -1, NULL, 0); - return -1; - } - memcpy(ro_data, msg->value.data, msg->value.len); - - node = ribmgr_ro_write(name, msg->value.data, msg->value.len); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - free(ro_data); - cdap_reply_send(instance, key, -1, NULL, 0); - return -1; - } - node->seqno = msg->seqno; - - pthread_mutex_lock(&rib.subs_lock); - - list_for_each(p, &rib.subs) { - struct ro_sub * e = list_entry(p, struct ro_sub, next); - len_s = strlen(e->name); - len_n = strlen(name); - - if (len_n < len_s) - continue; - - if (memcmp(name, e->name, len_s) == 0) { - if (e->ops->ro_updated == NULL) - continue; - - ro_data = malloc(node->len); - if (ro_data == NULL) - continue; - - memcpy(ro_data, node->data, node->len); - e->ops->ro_updated(name, ro_data, node->len); - } - } - - pthread_mutex_unlock(&rib.subs_lock); - pthread_mutex_unlock(&rib.ro_lock); - - if (cdap_reply_send(instance, key, ret, NULL, 0)) { - LOG_ERR("Failed to send reply to write request."); - return -1; - } + flow_set_t * fs; + fqueue_t * fq; + struct gam * gam; +} ribmgr; - return 0; -} - -static int ribmgr_enrol_sync(struct cdap * instance, struct rnode * node) -{ - int ret = 0; - - if (node != NULL) { - if (node->attr.enrol_sync == true) { - ro_msg_t msg = RO_MSG__INIT; - - if (ro_msg_create(node, &msg)) { - LOG_ERR("Failed to create RO msg."); - return -1; - } - - LOG_DBG("Syncing RO with name %s.", node->full_name); - - if (write_ro_msg(instance, &msg, - node->full_name, CDAP_CREATE)) { - LOG_ERR("Failed to send RO msg."); - return -1; - } - } - - ret = ribmgr_enrol_sync(instance, node->child); - if (ret == 0) - ret = ribmgr_enrol_sync(instance, node->sibling); - } - - return ret; -} - -static int ribmgr_cdap_start(struct cdap * instance, - cdap_key_t key, - char * name) -{ - if (strcmp(name, ENROLLMENT) == 0) { - LOG_DBG("New enrollment request."); - - if (cdap_reply_send(instance, key, 0, NULL, 0)) { - LOG_ERR("Failed to send reply to enrollment request."); - return -1; - } - - /* Loop through rtree and send correct objects. */ - LOG_DBG("Sending ROs that need to be sent on enrolment..."); - - pthread_mutex_lock(&rib.ro_lock); - if (ribmgr_enrol_sync(instance, rib.root->child)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to sync part of the RIB."); - return -1; - } - - pthread_mutex_unlock(&rib.ro_lock); - - LOG_DBGF("Sending stop enrollment..."); - - key = cdap_request_send(instance, CDAP_STOP, ENROLLMENT, - NULL, 0, 0); - if (key < 0) { - LOG_ERR("Failed to send stop of enrollment."); - return -1; - } - - if (cdap_reply_wait(instance, key, NULL, NULL)) { - LOG_ERR("Remote failed to complete enrollment."); - return -1; - } - } else { - LOG_WARN("Request to start unknown operation."); - if (cdap_reply_send(instance, key, -1, NULL, 0)) - LOG_ERR("Failed to send negative reply."); - } - - return 0; -} - -static int ribmgr_cdap_stop(struct cdap * instance, cdap_key_t key, char * name) -{ - int ret = 0; - - if (strcmp(name, ENROLLMENT) == 0) { - LOG_DBG("Stop enrollment received."); - /* FIXME: don't use states to match start to stop. */ - ribmgr_set_state(RIBMGR_OPERATIONAL); - } else { - ret = -1; - } - - if (cdap_reply_send(instance, key, ret, NULL, 0)) { - LOG_ERR("Failed to send reply to stop request."); - return -1; - } - - return 0; -} - -static void ro_id_delete(void * o) -{ - struct ro_id * ro_id = *((struct ro_id **) o); - - pthread_mutex_lock(&rib.ro_ids_lock); - list_del(&ro_id->next); - free(ro_id->full_name); - free(ro_id); - pthread_mutex_unlock(&rib.ro_ids_lock); -} - -static int ro_id_create(char * name, ro_msg_t * msg) -{ - struct ro_id * tmp; - - tmp = malloc(sizeof(*tmp)); - if (tmp == NULL) - return -ENOMEM; - - tmp->seqno = msg->seqno; - tmp->full_name = strdup(name); - list_head_init(&tmp->next); - - if (tmp->full_name == NULL) { - free(tmp); - return -ENOMEM; - } - - pthread_mutex_lock(&rib.ro_ids_lock); - list_add(&tmp->next, &rib.ro_ids); - - if (timerwheel_add(rib.wheel, ro_id_delete, - &tmp, sizeof(tmp), RO_ID_TIMEOUT)) { - LOG_ERR("Failed to add item to timerwheel."); - pthread_mutex_unlock(&rib.ro_ids_lock); - free(tmp->full_name); - free(tmp); - return -1; - } - pthread_mutex_unlock(&rib.ro_ids_lock); - - return 0; -} - -static void * cdap_req_handler(void * o) -{ - struct cdap * instance = (struct cdap *) o; - enum cdap_opcode opcode; - char * name; - uint8_t * data; - size_t len; - uint32_t flags; - ro_msg_t * msg; - struct list_head * p = NULL; - - assert(instance); - - while (true) { - cdap_key_t key = cdap_request_wait(instance, - &opcode, - &name, - &data, - &len, - &flags); - assert(key >= 0); - - if (opcode == CDAP_START) { - if (ribmgr_cdap_start(instance, key, name)) - LOG_WARN("CDAP start failed."); - free(name); - continue; - } - else if (opcode == CDAP_STOP) { - if (ribmgr_cdap_stop(instance, key, name)) - LOG_WARN("CDAP stop failed."); - free(name); - continue; - } - - assert(len > 0); - - msg = ro_msg__unpack(NULL, len, data); - if (msg == NULL) { - cdap_reply_send(instance, key, -1, NULL, 0); - LOG_WARN("Failed to unpack RO message"); - free(data); - continue; - } - - pthread_mutex_lock(&rib.ro_ids_lock); - list_for_each(p, &rib.ro_ids) { - struct ro_id * e = list_entry(p, struct ro_id, next); - - if (strcmp(e->full_name, name) == 0 && - e->seqno == msg->seqno) { - pthread_mutex_unlock(&rib.ro_ids_lock); - ro_msg__free_unpacked(msg, NULL); - cdap_reply_send(instance, key, 0, NULL, 0); - LOG_DBG("Already received this RO."); - free(name); - continue; - } - } - pthread_mutex_unlock(&rib.ro_ids_lock); - - if (opcode == CDAP_CREATE) { - if (ribmgr_cdap_create(instance, key, name, msg)) { - LOG_WARN("CDAP create failed."); - ro_msg__free_unpacked(msg, NULL); - free(name); - continue; - } - } else if (opcode == CDAP_WRITE) { - if (ribmgr_cdap_write(instance, key, name, - msg, flags)) { - LOG_WARN("CDAP write failed."); - ro_msg__free_unpacked(msg, NULL); - free(name); - continue; - } - } else if (opcode == CDAP_DELETE) { - if (ribmgr_cdap_delete(instance, key, name)) { - LOG_WARN("CDAP delete failed."); - ro_msg__free_unpacked(msg, NULL); - free(name); - continue; - } - } else { - LOG_INFO("Unsupported opcode received."); - ro_msg__free_unpacked(msg, NULL); - cdap_reply_send(instance, key, -1, NULL, 0); - free(name); - continue; - } - - if (ro_id_create(name, msg)) { - LOG_WARN("Failed to create RO id."); - ro_msg__free_unpacked(msg, NULL); - free(name); - continue; - } - - if (msg->recv_set == ALL_MEMBERS) { - pthread_rwlock_rdlock(&rib.flows_lock); - list_for_each(p, &rib.flows) { - struct mgmt_flow * e = - list_entry(p, struct mgmt_flow, next); - - /* Don't send it back. */ - if (e->instance == instance) - continue; - - if (write_ro_msg(e->instance, msg, - name, opcode)) - LOG_WARN("Failed to send to neighbor."); - } - pthread_rwlock_unlock(&rib.flows_lock); - } - - free(name); - ro_msg__free_unpacked(msg, NULL); - } - return (void *) 0; -} - -static int ribmgr_add_flow(int fd) -{ - struct cdap * instance = NULL; - struct mgmt_flow * flow; - - flow = malloc(sizeof(*flow)); - if (flow == NULL) - return -ENOMEM; - - instance = cdap_create(fd); - if (instance == NULL) { - LOG_ERR("Failed to create CDAP instance"); - free(flow); - return -1; - } - - list_head_init(&flow->next); - flow->instance = instance; - flow->fd = fd; - - if (pthread_create(&flow->handler, NULL, - cdap_req_handler, instance)) { - LOG_ERR("Failed to start handler thread for mgt flow."); - free(flow); - return -1; - } - - pthread_rwlock_wrlock(&rib.flows_lock); - - list_add(&flow->next, &rib.flows); - - pthread_rwlock_unlock(&rib.flows_lock); - - return 0; -} - -int ribmgr_remove_flow(int fd) +int ribmgr_init(void) { - struct list_head * pos, * n = NULL; - - pthread_rwlock_wrlock(&rib.flows_lock); - list_for_each_safe(pos, n, &rib.flows) { - struct mgmt_flow * flow = - list_entry(pos, struct mgmt_flow, next); - if (flow->fd == fd) { - pthread_cancel(flow->handler); - if (cdap_destroy(flow->instance)) - LOG_ERR("Failed to destroy CDAP instance."); - list_del(&flow->next); - pthread_rwlock_unlock(&rib.flows_lock); - free(flow); - return 0; - } - } - pthread_rwlock_unlock(&rib.flows_lock); - - return -1; -} - -/* FIXME: do this in a topologymanager instance */ -int ribmgr_add_nm1_flow(int fd) -{ - if (flow_alloc_resp(fd, 0) < 0) { - LOG_ERR("Could not respond to new flow."); - return -1; - } - - return ribmgr_add_flow(fd); -} - -int ribmgr_nm1_mgt_flow(char * dst_name) -{ - int fd; - int result; - - /* FIXME: Request retransmission. */ - fd = flow_alloc(dst_name, MGMT_AE, NULL); - if (fd < 0) { - LOG_ERR("Failed to allocate flow to %s.", dst_name); - return -1; - } - - result = flow_alloc_res(fd); - if (result < 0) { - LOG_ERR("Result of flow allocation to %s is %d.", - dst_name, result); - flow_dealloc(fd); - return -1; - } + enum pol_cacep pc; + enum pol_gam pg; - if (ribmgr_add_flow(fd)) { - LOG_ERR("Failed to add file descriptor."); - flow_dealloc(fd); + if (rib_read(BOOT_PATH "/rm/gam/type", &pg, sizeof(pg)) + != sizeof(pg)) { + LOG_ERR("Failed to read policy for ribmgr gam."); return -1; } - return fd; -} - -int ribmgr_bootstrap(struct dif_config * conf) -{ - static_info_msg_t stat_info = STATIC_INFO_MSG__INIT; - uint8_t * data = NULL; - size_t len = 0; - struct ro_attr attr; - - ro_attr_init(&attr); - attr.enrol_sync = true; - - if (ribmgr_ro_create(RIBMGR_PREFIX, attr, NULL, 0) == NULL) { - LOG_ERR("Failed to create RIBMGR RO."); + if (rib_read(BOOT_PATH "/rm/gam/cacep", &pc, sizeof(pc)) + != sizeof(pc)) { + LOG_ERR("Failed to read CACEP policy for ribmgr gam."); return -1; } - stat_info.addr_size = rib.dtc.addr_size = conf->addr_size; - stat_info.cep_id_size = rib.dtc.cep_id_size = conf->cep_id_size; - stat_info.pdu_length_size = rib.dtc.pdu_length_size - = conf->pdu_length_size; - stat_info.seqno_size = rib.dtc.seqno_size = conf->seqno_size; - stat_info.has_ttl = rib.dtc.has_ttl = conf->has_ttl; - stat_info.has_chk = rib.dtc.has_chk = conf->has_chk; - stat_info.min_pdu_size = rib.dtc.min_pdu_size = conf->min_pdu_size; - stat_info.max_pdu_size = rib.dtc.max_pdu_size = conf->max_pdu_size; - stat_info.addr_auth_type = rib.addr_auth_type = conf->addr_auth_type; - stat_info.dt_gam_type = rib.dt_gam_type = conf->dt_gam_type; + /* FIXME: Implement cacep policies */ + (void) pc; - len = static_info_msg__get_packed_size(&stat_info); - if (len == 0) { - LOG_ERR("Failed to get size of static information."); - ribmgr_ro_delete(RIBMGR_PREFIX); + ribmgr.gam = gam_create(pg, MGMT_AE); + if (ribmgr.gam == NULL) { + LOG_ERR("Failed to create gam."); return -1; } - data = malloc(len); - if (data == NULL) { - LOG_ERR("Failed to allocate memory."); - ribmgr_ro_delete(RIBMGR_PREFIX); + ribmgr.fs = flow_set_create(); + if (ribmgr.fs == NULL) { + LOG_ERR("Failed to create flow set."); + gam_destroy(ribmgr.gam); return -1; } - static_info_msg__pack(&stat_info, data); - - if (ribmgr_ro_create(RIBMGR_PREFIX STAT_INFO, - attr, data, len) == NULL) { - LOG_ERR("Failed to create static info RO."); - free(data); - ribmgr_ro_delete(RIBMGR_PREFIX); + ribmgr.fq = fqueue_create(); + if (ribmgr.fq == NULL) { + LOG_ERR("Failed to create fq."); + flow_set_destroy(ribmgr.fs); + gam_destroy(ribmgr.gam); return -1; } - if (dir_init()) { - LOG_ERR("Failed to init directory"); - ribmgr_ro_delete(RIBMGR_PREFIX STAT_INFO); - ribmgr_ro_delete(RIBMGR_PREFIX); - return -1; - } - - LOG_DBG("Bootstrapped RIB Manager."); - return 0; } -int ribmgr_enrol() +void ribmgr_fini(void) { - struct cdap * instance = NULL; - struct mgmt_flow * flow; - cdap_key_t key; - int ret; - struct timespec timeout = {(ENROLL_TIMEOUT / 1000), - (ENROLL_TIMEOUT % 1000) * MILLION}; - - pthread_rwlock_wrlock(&rib.flows_lock); - - assert(!list_is_empty(&rib.flows)); - - flow = list_first_entry((&rib.flows), struct mgmt_flow, next); - instance = flow->instance; - - key = cdap_request_send(instance, CDAP_START, ENROLLMENT, NULL, 0, 0); - if (key < 0) { - pthread_rwlock_unlock(&rib.flows_lock); - LOG_ERR("Failed to start enrollment."); - return -1; - } - - ret = cdap_reply_wait(instance, key, NULL, NULL); - if (ret) { - pthread_rwlock_unlock(&rib.flows_lock); - LOG_ERR("Failed to enroll: %d.", ret); - return -1; - } - - pthread_rwlock_unlock(&rib.flows_lock); - - if (ribmgr_wait_state(RIBMGR_OPERATIONAL, &timeout) == -ETIMEDOUT) - LOG_ERR("Enrollment of RIB timed out."); - - if (ribmgr_get_state() != RIBMGR_OPERATIONAL) - return -1; - - return 0; + flow_set_destroy(ribmgr.fs); + fqueue_destroy(ribmgr.fq); + gam_destroy(ribmgr.gam); } -int ribmgr_start_policies(void) +int ribmgr_flow_arr(int fd, + qosspec_t qs) { - rib.addr_auth = addr_auth_create(rib.addr_auth_type); - if (rib.addr_auth == NULL) { - LOG_ERR("Failed to create address authority."); - return -1; - } - - rib.address = rib.addr_auth->address(); - LOG_DBG("IPCP has address %lu.", (unsigned long) rib.address); + assert(ribmgr.gam); - return 0; -} - -struct dt_const * ribmgr_dt_const(void) -{ - return &(rib.dtc); -} - -uint64_t ribmgr_address(void) -{ - return rib.address; -} - -enum pol_gam ribmgr_dt_gam(void) -{ - return rib.dt_gam_type; -} - -static int send_neighbors_ro(char * name, ro_msg_t * msg, enum cdap_opcode code) -{ - struct list_head * p = NULL; - - pthread_rwlock_rdlock(&rib.flows_lock); - - list_for_each(p, &rib.flows) { - struct mgmt_flow * e = list_entry(p, struct mgmt_flow, next); - if (write_ro_msg(e->instance, msg, name, code)) { - pthread_rwlock_unlock(&rib.flows_lock); - LOG_ERR("Failed to send to a neighbor."); - return -1; - } - } - - pthread_rwlock_unlock(&rib.flows_lock); - - return 0; -} - -int ro_create(const char * name, - struct ro_attr * attr, - uint8_t * data, - size_t len) -{ - struct rnode * node; - ro_msg_t msg = RO_MSG__INIT; - struct ro_attr rattr; - - assert(name); - - if (attr == NULL) { - ro_attr_init(&rattr); - attr = &rattr; - } - - pthread_mutex_lock(&rib.ro_lock); - - node = ribmgr_ro_create(name, *attr, data, len); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); + if (gam_flow_arr(ribmgr.gam, fd, qs)) return -1; - } - - if (node->attr.recv_set == NO_SYNC) { - pthread_mutex_unlock(&rib.ro_lock); - return 0; - } - - if (ro_msg_create(node, &msg)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to create RO msg."); - return -1; - } - - if (send_neighbors_ro(node->full_name, &msg, CDAP_CREATE)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to send to neighbors."); - return -1; - } - - pthread_mutex_unlock(&rib.ro_lock); - - return 0; -} - -int ro_attr_init(struct ro_attr * attr) -{ - assert(attr); - - attr->enrol_sync = false; - attr->recv_set = NO_SYNC; - attr->expiry.tv_sec = 0; - attr->expiry.tv_nsec = 0; return 0; } -int ro_delete(const char * name) +int ribmgr_disseminate(char * path, + enum diss_target target, + enum diss_freq freq, + size_t delay) { - struct rnode * node; - ro_msg_t msg = RO_MSG__INIT; - - assert(name); - - pthread_mutex_lock(&rib.ro_lock); - - node = find_rnode_by_name(name); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to sync RO."); - return -1; - } - - if (node->attr.recv_set != NO_SYNC) { - if (ro_msg_create(node, &msg)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to create RO msg."); - return -1; - } - - if (send_neighbors_ro(node->full_name, &msg, CDAP_DELETE)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to send to neighbors."); - return -1; - } - } - - if (ribmgr_ro_delete(name)) { - pthread_mutex_unlock(&rib.ro_lock); - return -1; - } - - pthread_mutex_unlock(&rib.ro_lock); + (void) path; + (void) target; + (void) freq; + (void) delay; return 0; } - -int ro_write(const char * name, uint8_t * data, size_t len) -{ - struct rnode * node; - ro_msg_t msg = RO_MSG__INIT; - - assert(name); - assert(data); - - pthread_mutex_lock(&rib.ro_lock); - - node = ribmgr_ro_write(name, data, len); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to create RO."); - return -1; - } - node->seqno++; - - if (node->attr.recv_set == NO_SYNC) { - pthread_mutex_unlock(&rib.ro_lock); - return 0; - } - - if (ro_msg_create(node, &msg)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to create RO msg."); - return -1; - } - - if (send_neighbors_ro(node->full_name, &msg, CDAP_WRITE)) { - pthread_mutex_unlock(&rib.ro_lock); - LOG_ERR("Failed to send to neighbors."); - return -1; - } - - pthread_mutex_unlock(&rib.ro_lock); - - return 0; -} - -ssize_t ro_read(const char * name, uint8_t ** data) -{ - struct rnode * node; - ssize_t len; - - assert(name); - assert(data); - - pthread_mutex_lock(&rib.ro_lock); - - node = find_rnode_by_name(name); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - return -1; - } - - *data = malloc(node->len); - if (*data == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - return -1; - } - - memcpy(*data, node->data, node->len); - len = node->len; - - pthread_mutex_unlock(&rib.ro_lock); - - return len; -} - -ssize_t ro_children(const char * name, char *** children) -{ - struct rnode * node; - struct rnode * child; - ssize_t len = 0; - int i = 0; - - assert(name); - assert(children); - - pthread_mutex_lock(&rib.ro_lock); - - node = find_rnode_by_name(name); - if (node == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - return -1; - } - - child = node->child; - while (child != NULL) { - len++; - child = child->sibling; - } - child = node->child; - - *children = malloc(len); - if (*children == NULL) { - pthread_mutex_unlock(&rib.ro_lock); - return -1; - } - - for (i = 0; i < len; i++) { - (*children)[i] = strdup(child->name); - if ((*children)[i] == NULL) { - while (i >= 0) { - free((*children)[i]); - i--; - } - free(*children); - pthread_mutex_unlock(&rib.ro_lock); - return -1; - } - child = child->sibling; - } - - pthread_mutex_unlock(&rib.ro_lock); - - return len; -} - -bool ro_exists(const char * name) -{ - struct rnode * node; - bool found; - - assert(name); - - pthread_mutex_lock(&rib.ro_lock); - - node = find_rnode_by_name(name); - found = (node == NULL) ? false : true; - - pthread_mutex_unlock(&rib.ro_lock); - - return found; -} - -int ro_subscribe(const char * name, struct ro_sub_ops * ops) -{ - struct ro_sub * sub; - int sid; - - assert(name); - assert(ops); - - sub = malloc(sizeof(*sub)); - if (sub == NULL) - return -ENOMEM; - - list_head_init(&sub->next); - - sub->name = strdup(name); - if (sub->name == NULL) { - free(sub); - return -1; - } - - sub->ops = ops; - - pthread_mutex_lock(&rib.subs_lock); - - sid = bmp_allocate(rib.sids); - if (sid < 0) { - pthread_mutex_unlock(&rib.subs_lock); - free(sub->name); - free(sub); - LOG_ERR("Failed to get sub id."); - return -1; - } - sub->sid = sid; - - list_add(&sub->next, &rib.subs); - - pthread_mutex_unlock(&rib.subs_lock); - - return sid; -} - -int ro_unsubscribe(int sid) -{ - struct list_head * pos = NULL; - struct list_head * n = NULL; - - pthread_mutex_lock(&rib.subs_lock); - - list_for_each_safe(pos, n, &(rib.subs)) { - struct ro_sub * e = list_entry(pos, struct ro_sub, next); - if (sid == e->sid) { - bmp_release(rib.sids, sid); - list_del(&e->next); - free(e->name); - free(e); - pthread_mutex_unlock(&rib.subs_lock); - return 0; - } - } - - pthread_mutex_unlock(&rib.subs_lock); - - LOG_ERR("No such subscription found."); - - return -1; -} diff --git a/src/ipcpd/normal/ribmgr.h b/src/ipcpd/normal/ribmgr.h index 22212de9..12f407ab 100644 --- a/src/ipcpd/normal/ribmgr.h +++ b/src/ipcpd/normal/ribmgr.h @@ -24,27 +24,29 @@ #include <ouroboros/irm_config.h> #include <ouroboros/utils.h> +#include <ouroboros/qos.h> -#include "dt_const.h" +enum diss_target { + NONE = 0, + NEIGHBORS, + ALL_MEMBERS +}; -int ribmgr_init(void); +enum diss_freq { + SINGLE = 0, + PERIODIC +}; -int ribmgr_fini(void); +int ribmgr_init(void); -int ribmgr_add_nm1_flow(int fd); +void ribmgr_fini(void); -int ribmgr_nm1_mgt_flow(char * dst_name); +int ribmgr_flow_arr(int fd, + qosspec_t qs); -int ribmgr_bootstrap(struct dif_config * conf); - -int ribmgr_enrol(void); - -int ribmgr_start_policies(void); - -struct dt_const * ribmgr_dt_const(void); - -uint64_t ribmgr_address(void); - -enum pol_gam ribmgr_dt_gam(void); +int ribmgr_disseminate(char * path, + enum diss_target target, + enum diss_freq freq, + size_t delay); #endif /* OUROBOROS_IPCPD_NORMAL_RIBMGR_H */ diff --git a/src/ipcpd/normal/ro.h b/src/ipcpd/normal/ro.h deleted file mode 100644 index 6fda2adf..00000000 --- a/src/ipcpd/normal/ro.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * RIB objects - * - * Sander Vrijders <sander.vrijders@intec.ugent.be> - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_RO_H -#define OUROBOROS_IPCPD_NORMAL_RO_H - -#include <stdbool.h> -#include <time.h> -#include <stdint.h> - -enum ro_recv_set { - NO_SYNC = 0, - NEIGHBORS, - ALL_MEMBERS -}; - -struct ro_attr { - bool enrol_sync; - enum ro_recv_set recv_set; - struct timespec expiry; -}; - -/* All RIB-objects have a pathname, separated by a slash. */ -/* Takes ownership of the data */ -int ro_create(const char * name, - struct ro_attr * attr, - uint8_t * data, - size_t len); - -int ro_attr_init(struct ro_attr * attr); - -int ro_delete(const char * name); - -int ro_write(const char * name, - uint8_t * data, - size_t len); - -/* Reader takes ownership of data */ -ssize_t ro_read(const char * name, - uint8_t ** data); - -ssize_t ro_children(const char * name, - char *** children); - -bool ro_exists(const char * name); - -/* Callback passes ownership of the data */ -struct ro_sub_ops { - void (* ro_created)(const char * name, - uint8_t * data, - size_t len); - void (* ro_updated)(const char * name, - uint8_t * data, - size_t len); - void (* ro_deleted)(const char * name); -}; - -/* Returns subscriber-id */ -int ro_subscribe(const char * name, - struct ro_sub_ops * ops); - -int ro_unsubscribe(int sid); - -#endif /* OUROBOROS_IPCPD_NORMAL_RO_H */ diff --git a/src/ipcpd/normal/shm_pci.c b/src/ipcpd/normal/shm_pci.c index 4d66bf06..1c2cee54 100644 --- a/src/ipcpd/normal/shm_pci.c +++ b/src/ipcpd/normal/shm_pci.c @@ -20,18 +20,17 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define OUROBOROS_PREFIX "ipcpd/shm_pci" - -#include <ouroboros/logs.h> +#include <ouroboros/config.h> #include <ouroboros/errno.h> #include <ouroboros/crc32.h> +#include <ouroboros/rib.h> + +#include "shm_pci.h" +#include "dt_const.h" #include <stdlib.h> #include <string.h> - -#include "shm_pci.h" -#include "frct.h" -#include "ribmgr.h" +#include <assert.h> #define PDU_TYPE_SIZE 1 #define QOS_ID_SIZE 1 @@ -39,73 +38,124 @@ #define TTL_SIZE 1 #define CHK_SIZE 4 -static size_t shm_pci_head_size(struct dt_const * dtc) -{ - size_t len = 0; +#define BOOT_PATH "/" BOOT_NAME - len = PDU_TYPE_SIZE + dtc->addr_size * 2 + dtc->cep_id_size * 2 - + dtc->pdu_length_size + dtc->seqno_size + QOS_ID_SIZE; +struct { + struct dt_const dtc; + size_t head_size; + size_t tail_size; - if (dtc->has_ttl) - len += TTL_SIZE; + /* offsets */ + size_t dst_addr_o; + size_t src_addr_o; + size_t dst_cep_id_o; + size_t src_cep_id_o; + size_t pdu_length_o; + size_t seqno_o; + size_t qos_id_o; + size_t ttl_o; +} pci_info; - return len; -} -static size_t shm_pci_tail_size(struct dt_const * dtc) +static void ser_pci_head(uint8_t * head, + struct pci * pci) { - return dtc->has_chk ? CHK_SIZE : 0; + uint8_t ttl = DEFAULT_TTL; + + assert(head); + assert(pci); + + /* FIXME: Add check and operations for Big Endian machines */ + memcpy(head, &pci->pdu_type, PDU_TYPE_SIZE); + memcpy(head + pci_info.dst_addr_o, &pci->dst_addr, + pci_info.dtc.addr_size); + memcpy(head + pci_info.src_addr_o, &pci->src_addr, + pci_info.dtc.addr_size); + memcpy(head + pci_info.dst_cep_id_o, &pci->dst_cep_id, + pci_info.dtc.cep_id_size); + memcpy(head + pci_info.src_cep_id_o, &pci->src_cep_id, + pci_info.dtc.cep_id_size); + memcpy(head + pci_info.pdu_length_o, &pci->pdu_length, + pci_info.dtc.pdu_length_size); + memcpy(head + pci_info.seqno_o, &pci->seqno, + pci_info.dtc.seqno_size); + memcpy(head + pci_info.qos_id_o, &pci->qos_id, QOS_ID_SIZE); + if (pci_info.dtc.has_ttl) + memcpy(head + pci_info.ttl_o, &ttl, TTL_SIZE); } -static void ser_pci_head(uint8_t * head, - struct pci * pci, - struct dt_const * dtc) +int shm_pci_init(void) { - int offset = 0; - uint8_t ttl = DEFAULT_TTL; + /* read dt constants from the RIB */ + if (rib_read(BOOT_PATH "/dt/const/addr_size", + &pci_info.dtc.addr_size, + sizeof(pci_info.dtc.addr_size)) || + rib_read(BOOT_PATH "/dt/const/cep_id_size", + &pci_info.dtc.cep_id_size, + sizeof(pci_info.dtc.cep_id_size)) || + rib_read(BOOT_PATH "/dt/const/seqno_size", + &pci_info.dtc.seqno_size, + sizeof(pci_info.dtc.seqno_size)) || + rib_read(BOOT_PATH "/dt/const/has_ttl", + &pci_info.dtc.has_ttl, + sizeof(pci_info.dtc.has_ttl)) || + rib_read(BOOT_PATH "/dt/const/has_chk", + &pci_info.dtc.has_chk, + sizeof(pci_info.dtc.has_chk)) || + rib_read(BOOT_PATH "/dt/const/min_pdu_size", + &pci_info.dtc.min_pdu_size, + sizeof(pci_info.dtc.min_pdu_size)) || + rib_read(BOOT_PATH "/dt/const/max_pdu_size", + &pci_info.dtc.max_pdu_size, + sizeof(pci_info.dtc.max_pdu_size))) + return -1; - memcpy(head, &pci->pdu_type, PDU_TYPE_SIZE); - offset += PDU_TYPE_SIZE; - memcpy(head + offset, &pci->dst_addr, dtc->addr_size); - offset += dtc->addr_size; - memcpy(head + offset, &pci->src_addr, dtc->addr_size); - offset += dtc->addr_size; - memcpy(head + offset, &pci->dst_cep_id, dtc->cep_id_size); - offset += dtc->cep_id_size; - memcpy(head + offset, &pci->src_cep_id, dtc->cep_id_size); - offset += dtc->cep_id_size; - memcpy(head + offset, &pci->pdu_length, dtc->pdu_length_size); - offset += dtc->pdu_length_size; - memcpy(head + offset, &pci->seqno, dtc->seqno_size); - offset += dtc->seqno_size; - memcpy(head + offset, &pci->qos_id, QOS_ID_SIZE); - offset += QOS_ID_SIZE; - if (dtc->has_ttl) - memcpy(head + offset, &ttl, TTL_SIZE); + pci_info.dst_addr_o = PDU_TYPE_SIZE; + pci_info.src_addr_o = pci_info.dst_addr_o + pci_info.dtc.addr_size; + pci_info.dst_cep_id_o = pci_info.dst_addr_o + pci_info.dtc.addr_size; + pci_info.dst_cep_id_o = pci_info.src_addr_o + pci_info.dtc.addr_size; + pci_info.src_cep_id_o = pci_info.dst_cep_id_o + + pci_info.dtc.cep_id_size; + pci_info.pdu_length_o = pci_info.src_cep_id_o + + pci_info.dtc.cep_id_size; + pci_info.seqno_o = pci_info.pdu_length_o + pci_info.dtc.pdu_length_size; + pci_info.qos_id_o = pci_info.seqno_o + pci_info.dtc.seqno_size; + pci_info.ttl_o = pci_info.qos_id_o + QOS_ID_SIZE; + + pci_info.head_size = pci_info.ttl_o; + + if (pci_info.dtc.has_ttl) + pci_info.head_size += TTL_SIZE; + + pci_info.tail_size = pci_info.dtc.has_chk ? CHK_SIZE : 0; + + return 0; +} + +void shm_pci_fini(void) { + return ; } int shm_pci_ser(struct shm_du_buff * sdb, - struct pci * pci) + struct pci * pci) { uint8_t * head; uint8_t * tail; - struct dt_const * dtc; - dtc = ribmgr_dt_const(); - if (dtc == NULL) - return -1; + assert(sdb); + assert(pci); - head = shm_du_buff_head_alloc(sdb, shm_pci_head_size(dtc)); + head = shm_du_buff_head_alloc(sdb, pci_info.head_size); if (head == NULL) - return -1; + return -EPERM; - ser_pci_head(head, pci, dtc); + ser_pci_head(head, pci); - if (dtc->has_chk) { - tail = shm_du_buff_tail_alloc(sdb, shm_pci_tail_size(dtc)); + if (pci_info.dtc.has_chk) { + tail = shm_du_buff_tail_alloc(sdb, pci_info.tail_size); if (tail == NULL) { - shm_du_buff_head_release(sdb, shm_pci_tail_size(dtc)); - return -1; + shm_du_buff_head_release(sdb, pci_info.head_size); + return -EPERM; } crc32((uint32_t *) tail, head, tail - head); @@ -118,22 +168,16 @@ buffer_t * shm_pci_ser_buf(buffer_t * buf, struct pci * pci) { buffer_t * buffer; - struct dt_const * dtc; - if (buf == NULL || pci == NULL) - return NULL; - - dtc = ribmgr_dt_const(); - if (dtc == NULL) - return NULL; + assert(buf); + assert(pci); buffer = malloc(sizeof(*buffer)); if (buffer == NULL) return NULL; - buffer->len = buf->len + - shm_pci_head_size(dtc) + - shm_pci_tail_size(dtc); + buffer->len = buf->len + pci_info.head_size + + pci_info.tail_size; buffer->data = malloc(buffer->len); if (buffer->data == NULL) { @@ -141,118 +185,59 @@ buffer_t * shm_pci_ser_buf(buffer_t * buf, return NULL; } - ser_pci_head(buffer->data, pci, dtc); - memcpy(buffer->data + shm_pci_head_size(dtc), + ser_pci_head(buffer->data, pci); + memcpy(buffer->data + pci_info.head_size, buf->data, buf->len); free(buf->data); - if (dtc->has_chk) - crc32((uint32_t *) buffer->data + - shm_pci_head_size(dtc) + buf->len, + if (pci_info.dtc.has_chk) + crc32((uint32_t *) (buffer->data + + pci_info.head_size + buf->len), buffer->data, - shm_pci_head_size(dtc) + buf->len); + pci_info.head_size + buf->len); return buffer; } -struct pci * shm_pci_des(struct shm_du_buff * sdb) +void shm_pci_des(struct shm_du_buff * sdb, + struct pci * pci) { uint8_t * head; - struct pci * pci; - int offset = 0; - struct dt_const * dtc; - if (sdb == NULL) - return NULL; + assert(sdb); + assert(pci); head = shm_du_buff_head(sdb); - dtc = ribmgr_dt_const(); - if (dtc == NULL) - return NULL; - - pci = malloc(sizeof(*pci)); - if (pci == NULL) - return NULL; - + /* FIXME: Add check and operations for Big Endian machines */ memcpy(&pci->pdu_type, head, PDU_TYPE_SIZE); - offset += PDU_TYPE_SIZE; - memcpy(&pci->dst_addr, head + offset, dtc->addr_size); - offset += dtc->addr_size; - memcpy(&pci->src_addr, head + offset, dtc->addr_size); - offset += dtc->addr_size; - memcpy(&pci->dst_cep_id, head + offset, dtc->cep_id_size); - offset += dtc->cep_id_size; - memcpy(&pci->src_cep_id, head + offset, dtc->cep_id_size); - offset += dtc->cep_id_size; - memcpy(&pci->pdu_length, head + offset, dtc->pdu_length_size); - offset += dtc->pdu_length_size; - memcpy(&pci->seqno, head + offset, dtc->seqno_size); - offset += dtc->seqno_size; - memcpy(&pci->qos_id, head + offset, QOS_ID_SIZE); - offset += QOS_ID_SIZE; - if (dtc->has_ttl) - memcpy(&pci->ttl, head + offset, TTL_SIZE); - - return pci; -} - -int shm_pci_shrink(struct shm_du_buff * sdb) -{ - struct dt_const * dtc; - - if (sdb == NULL) - return -1; - - dtc = ribmgr_dt_const(); - if (dtc == NULL) - return -1; - - if (shm_du_buff_head_release(sdb, shm_pci_head_size(dtc))) { - LOG_ERR("Failed to shrink head."); - return -1; - } - - if (shm_du_buff_tail_release(sdb, shm_pci_tail_size(dtc))) { - LOG_ERR("Failed to shrink tail."); - return -1; + memcpy(&pci->dst_addr, head + pci_info.dst_addr_o, + pci_info.dtc.addr_size); + memcpy(&pci->src_addr, head + pci_info.src_addr_o, + pci_info.dtc.addr_size); + memcpy(&pci->dst_cep_id, head + pci_info.dst_cep_id_o, + pci_info.dtc.cep_id_size); + memcpy(&pci->src_cep_id, head + pci_info.src_cep_id_o, + pci_info.dtc.cep_id_size); + memcpy(&pci->pdu_length, head + pci_info.pdu_length_o, + pci_info.dtc.pdu_length_size); + memcpy(&pci->seqno, head + pci_info.seqno_o, + pci_info.dtc.seqno_size); + memcpy(&pci->qos_id, head + pci_info.qos_id_o, QOS_ID_SIZE); + + if (pci_info.dtc.has_ttl) { + --*(head + pci_info.ttl_o); /* decrease TTL */ + memcpy(&pci->ttl, head + pci_info.ttl_o, TTL_SIZE); + } else { + pci->ttl = 1; } - - return 0; } -int shm_pci_dec_ttl(struct shm_du_buff * sdb) +void shm_pci_shrink(struct shm_du_buff * sdb) { - struct dt_const * dtc; - size_t offset = 0; - uint8_t * head; - uint8_t * tail; + assert(sdb); - dtc = ribmgr_dt_const(); - if (dtc == NULL) - return -1; - - if (dtc->has_ttl == false) - return 0; - - offset = shm_pci_head_size(dtc) - 1; - - head = shm_du_buff_head(sdb); - if (head == NULL) - return -1; - - head[offset]--; - - if (dtc->has_chk) { - tail = shm_du_buff_tail(sdb); - if (tail == NULL) - return -1; - - tail -= CHK_SIZE; - - crc32((uint32_t *) tail, head, tail - head); - } - - return 0; + shm_du_buff_head_release(sdb, pci_info.head_size); + shm_du_buff_tail_release(sdb, pci_info.tail_size); } diff --git a/src/ipcpd/normal/shm_pci.h b/src/ipcpd/normal/shm_pci.h index c1d823bf..17ce5cdd 100644 --- a/src/ipcpd/normal/shm_pci.h +++ b/src/ipcpd/normal/shm_pci.h @@ -25,8 +25,7 @@ #include <ouroboros/shm_rdrbuff.h> #include <ouroboros/utils.h> - -#include "dt_const.h" +#include <ouroboros/qos.h> #define PDU_TYPE_MGMT 0x40 #define PDU_TYPE_DTP 0x80 @@ -45,19 +44,21 @@ struct pci { uint32_t pdu_length; uint64_t seqno; uint8_t ttl; - uint8_t flags; }; +int shm_pci_init(void); + +void shm_pci_fini(void); + int shm_pci_ser(struct shm_du_buff * sdb, struct pci * pci); buffer_t * shm_pci_ser_buf(buffer_t * buf, struct pci * pci); -struct pci * shm_pci_des(struct shm_du_buff * sdb); - -int shm_pci_shrink(struct shm_du_buff * sdb); +void shm_pci_des(struct shm_du_buff * sdb, + struct pci * pci); -int shm_pci_dec_ttl(struct shm_du_buff * sdb); +void shm_pci_shrink(struct shm_du_buff * sdb); #endif /* OUROBOROS_IPCPD_NORMAL_SHM_PCI_H */ diff --git a/src/ipcpd/normal/static_info.proto b/src/ipcpd/normal/static_info.proto deleted file mode 100644 index bb6f8c4e..00000000 --- a/src/ipcpd/normal/static_info.proto +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Static information message - * - * Dimitri Staessens <dimitri.staessens@intec.ugent.be> - * Sander Vrijders <sander.vrijders@intec.ugent.be> - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -syntax = "proto2"; - -message static_info_msg { - required uint32 addr_size = 1; - required uint32 cep_id_size = 2; - required uint32 pdu_length_size = 3; - required uint32 seqno_size = 4; - required bool has_ttl = 5; - required bool has_chk = 6; - required uint32 min_pdu_size = 7; - required uint32 max_pdu_size = 8; - required uint32 addr_auth_type = 9; - required uint32 dt_gam_type = 10; -}
\ No newline at end of file diff --git a/src/lib/dif_config.proto b/src/lib/dif_config.proto index f1f8747b..d47af049 100644 --- a/src/lib/dif_config.proto +++ b/src/lib/dif_config.proto @@ -30,14 +30,14 @@ message dif_config_msg { optional uint32 addr_size = 3; optional uint32 cep_id_size = 4; optional uint32 pdu_length_size = 5; - optional uint32 qos_id_size = 6; - optional uint32 seqno_size = 7; - optional bool has_ttl = 8; - optional bool has_chk = 9; - optional uint32 min_pdu_size = 10; - optional uint32 max_pdu_size = 11; - optional uint32 addr_auth_type = 12; - optional uint32 dt_gam_type = 13; + optional uint32 seqno_size = 6; + optional bool has_ttl = 7; + optional bool has_chk = 8; + optional uint32 min_pdu_size = 9; + optional uint32 max_pdu_size = 10; + optional uint32 addr_auth_type = 11; + optional uint32 dt_gam_type = 12; + optional uint32 rm_gam_type = 13; // Config for shim UDP optional uint32 ip_addr = 14; optional uint32 dns_addr = 15; diff --git a/src/lib/irm.c b/src/lib/irm.c index ade38b6f..8b312833 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -113,7 +113,6 @@ int irm_bootstrap_ipcp(pid_t api, config.has_addr_size = true; config.has_cep_id_size = true; config.has_pdu_length_size = true; - config.has_qos_id_size = true; config.has_seqno_size = true; config.has_has_ttl = true; config.has_has_chk = true; @@ -121,11 +120,11 @@ int irm_bootstrap_ipcp(pid_t api, config.has_max_pdu_size = true; config.has_addr_auth_type = true; config.has_dt_gam_type = true; + config.has_rm_gam_type = true; config.addr_size = conf->addr_size; config.cep_id_size = conf->cep_id_size; config.pdu_length_size = conf->pdu_length_size; - config.qos_id_size = conf->qos_id_size; config.seqno_size = conf->seqno_size; config.has_ttl = conf->has_ttl; config.has_chk = conf->has_chk; @@ -133,6 +132,7 @@ int irm_bootstrap_ipcp(pid_t api, config.max_pdu_size = conf->max_pdu_size; config.addr_auth_type = conf->addr_auth_type; config.dt_gam_type = conf->dt_gam_type; + config.rm_gam_type = conf->rm_gam_type; break; case IPCP_SHIM_UDP: config.has_ip_addr = true; diff --git a/src/lib/shm_rdrbuff.c b/src/lib/shm_rdrbuff.c index ce81d171..55047aa5 100644 --- a/src/lib/shm_rdrbuff.c +++ b/src/lib/shm_rdrbuff.c @@ -619,28 +619,20 @@ uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb, return buf; } -int shm_du_buff_head_release(struct shm_du_buff * sdb, - size_t size) +void shm_du_buff_head_release(struct shm_du_buff * sdb, + size_t size) { assert(sdb); - - if (size > sdb->du_tail - sdb->du_head) - return -EOVERFLOW; + assert(!(size > sdb->du_tail - sdb->du_head)); sdb->du_head += size; - - return 0; } -int shm_du_buff_tail_release(struct shm_du_buff * sdb, - size_t size) +void shm_du_buff_tail_release(struct shm_du_buff * sdb, + size_t size) { assert(sdb); - - if (size > sdb->du_tail - sdb->du_head) - return -EOVERFLOW; + assert(!(size > sdb->du_tail - sdb->du_head)); sdb->du_tail -= size; - - return 0; } diff --git a/src/tools/irm/irm_ipcp_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c index 4c7f2168..10c89060 100644 --- a/src/tools/irm/irm_ipcp_bootstrap.c +++ b/src/tools/irm/irm_ipcp_bootstrap.c @@ -46,9 +46,11 @@ #define DEFAULT_DDNS 0 #define DEFAULT_ADDR_AUTH FLAT_RANDOM #define DEFAULT_DT_GAM COMPLETE +#define DEFAULT_RM_GAM COMPLETE #define ADDR_AUTH_FLAT "flat" #define DT_GAM_COMPLETE "complete" +#define RM_GAM_COMPLETE "complete" static void usage(void) { @@ -71,6 +73,8 @@ static void usage(void) " [addr_auth <address policy> (default: %s)]\n" " [dt_gam <data transfer graph adjacency manager>" "(default: %s)]\n" + " [rm_gam <rib manager graph adjacency manager>" + "(default: %s)]\n" "if TYPE == " SHIM_UDP "\n" " ip <IP address in dotted notation>\n" " [dns <DDNS IP address in dotted notation>" @@ -80,7 +84,7 @@ static void usage(void) DEFAULT_ADDR_SIZE, DEFAULT_CEP_ID_SIZE, DEFAULT_PDU_LEN_SIZE, DEFAULT_SEQ_NO_SIZE, DEFAULT_MIN_PDU_SIZE, DEFAULT_MAX_PDU_SIZE, - ADDR_AUTH_FLAT, DT_GAM_COMPLETE, DEFAULT_DDNS); + ADDR_AUTH_FLAT, DT_GAM_COMPLETE, RM_GAM_COMPLETE, DEFAULT_DDNS); } int do_bootstrap_ipcp(int argc, char ** argv) @@ -98,6 +102,7 @@ int do_bootstrap_ipcp(int argc, char ** argv) uint32_t max_pdu_size = DEFAULT_MAX_PDU_SIZE; enum pol_addr_auth addr_auth_type = DEFAULT_ADDR_AUTH; enum pol_gam dt_gam_type = DEFAULT_DT_GAM; + enum pol_gam rm_gam_type = DEFAULT_RM_GAM; uint32_t ip_addr = 0; uint32_t dns_addr = DEFAULT_DDNS; char * ipcp_type = NULL; @@ -152,6 +157,9 @@ int do_bootstrap_ipcp(int argc, char ** argv) } else if (matches(*argv, "dt_gam") == 0) { if (strcmp(DT_GAM_COMPLETE, *(argv + 1)) == 0) dt_gam_type = COMPLETE; + } else if (matches(*argv, "rm_gam") == 0) { + if (strcmp(RM_GAM_COMPLETE, *(argv + 1)) == 0) + rm_gam_type = COMPLETE; } else { printf("\"%s\" is unknown, try \"irm " "ipcp bootstrap\".\n", *argv); @@ -181,6 +189,7 @@ int do_bootstrap_ipcp(int argc, char ** argv) conf.max_pdu_size = max_pdu_size; conf.addr_auth_type = addr_auth_type; conf.dt_gam_type = dt_gam_type; + conf.rm_gam_type = rm_gam_type; } else if (strcmp(ipcp_type, SHIM_UDP) == 0) { conf.type = IPCP_SHIM_UDP; if (ip_addr == 0) { |