diff options
Diffstat (limited to 'src/ipcpd/normal/ribmgr.c')
-rw-r--r-- | src/ipcpd/normal/ribmgr.c | 293 |
1 files changed, 288 insertions, 5 deletions
diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index 98ed38c6..8bb320c0 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -22,41 +22,324 @@ #define OUROBOROS_PREFIX "rib-manager" +#include <ouroboros/config.h> #include <ouroboros/logs.h> +#include <ouroboros/cdap.h> +#include <ouroboros/list.h> + +#include <stdlib.h> +#include <pthread.h> +#include <string.h> #include "ribmgr.h" +#include "dt_const.h" +#include "frct.h" +#include "ipcp.h" + +#define ENROLLMENT "enrollment" + +extern struct ipcp * _ipcp; + +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); + INIT_LIST_HEAD(&rib->cdap_reqs); + + 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->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); + + 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_fmgr_msg() +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_add_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_rdlock(&_ipcp->state_lock); + pthread_rwlock_wrlock(&rib->flows_lock); + if (list_empty(&rib->flows) && + (_ipcp->state == IPCP_INIT || + _ipcp->state == IPCP_DISCONNECTED)) { + _ipcp->state = IPCP_PENDING_ENROLL; + pthread_rwlock_unlock(&_ipcp->state_lock); + + 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); + } + pthread_rwlock_unlock(&_ipcp->state_lock); + + list_add(&flow->next, &rib->flows); + pthread_rwlock_unlock(&rib->flows_lock); + + return 0; +} + +int ribmgr_remove_flow(int fd) +{ + 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) { + if (cdap_destroy(flow->instance)) + LOG_ERR("Failed to destroy CDAP instance."); + list_del(&flow->next); + free(flow); + return 0; + } + } + pthread_rwlock_unlock(&rib->flows_lock); + + return -1; +} + +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; +} |