From 0c0508619959b5ac98b31b4389fcfadf5ee26d9b Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 27 Jul 2016 16:46:23 +0200 Subject: ipcpd: normal: Provide initial steps for enrollment This provides the normal IPCP with bootstrapping and the initial steps for enrollment. Next step is actually reacting to an enrollment request and sending the data transfer constants. --- include/ouroboros/config.h.in | 2 +- include/ouroboros/dif_config.h | 1 - src/ipcpd/local/main.c | 1 - src/ipcpd/normal/dt_const.h | 3 +- src/ipcpd/normal/fmgr.c | 52 ++++---- src/ipcpd/normal/frct.c | 21 ++- src/ipcpd/normal/frct.h | 2 +- src/ipcpd/normal/main.c | 62 ++++++++- src/ipcpd/normal/ribmgr.c | 265 ++++++++++++++++++++++++++++++++++++- src/lib/cdap.c | 46 +++---- src/tools/irm/irm_ipcp_bootstrap.c | 13 +- 11 files changed, 396 insertions(+), 72 deletions(-) diff --git a/include/ouroboros/config.h.in b/include/ouroboros/config.h.in index 7bb4cee0..97627677 100644 --- a/include/ouroboros/config.h.in +++ b/include/ouroboros/config.h.in @@ -43,7 +43,7 @@ #define SHM_AP_RBUFF_PREFIX "ouroboros.rbuff." #define SHM_RBUFF_SIZE (1 << 14) #define IRMD_MAX_FLOWS 4096 -#define IRMD_THREADPOOL_SIZE 3 +#define IRMD_THREADPOOL_SIZE 5 #define IRMD_FLOW_TIMEOUT 5000 /* ms */ #define LOG_DIR "/@LOG_DIR@/" diff --git a/include/ouroboros/dif_config.h b/include/ouroboros/dif_config.h index c365800c..2e354e8c 100644 --- a/include/ouroboros/dif_config.h +++ b/include/ouroboros/dif_config.h @@ -43,7 +43,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; /* DUP constants */ diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index fcf5f879..4b9dcbbc 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ipcpd/normal/dt_const.h b/src/ipcpd/normal/dt_const.h index 65cde5f7..b33f16c5 100644 --- a/src/ipcpd/normal/dt_const.h +++ b/src/ipcpd/normal/dt_const.h @@ -31,9 +31,10 @@ struct dt_const { uint8_t cep_id_size; uint8_t pdu_length_size; uint8_t seqno_size; - uint8_t qos_id_size; uint8_t ttl_size; uint8_t chk_size; + uint32_t min_pdu_size; + uint32_t max_pdu_size; }; #endif /* IPCP_DT_CONST_H */ diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 9521805f..4b3c49e6 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -48,7 +48,7 @@ struct fmgr { struct list_head n_1_flows; pthread_mutex_t n_1_flows_lock; -} * instance = NULL; +} * fmgr = NULL; static int add_n_1_fd(int fd, char * ae_name) @@ -65,9 +65,9 @@ static int add_n_1_fd(int fd, tmp->fd = fd; tmp->ae_name = ae_name; - pthread_mutex_lock(&instance->n_1_flows_lock); - list_add(&tmp->next, &instance->n_1_flows); - pthread_mutex_unlock(&instance->n_1_flows_lock); + pthread_mutex_lock(&fmgr->n_1_flows_lock); + list_add(&tmp->next, &fmgr->n_1_flows); + pthread_mutex_unlock(&fmgr->n_1_flows_lock); return 0; } @@ -77,6 +77,8 @@ static void * fmgr_listen(void * o) int fd; char * ae_name; + /* FIXME: Only start to listen once we are enrolled */ + while (true) { fd = flow_accept(&ae_name); if (fd < 0) { @@ -84,6 +86,8 @@ static void * fmgr_listen(void * o) continue; } + LOG_DBG("New flow alloc request for AE %s", ae_name); + if (!(strcmp(ae_name, MGMT_AE) == 0 || strcmp(ae_name, DT_AE) == 0)) { if (flow_alloc_resp(fd, -1)) @@ -101,18 +105,20 @@ static void * fmgr_listen(void * o) LOG_DBG("Accepted new flow allocation request for AE %s.", ae_name); - if (strcmp(ae_name, MGMT_AE) == 0 && - ribmgr_mgmt_flow(fd)) { - LOG_ERR("Failed to hand file descriptor to RIB."); - flow_dealloc(fd); - continue; + if (strcmp(ae_name, MGMT_AE) == 0) { + if (ribmgr_mgmt_flow(fd)) { + LOG_ERR("Failed to hand fd to RIB."); + flow_dealloc(fd); + continue; + } } - if (strcmp(ae_name, DT_AE) == 0 && - frct_dt_flow(fd)) { - LOG_ERR("Failed to hand file descriptor to FRCT."); - flow_dealloc(fd); - continue; + if (strcmp(ae_name, DT_AE) == 0) { + if (frct_dt_flow(fd)) { + LOG_ERR("Failed to hand fd to FRCT."); + flow_dealloc(fd); + continue; + } } if (add_n_1_fd(fd, ae_name)) { @@ -127,16 +133,16 @@ static void * fmgr_listen(void * o) int fmgr_init() { - instance = malloc(sizeof(*instance)); - if (instance == NULL) { + fmgr = malloc(sizeof(*fmgr)); + if (fmgr == NULL) { return -1; } - INIT_LIST_HEAD(&instance->n_1_flows); + INIT_LIST_HEAD(&fmgr->n_1_flows); - pthread_mutex_init(&instance->n_1_flows_lock, NULL); + pthread_mutex_init(&fmgr->n_1_flows_lock, NULL); - pthread_create(&instance->listen_thread, + pthread_create(&fmgr->listen_thread, NULL, fmgr_listen, NULL); @@ -148,12 +154,12 @@ int fmgr_fini() { struct list_head * pos = NULL; - pthread_cancel(instance->listen_thread); + pthread_cancel(fmgr->listen_thread); - pthread_join(instance->listen_thread, + pthread_join(fmgr->listen_thread, NULL); - list_for_each(pos, &instance->n_1_flows) { + list_for_each(pos, &fmgr->n_1_flows) { struct n_1_flow * e = list_entry(pos, struct n_1_flow, next); if (e->ae_name != NULL) @@ -161,7 +167,7 @@ int fmgr_fini() flow_dealloc(e->fd); } - free(instance); + free(fmgr); return 0; } diff --git a/src/ipcpd/normal/frct.c b/src/ipcpd/normal/frct.c index 22f8a9fc..49006276 100644 --- a/src/ipcpd/normal/frct.c +++ b/src/ipcpd/normal/frct.c @@ -22,6 +22,8 @@ #define OUROBOROS_PREFIX "flow-rtx-control" +#include + #include #include "frct.h" @@ -30,16 +32,29 @@ struct frct_i { }; -int frct_init(struct dt_const * dt_const) +struct frct { + struct dt_const * dtc; + +} * frct = NULL; + +int frct_init(struct dt_const * dtc) { - LOG_MISSING; + if (dtc == NULL) + return -1; + + frct = malloc(sizeof(*frct)); + if (frct == NULL) { + return -1; + } + + frct->dtc = dtc; return 0; } int frct_fini() { - LOG_MISSING; + free(frct); return 0; } diff --git a/src/ipcpd/normal/frct.h b/src/ipcpd/normal/frct.h index 07fd2c65..515bed3f 100644 --- a/src/ipcpd/normal/frct.h +++ b/src/ipcpd/normal/frct.h @@ -29,7 +29,7 @@ struct frct_i; -int frct_init(struct dt_const * dt_const); +int frct_init(struct dt_const * dtc); int frct_fini(); struct frct_i * frct_i_create(int port_id, diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 2d97f435..54ebd674 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -1,3 +1,25 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Normal IPC Process + * + * Sander Vrijders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "normal-ipcp" #include @@ -108,16 +130,48 @@ static int normal_ipcp_name_unreg(char * name) static int normal_ipcp_enroll(char * dif_name) { - LOG_MISSING; + pthread_rwlock_rdlock(&_ipcp->state_lock); - return -1; + if (_ipcp->state != IPCP_INIT) { + pthread_rwlock_unlock(&_ipcp->state_lock); + LOG_DBGF("Won't enroll an IPCP that is not in INIT."); + return -1; /* -ENOTINIT */ + } + + if (fmgr_mgmt_flow(dif_name)) { + pthread_rwlock_unlock(&_ipcp->state_lock); + LOG_ERR("Failed to establish management flow."); + return -1; + } + + _ipcp->state = IPCP_ENROLLED; + + pthread_rwlock_unlock(&_ipcp->state_lock); + + return 0; } static int normal_ipcp_bootstrap(struct dif_config * conf) { - LOG_MISSING; + pthread_rwlock_rdlock(&_ipcp->state_lock); + + if (_ipcp->state != IPCP_INIT) { + pthread_rwlock_unlock(&_ipcp->state_lock); + LOG_DBGF("Won't bootstrap an IPCP that is not in INIT."); + return -1; /* -ENOTINIT */ + } + + if (ribmgr_bootstrap(conf)) { + pthread_rwlock_unlock(&_ipcp->state_lock); + LOG_ERR("Failed to bootstrap RIB manager."); + return -1; + } + + _ipcp->state = IPCP_ENROLLED; - return -1; + pthread_rwlock_unlock(&_ipcp->state_lock); + + return 0; } static struct ipcp_ops normal_ops = { diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index 98ed38c6..4d29b098 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -22,38 +22,295 @@ #define OUROBOROS_PREFIX "rib-manager" +#include #include +#include +#include + +#include +#include +#include #include "ribmgr.h" +#include "dt_const.h" +#include "frct.h" + +#define ENROLLMENT "enrollment" + +enum cdap_opcode { + READ = 0, + WRITE, + START, + STOP, + CREATE, + DELETE +}; + +struct cdap_request { + enum cdap_opcode code; + char * name; + int invoke_id; + struct cdap * instance; + + struct list_head next; +}; + +struct mgmt_flow { + struct cdap * instance; + int fd; + struct list_head next; +}; + +struct rib { + struct dt_const dtc; + + struct list_head flows; + pthread_rwlock_t flows_lock; + + struct list_head cdap_reqs; + pthread_mutex_t cdap_reqs_lock; +} * rib = NULL; + +/* Call while holding cdap_reqs_lock */ +int cdap_request_add(struct cdap * instance, + enum cdap_opcode code, + char * name, + int invoke_id) +{ + struct cdap_request * req; + + req = malloc(sizeof(*req)); + if (req == NULL) + return -1; + + req->code = code; + req->invoke_id = invoke_id; + req->instance = instance; + + req->name = strdup(name); + if (req->name == NULL) { + free(req); + return -1; + } + + INIT_LIST_HEAD(&req->next); + + list_add(&req->next, &rib->cdap_reqs); + + return 0; +} int ribmgr_init() { - LOG_MISSING; + rib = malloc(sizeof(*rib)); + if (rib == NULL) { + return -1; + } + + INIT_LIST_HEAD(&rib->flows); + + if (pthread_rwlock_init(&rib->flows_lock, NULL)) { + LOG_ERR("Failed to initialize rwlock."); + free(rib); + return -1; + } + + if (pthread_mutex_init(&rib->cdap_reqs_lock, NULL)) { + LOG_ERR("Failed to initialize mutex."); + free(rib); + return -1; + } return 0; } int ribmgr_fini() { - LOG_MISSING; + struct list_head * pos = NULL; + struct list_head * n = NULL; + + pthread_mutex_lock(&rib->cdap_reqs_lock); + list_for_each_safe(pos, n, &rib->cdap_reqs) { + struct cdap_request * req = + list_entry(pos, struct cdap_request, next); + + free(req->name); + list_del(&req->next); + free(req); + } + pthread_mutex_unlock(&rib->cdap_reqs_lock); + + pthread_rwlock_wrlock(&rib->flows_lock); + list_for_each_safe(pos, n, &rib->cdap_reqs) { + struct mgmt_flow * flow = + list_entry(pos, struct mgmt_flow, next); + if (cdap_destroy(flow->instance)) + LOG_ERR("Failed to destroy CDAP instance."); + } + pthread_rwlock_unlock(&rib->flows_lock); + + free(rib); return 0; } -int ribmgr_mgmt_flow(int fd) +int ribmgr_cdap_reply(struct cdap * instance, + int invoke_id, + int result, + buffer_t * val, + size_t len) { LOG_MISSING; + /* FIXME: Check all cdap_reqs here to see if we expect a reply */ + return -1; } -int ribmgr_bootstrap(struct dif_config * conf) +int ribmgr_cdap_read(struct cdap * instance, + char * name) +{ + LOG_MISSING; + + return -1; +} + +int ribmgr_cdap_write(struct cdap * instance, + char * name, + buffer_t * val, + size_t len, + uint32_t flags) +{ + LOG_MISSING; + + return -1; +} + +int ribmgr_cdap_create(struct cdap * instance, + char * name, + buffer_t val) { LOG_MISSING; return -1; } +int ribmgr_cdap_delete(struct cdap * instance, + char * name, + buffer_t val) +{ + LOG_MISSING; + + return -1; +} + +int ribmgr_cdap_start(struct cdap * instance, + char * name) +{ + LOG_MISSING; + + /* FIXME: Handle enrollment request here */ + + return -1; +} + +int ribmgr_cdap_stop(struct cdap * instance, + char * name) +{ + LOG_MISSING; + + return -1; +} + +static struct cdap_ops ribmgr_ops = { + .cdap_reply = ribmgr_cdap_reply, + .cdap_read = ribmgr_cdap_read, + .cdap_write = ribmgr_cdap_write, + .cdap_create = ribmgr_cdap_create, + .cdap_delete = ribmgr_cdap_delete, + .cdap_start = ribmgr_cdap_start, + .cdap_stop = ribmgr_cdap_stop +}; + +int ribmgr_mgmt_flow(int fd) +{ + struct cdap * instance = NULL; + struct mgmt_flow * flow; + int iid = 0; + + flow = malloc(sizeof(*flow)); + if (flow == NULL) + return -1; + + instance = cdap_create(&ribmgr_ops, fd); + if (instance == NULL) { + LOG_ERR("Failed to create CDAP instance"); + free(flow); + return -1; + } + + INIT_LIST_HEAD(&flow->next); + flow->instance = instance; + flow->fd = fd; + + pthread_rwlock_wrlock(&rib->flows_lock); + if (list_empty(&rib->flows)) { + pthread_mutex_lock(&rib->cdap_reqs_lock); + iid = cdap_send_start(instance, + ENROLLMENT); + if (iid < 0) { + pthread_mutex_unlock(&rib->cdap_reqs_lock); + pthread_rwlock_unlock(&rib->flows_lock); + LOG_ERR("Failed to start enrollment."); + cdap_destroy(instance); + free(flow); + return -1; + } + + if (cdap_request_add(instance, START, ENROLLMENT, iid)) { + pthread_mutex_unlock(&rib->cdap_reqs_lock); + pthread_rwlock_unlock(&rib->flows_lock); + LOG_ERR("Failed to add CDAP request to list."); + cdap_destroy(instance); + free(flow); + return -1; + } + pthread_mutex_unlock(&rib->cdap_reqs_lock); + } + + list_add(&flow->next, &rib->flows); + pthread_rwlock_unlock(&rib->flows_lock); + + return 0; +} + +int ribmgr_bootstrap(struct dif_config * conf) +{ + if (conf == NULL || + conf->type != IPCP_NORMAL) { + LOG_ERR("Bad DIF configuration."); + return -1; + } + + rib->dtc.addr_size = conf->addr_size; + rib->dtc.cep_id_size = conf->cep_id_size; + rib->dtc.pdu_length_size = conf->pdu_length_size; + rib->dtc.seqno_size = conf->seqno_size; + rib->dtc.ttl_size = conf->ttl_size; + rib->dtc.chk_size = conf->chk_size; + rib->dtc.min_pdu_size = conf->min_pdu_size; + rib->dtc.max_pdu_size = conf->max_pdu_size; + + if (frct_init(&rib->dtc)) { + LOG_ERR("Failed to initialize FRCT."); + return -1; + } + + LOG_DBG("Bootstrapped RIB Manager."); + + return 0; +} + int ribmgr_fmgr_msg() { LOG_MISSING; diff --git a/src/lib/cdap.c b/src/lib/cdap.c index 4275bfc7..441f7e44 100644 --- a/src/lib/cdap.c +++ b/src/lib/cdap.c @@ -69,6 +69,28 @@ static ssize_t cdap_msg_to_buffer(cdap_t * msg, return len; } +static int next_invoke_id(struct cdap * instance) +{ + int ret; + + pthread_mutex_lock(&instance->ids_lock); + ret = bmp_allocate(instance->ids); + pthread_mutex_unlock(&instance->ids_lock); + + return ret; +} + +static int release_invoke_id(struct cdap * instance, + int id) +{ + int ret; + + pthread_mutex_lock(&instance->ids_lock); + ret = bmp_release(instance->ids, id); + pthread_mutex_unlock(&instance->ids_lock); + + return ret; +} static void * sdu_reader(void * o) { @@ -146,6 +168,7 @@ static void * sdu_reader(void * o) msg->result, val, length); + release_invoke_id(instance, msg->invoke_id); free(val); } break; @@ -225,29 +248,6 @@ int cdap_destroy(struct cdap * instance) return 0; } -static int next_invoke_id(struct cdap * instance) -{ - int ret; - - pthread_mutex_lock(&instance->ids_lock); - ret = bmp_allocate(instance->ids); - pthread_mutex_unlock(&instance->ids_lock); - - return ret; -} - -static int release_invoke_id(struct cdap * instance, - int id) -{ - int ret; - - pthread_mutex_lock(&instance->ids_lock); - ret = bmp_release(instance->ids, id); - pthread_mutex_unlock(&instance->ids_lock); - - return ret; -} - static int write_msg(struct cdap * instance, cdap_t * msg) { diff --git a/src/tools/irm/irm_ipcp_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c index c2b696e4..7d6cbc26 100644 --- a/src/tools/irm/irm_ipcp_bootstrap.c +++ b/src/tools/irm/irm_ipcp_bootstrap.c @@ -39,7 +39,6 @@ #define DEFAULT_ADDR_SIZE 4 #define DEFAULT_CEP_ID_SIZE 2 #define DEFAULT_PDU_LEN_SIZE 2 -#define DEFAULT_QOS_ID_SIZE 1 #define DEFAULT_SEQ_NO_SIZE 4 #define DEFAULT_TTL_SIZE 1 #define DEFAULT_CHK_SIZE 2 @@ -60,7 +59,6 @@ static void usage() " [addr
(default: %d)]\n" " [cep_id (default: %d)]\n" " [pdu_len (default: %d)]\n" - " [qos_id (default: %d)]\n" " [seqno (default: %d)]\n" " [ttl