From 176698e8c2fd7ab8007b8074515d6144e7177d8e Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Fri, 25 Aug 2017 17:19:17 +0200 Subject: ipcpd: Deprecate gam as autonomous component The graph adjacency manager has been deprecated in favor of providing an external interface into the connectivity manager so that adjacencies can be controlled from the command line, user scripts or user applications. The gam and its associated policies were removed from the normal IPCP and the IRM configuration tools. The "/members" part of the RIB was deprecated. Removal of the gam means that initial connectivity based on changes in the RIB can't be provided, so some changes were required throughout the normal IPCP. The enrollment procedure was revised to establish its own connectivity. First, it gets boot information from a peer by establishing a connection to the remote enrollment component and downloading the IPCP configuratoin. This is now done using its own protocol buffers message in anticipation of deprecation of the RIB and CDAP for communication within a DIF. After the boot information is downloaded, it establishes a data transfer flow for enrolling the directory (DHT). After the DHT has enrolled, it signals the peer to that enrollment is done, and the data transfer connection is torn down. Signaling connections is done via the nbs struct, which is now passed to the connmgr, which enables control of the connectivity graph from external sources. --- src/ipcpd/normal/CMakeLists.txt | 6 +- src/ipcpd/normal/addr_auth.c | 5 +- src/ipcpd/normal/addr_auth.h | 3 +- src/ipcpd/normal/ae.h | 21 +- src/ipcpd/normal/connmgr.c | 295 +++++++++++------------ src/ipcpd/normal/connmgr.h | 22 +- src/ipcpd/normal/dir.c | 92 ++----- src/ipcpd/normal/dir.h | 4 + src/ipcpd/normal/dt.c | 82 ++++--- src/ipcpd/normal/dt.h | 9 +- src/ipcpd/normal/dt_pci.c | 18 +- src/ipcpd/normal/dt_pci.h | 6 +- src/ipcpd/normal/enroll.c | 451 +++++++++++++++++++---------------- src/ipcpd/normal/enroll.h | 21 +- src/ipcpd/normal/enroll.proto | 39 +++ src/ipcpd/normal/flow_alloc.proto | 18 +- src/ipcpd/normal/gam.c | 83 ------- src/ipcpd/normal/gam.h | 37 --- src/ipcpd/normal/main.c | 385 ++++++++++++++---------------- src/ipcpd/normal/neighbors.c | 2 +- src/ipcpd/normal/neighbors.h | 12 +- src/ipcpd/normal/pol-addr-auth-ops.h | 2 +- src/ipcpd/normal/pol-gam-ops.h | 36 --- src/ipcpd/normal/pol/complete.c | 180 -------------- src/ipcpd/normal/pol/complete.h | 41 ---- src/ipcpd/normal/pol/flat.c | 106 +------- src/ipcpd/normal/pol/flat.h | 4 +- src/ipcpd/normal/pol/link_state.c | 51 ++-- src/ipcpd/normal/ribconfig.h | 4 - src/ipcpd/normal/ribmgr.c | 116 ++++----- src/ipcpd/normal/ribmgr.h | 4 + src/ipcpd/normal/routing.c | 15 +- src/ipcpd/normal/sdu_sched.c | 6 + 33 files changed, 881 insertions(+), 1295 deletions(-) create mode 100644 src/ipcpd/normal/enroll.proto delete mode 100644 src/ipcpd/normal/gam.c delete mode 100644 src/ipcpd/normal/gam.h delete mode 100644 src/ipcpd/normal/pol-gam-ops.h delete mode 100644 src/ipcpd/normal/pol/complete.c delete mode 100644 src/ipcpd/normal/pol/complete.h (limited to 'src/ipcpd/normal') diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index 7a40e94c..aebc6c35 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -15,6 +15,8 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(IPCP_NORMAL_TARGET ipcpd-normal CACHE INTERNAL "") protobuf_generate_c(FLOW_ALLOC_SRCS FLOW_ALLOC_HDRS flow_alloc.proto) +protobuf_generate_c(ENROLL_PROTO_SRCS ENROLL_PROTO_HDRS enroll.proto + ${CMAKE_SOURCE_DIR}/src/lib/ipcp_config.proto) protobuf_generate_c(KAD_PROTO_SRCS KAD_PROTO_HDRS kademlia.proto) # Add GPB sources of policies last @@ -34,7 +36,6 @@ set(SOURCE_FILES dt_pci.c enroll.c fa.c - gam.c main.c neighbors.c pff.c @@ -42,14 +43,13 @@ set(SOURCE_FILES routing.c sdu_sched.c # Add policies last - pol/complete.c pol/flat.c pol/link_state.c pol/graph.c ) add_executable(ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES} - ${FLOW_ALLOC_SRCS} ${FSO_SRCS} ${KAD_PROTO_SRCS}) + ${FLOW_ALLOC_SRCS} ${FSO_SRCS} ${KAD_PROTO_SRCS} ${ENROLL_PROTO_SRCS}) target_link_libraries(ipcpd-normal LINK_PUBLIC ouroboros) include(AddCompileFlags) diff --git a/src/ipcpd/normal/addr_auth.c b/src/ipcpd/normal/addr_auth.c index e327e2fa..e4aacccd 100644 --- a/src/ipcpd/normal/addr_auth.c +++ b/src/ipcpd/normal/addr_auth.c @@ -35,7 +35,8 @@ struct addr_auth { struct pol_addr_auth_ops * ops; } addr_auth; -int addr_auth_init(enum pol_addr_auth type) +int addr_auth_init(enum pol_addr_auth type, + const void * info) { switch (type) { case FLAT_RANDOM: @@ -46,7 +47,7 @@ int addr_auth_init(enum pol_addr_auth type) return -1; } - return addr_auth.ops->init(); + return addr_auth.ops->init(info); } uint64_t addr_auth_address(void) diff --git a/src/ipcpd/normal/addr_auth.h b/src/ipcpd/normal/addr_auth.h index 5a6dec05..14754660 100644 --- a/src/ipcpd/normal/addr_auth.h +++ b/src/ipcpd/normal/addr_auth.h @@ -27,7 +27,8 @@ #include -int addr_auth_init(enum pol_addr_auth type); +int addr_auth_init(enum pol_addr_auth type, + const void * info); int addr_auth_fini(void); diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h index 6285ba6a..4534cefa 100644 --- a/src/ipcpd/normal/ae.h +++ b/src/ipcpd/normal/ae.h @@ -23,8 +23,23 @@ #ifndef OUROBOROS_IPCPD_NORMAL_AE_H #define OUROBOROS_IPCPD_NORMAL_AE_H -#define MGMT_AE "Management" -#define DT_AE "Data transfer" -#define ENROLL_AE "Enrollment" +#include + +#include "dt.h" + +enum ae_id { + AEID_DT = 0, + AEID_ENROLL, + AEID_MGMT, + AEID_MAX +}; + +struct conn { + struct conn_info conn_info; + struct flow_info { + int fd; + qosspec_t qs; + } flow_info; +}; #endif /* OUROBOROS_IPCPD_NORMAL_AE_H */ diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c index a83d71c3..b6e5e31a 100644 --- a/src/ipcpd/normal/connmgr.c +++ b/src/ipcpd/normal/connmgr.c @@ -22,7 +22,7 @@ #define _POSIX_C_SOURCE 200112L -#define OUROBOROS_PREFIX "normal-ipcp" +#define OUROBOROS_PREFIX "Connection manager" #include #include @@ -42,57 +42,50 @@ #include #include +enum connmgr_state { + CONNMGR_NULL = 0, + CONNMGR_INIT, + CONNMGR_RUNNING +}; + struct ae_conn { struct list_head next; struct conn conn; }; struct ae { - struct list_head next; + struct nbs * nbs; struct conn_info info; - struct list_head conn_list; - pthread_cond_t conn_cond; - pthread_mutex_t conn_lock; + struct list_head conns; + pthread_cond_t cond; + pthread_mutex_t lock; }; struct { - pthread_t acceptor; + struct ae aes[AEID_MAX]; + enum connmgr_state state; - struct list_head aes; - pthread_rwlock_t aes_lock; + pthread_t acceptor; } connmgr; - -static int get_info_by_name(const char * name, - struct conn_info * info) +static int get_id_by_name(const char * name) { - struct list_head * p; + enum ae_id i; - pthread_rwlock_rdlock(&connmgr.aes_lock); - - list_for_each(p, &connmgr.aes) { - struct ae * ae = list_entry(p, struct ae, next); - if (strcmp(ae->info.ae_name, name) == 0) { - memcpy(info, &ae->info, sizeof(*info)); - pthread_rwlock_unlock(&connmgr.aes_lock); - return 0; - } - } - - pthread_rwlock_unlock(&connmgr.aes_lock); + for (i = 0; i < AEID_MAX; ++i) + if (strcmp(name, connmgr.aes[i].info.ae_name) == 0) + return i; return -1; } -static int add_ae_conn(const char * name, +static int add_ae_conn(enum ae_id id, int fd, qosspec_t qs, struct conn_info * rcv_info) { struct ae_conn * ae_conn; - struct list_head * p; - struct ae * ae = NULL; ae_conn = malloc(sizeof(*ae_conn)); if (ae_conn == NULL) { @@ -106,28 +99,12 @@ static int add_ae_conn(const char * name, list_head_init(&ae_conn->next); - pthread_rwlock_wrlock(&connmgr.aes_lock); + pthread_mutex_lock(&connmgr.aes[id].lock); - list_for_each(p, &connmgr.aes) { - ae = list_entry(p, struct ae, next); - if (strcmp(ae->info.ae_name, name) == 0) - break; - } + list_add(&ae_conn->next, &connmgr.aes[id].conns); + pthread_cond_signal(&connmgr.aes[id].cond); - /* Check if entry was removed during allocation. */ - if (ae == NULL || strcmp(ae->info.ae_name, name) != 0) { - pthread_rwlock_unlock(&connmgr.aes_lock); - return -1; - } - - pthread_mutex_lock(&ae->conn_lock); - - list_add(&ae_conn->next, &ae->conn_list); - pthread_cond_signal(&ae->conn_cond); - - pthread_mutex_unlock(&ae->conn_lock); - - pthread_rwlock_unlock(&connmgr.aes_lock); + pthread_mutex_unlock(&connmgr.aes[id].lock); return 0; } @@ -136,7 +113,6 @@ static void * flow_acceptor(void * o) { int fd; qosspec_t qs; - struct conn_info snd_info; struct conn_info rcv_info; struct conn_info fail_info; @@ -145,10 +121,7 @@ static void * flow_acceptor(void * o) memset(&fail_info, 0, sizeof(fail_info)); while (true) { - if (ipcp_get_state() != IPCP_OPERATIONAL) { - log_info("Shutting down flow acceptor."); - return 0; - } + int id; fd = flow_accept(&qs, NULL); if (fd < 0) { @@ -158,26 +131,30 @@ static void * flow_acceptor(void * o) } if (cacep_rcv(fd, &rcv_info)) { - log_err("Error establishing application connection."); + log_dbg("Error establishing application connection."); flow_dealloc(fd); continue; } - if (get_info_by_name(rcv_info.ae_name, &snd_info)) { - log_err("Failed to get info for %s.", rcv_info.ae_name); + id = get_id_by_name(rcv_info.ae_name); + if (id < 0) { + log_dbg("Connection request for unknown AE %s.", + rcv_info.ae_name); cacep_snd(fd, &fail_info); flow_dealloc(fd); continue; } - if (cacep_snd(fd, &snd_info)) { - log_err("Failed to respond to request."); + assert(id < AEID_MAX); + + if (cacep_snd(fd, &connmgr.aes[id].info)) { + log_dbg("Failed to respond to request."); flow_dealloc(fd); continue; } - if (add_ae_conn(rcv_info.ae_name, fd, qs, &rcv_info)) { - log_err("Failed to add new connection."); + if (add_ae_conn(id, fd, qs, &rcv_info)) { + log_dbg("Failed to add new connection."); flow_dealloc(fd); continue; } @@ -188,130 +165,108 @@ static void * flow_acceptor(void * o) int connmgr_init(void) { - if (pthread_rwlock_init(&connmgr.aes_lock, NULL)) - return -1; - - list_head_init(&connmgr.aes); + connmgr.state = CONNMGR_INIT; return 0; } +void connmgr_fini(void) +{ + int i; + + if (connmgr.state == CONNMGR_RUNNING) + pthread_join(connmgr.acceptor, NULL); + + for (i = 0; i < AEID_MAX; ++i) + connmgr_ae_fini(i); +} + int connmgr_start(void) { if (pthread_create(&connmgr.acceptor, NULL, flow_acceptor, NULL)) return -1; + connmgr.state = CONNMGR_RUNNING; + return 0; } void connmgr_stop(void) { - pthread_cancel(connmgr.acceptor); + if (connmgr.state == CONNMGR_RUNNING) + pthread_cancel(connmgr.acceptor); } -static void destroy_ae(struct ae * ae) +int connmgr_ae_init(enum ae_id id, + const struct conn_info * info, + struct nbs * nbs) { - struct list_head * p; - struct list_head * h; - - pthread_mutex_lock(&ae->conn_lock); - - list_for_each_safe(p, h, &ae->conn_list) { - struct ae_conn * e = list_entry(p, struct ae_conn, next); - list_del(&e->next); - free(e); - } - - pthread_mutex_unlock(&ae->conn_lock); + struct ae * ae; - pthread_cond_destroy(&ae->conn_cond); - pthread_mutex_destroy(&ae->conn_lock); + assert(id >= 0 && id < AEID_MAX); - free(ae); -} + ae = connmgr.aes + id; -void connmgr_fini(void) -{ - struct list_head * p; - struct list_head * h; + if (pthread_mutex_init(&ae->lock, NULL)) { + return -1; + } - pthread_join(connmgr.acceptor, NULL); + if (pthread_cond_init(&ae->cond, NULL)) { + pthread_mutex_destroy(&ae->lock); + return -1; + } - pthread_rwlock_wrlock(&connmgr.aes_lock); + list_head_init(&ae->conns); - list_for_each_safe(p, h, &connmgr.aes) { - struct ae * e = list_entry(p, struct ae, next); - list_del(&e->next); - destroy_ae(e); - } + memcpy(&connmgr.aes[id].info, info, sizeof(connmgr.aes[id].info)); - pthread_rwlock_unlock(&connmgr.aes_lock); + connmgr.aes[id].nbs = nbs; - pthread_rwlock_destroy(&connmgr.aes_lock); + return 0; } -struct ae * connmgr_ae_create(struct conn_info info) +void connmgr_ae_fini(enum ae_id id) { - struct ae * ae; - - ae = malloc(sizeof(*ae)); - if (ae == NULL) - goto fail_malloc; - - list_head_init(&ae->next); - list_head_init(&ae->conn_list); - - ae->info = info; - - if (pthread_mutex_init(&ae->conn_lock, NULL)) - goto fail_mutex_init; - - if (pthread_cond_init(&ae->conn_cond, NULL)) - goto fail_cond_init; - - pthread_rwlock_wrlock(&connmgr.aes_lock); + struct list_head * p; + struct list_head * h; + struct ae * ae; - list_add(&ae->next, &connmgr.aes); + assert(id >= 0 && id < AEID_MAX); - pthread_rwlock_unlock(&connmgr.aes_lock); + if (strlen(connmgr.aes[id].info.ae_name) == 0) + return; - return ae; + ae = connmgr.aes + id; - fail_cond_init: - pthread_mutex_destroy(&ae->conn_lock); - fail_mutex_init: - free(ae); - fail_malloc: - return NULL; -} + pthread_mutex_lock(&ae->lock); -void connmgr_ae_destroy(struct ae * ae) -{ - assert(ae); + list_for_each_safe(p, h, &ae->conns) { + struct ae_conn * e = list_entry(p, struct ae_conn, next); + list_del(&e->next); + free(e); + } - pthread_rwlock_wrlock(&connmgr.aes_lock); + pthread_mutex_unlock(&ae->lock); - list_del(&ae->next); + pthread_cond_destroy(&ae->cond); + pthread_mutex_destroy(&ae->lock); - pthread_rwlock_unlock(&connmgr.aes_lock); + memset(&connmgr.aes[id].info, 0, sizeof(connmgr.aes[id].info)); - destroy_ae(ae); + connmgr.aes[id].nbs = NULL; } -int connmgr_alloc(struct ae * ae, - const char * dst_name, +int connmgr_alloc(enum ae_id id, + const char * dst, qosspec_t * qs, struct conn * conn) { - assert(ae); - assert(dst_name); - assert(conn); + assert(id >= 0 && id < AEID_MAX); + assert(dst); - memset(&conn->conn_info, 0, sizeof(conn->conn_info)); - - conn->flow_info.fd = flow_alloc(dst_name, qs, NULL); + conn->flow_info.fd = flow_alloc(dst, qs, NULL); if (conn->flow_info.fd < 0) { - log_err("Failed to allocate flow to %s.", dst_name); + log_dbg("Failed to allocate flow to %s.", dst); return -1; } @@ -320,49 +275,81 @@ int connmgr_alloc(struct ae * ae, else memset(&conn->flow_info.qs, 0, sizeof(conn->flow_info.qs)); - if (cacep_snd(conn->flow_info.fd, &ae->info)) { - log_err("Failed to create application connection."); + log_dbg("Sending cacep info for protocol %s to fd %d.", + connmgr.aes[id].info.protocol, conn->flow_info.fd); + + if (cacep_snd(conn->flow_info.fd, &connmgr.aes[id].info)) { + log_dbg("Failed to create application connection."); flow_dealloc(conn->flow_info.fd); return -1; } if (cacep_rcv(conn->flow_info.fd, &conn->conn_info)) { - log_err("Failed to connect to application."); + log_dbg("Failed to connect to application."); + flow_dealloc(conn->flow_info.fd); + return -1; + } + + if (strcmp(connmgr.aes[id].info.protocol, conn->conn_info.protocol)) { + log_dbg("Unknown protocol (requested %s, got %s).", + connmgr.aes[id].info.protocol, + conn->conn_info.protocol); + flow_dealloc(conn->flow_info.fd); + return -1; + } + + if (connmgr.aes[id].info.pref_version != conn->conn_info.pref_version) { + log_dbg("Unknown protocol version."); flow_dealloc(conn->flow_info.fd); return -1; } - if (strcmp(ae->info.protocol, conn->conn_info.protocol) || - ae->info.pref_version != conn->conn_info.pref_version || - ae->info.pref_syntax != conn->conn_info.pref_syntax) { + if (connmgr.aes[id].info.pref_syntax != conn->conn_info.pref_syntax) { + log_dbg("Unknown protocol syntax."); flow_dealloc(conn->flow_info.fd); return -1; } + if (connmgr.aes[id].nbs != NULL) + nbs_add(connmgr.aes[id].nbs, *conn); + return 0; } -int connmgr_wait(struct ae * ae, +int connmgr_dealloc(enum ae_id id, + struct conn * conn) +{ + if (connmgr.aes[id].nbs != NULL) + nbs_del(connmgr.aes[id].nbs, conn->flow_info.fd); + + return flow_dealloc(conn->flow_info.fd); +} + + +int connmgr_wait(enum ae_id id, struct conn * conn) { struct ae_conn * ae_conn; + struct ae * ae; - assert(ae); + assert(id >= 0 && id < AEID_MAX); assert(conn); - pthread_mutex_lock(&ae->conn_lock); + ae = connmgr.aes + id; + + pthread_mutex_lock(&ae->lock); pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock, - (void *) &ae->conn_lock); + (void *) &ae->lock); - while (list_is_empty(&ae->conn_list)) - pthread_cond_wait(&ae->conn_cond, &ae->conn_lock); + while (list_is_empty(&ae->conns)) + pthread_cond_wait(&ae->cond, &ae->lock); pthread_cleanup_pop(false); - ae_conn = list_first_entry((&ae->conn_list), struct ae_conn, next); + ae_conn = list_first_entry((&ae->conns), struct ae_conn, next); if (ae_conn == NULL) { - pthread_mutex_unlock(&ae->conn_lock); + pthread_mutex_unlock(&ae->lock); return -1; } @@ -371,7 +358,7 @@ int connmgr_wait(struct ae * ae, list_del(&ae_conn->next); free(ae_conn); - pthread_mutex_unlock(&ae->conn_lock); + pthread_mutex_unlock(&ae->lock); return 0; } diff --git a/src/ipcpd/normal/connmgr.h b/src/ipcpd/normal/connmgr.h index 40d74348..920058da 100644 --- a/src/ipcpd/normal/connmgr.h +++ b/src/ipcpd/normal/connmgr.h @@ -26,13 +26,8 @@ #include #include -struct conn { - struct conn_info conn_info; - struct flow_info { - int fd; - qosspec_t qs; - } flow_info; -}; +#include "ae.h" +#include "neighbors.h" int connmgr_init(void); @@ -42,16 +37,21 @@ int connmgr_start(void); void connmgr_stop(void); -struct ae * connmgr_ae_create(struct conn_info info); +int connmgr_ae_init(enum ae_id id, + const struct conn_info * info, + struct nbs * nbs); -void connmgr_ae_destroy(struct ae * ae); +void connmgr_ae_fini(enum ae_id id); -int connmgr_alloc(struct ae * ae, +int connmgr_alloc(enum ae_id id, const char * dst, qosspec_t * qs, struct conn * conn); -int connmgr_wait(struct ae * ae, +int connmgr_dealloc(enum ae_id id, + struct conn * conn); + +int connmgr_wait(enum ae_id id, struct conn * conn); #endif /* OUROBOROS_IPCPD_NORMAL_CONNMGR_H */ diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index feae7013..2e2c113a 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -46,80 +46,21 @@ struct dht * dht; -static uint64_t find_peer_addr(void) +int dir_init(void) { - ssize_t i; - char ** members; - ssize_t n_members; - size_t reset; - char path[RIB_MAX_PATH_LEN + 1]; - - strcpy(path, MEMBERS_PATH); - - reset = strlen(path); - - n_members = rib_children(path, &members); - if (n_members == 1) { - freepp(ssize_t, members, n_members); - return 0; - } - - for (i = 0; i < n_members; ++i) { - uint64_t addr; - rib_path_append(path, members[i]); - if (rib_read(path, &addr, sizeof(addr)) != sizeof(addr)) { - log_err("Failed to read address from RIB."); - freepp(ssize_t, members, n_members); - return ipcpi.dt_addr; - } - - if (addr != ipcpi.dt_addr) { - freepp(ssize_t, members, n_members); - return addr; - } - - path[reset] = '\0'; - } - - freepp(ssize_t, members, n_members); - - return 0; -} - -int dir_init() -{ - uint64_t addr; - dht = dht_create(ipcpi.dt_addr); if (dht == NULL) return -ENOMEM; - addr = find_peer_addr(); - if (addr == ipcpi.dt_addr) { - log_err("Failed to get peer address."); - dht_destroy(dht); - return -EPERM; - } - - if (addr != 0) { - size_t retr = 0; - log_dbg("Enrolling directory with peer %" PRIu64 ".", addr); - /* NOTE: we could try other members if dht_enroll times out. */ - while (dht_enroll(dht, addr)) { - if (retr++ == ENROL_RETR) { - dht_destroy(dht); - return -EPERM; - } - - log_dbg("Directory enrollment failed, retrying..."); - sleep(ENROL_INTV); - } - - log_dbg("Directory enrolled."); + return 0; +} - return 0; - } +void dir_fini(void) +{ + dht_destroy(dht); +} +int dir_bootstrap(void) { log_dbg("Bootstrapping directory."); /* TODO: get parameters for bootstrap from IRM tool. */ @@ -133,9 +74,20 @@ int dir_init() return 0; } -void dir_fini(void) -{ - dht_destroy(dht); +int dir_enroll(uint64_t addr) { + size_t retr = 0; + log_dbg("Enrolling directory with peer %" PRIu64 ".", addr); + while (dht_enroll(dht, addr)) { + if (retr++ == ENROL_RETR) + return -EPERM; + + log_dbg("Directory enrollment failed, retrying..."); + sleep(ENROL_INTV); + } + + log_dbg("Directory enrolled."); + + return 0; } int dir_reg(const uint8_t * hash) diff --git a/src/ipcpd/normal/dir.h b/src/ipcpd/normal/dir.h index 5f3f738e..13571b68 100644 --- a/src/ipcpd/normal/dir.h +++ b/src/ipcpd/normal/dir.h @@ -27,6 +27,10 @@ int dir_init(void); void dir_fini(void); +int dir_bootstrap(void); + +int dir_enroll(uint64_t peer); + int dir_reg(const uint8_t * hash); int dir_unreg(const uint8_t * hash); diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c index f4ab2440..19c2d3a6 100644 --- a/src/ipcpd/normal/dt.c +++ b/src/ipcpd/normal/dt.c @@ -38,7 +38,6 @@ #include "dt_pci.h" #include "pff.h" #include "neighbors.h" -#include "gam.h" #include "routing.h" #include "sdu_sched.h" #include "ae.h" @@ -67,11 +66,12 @@ struct { struct ae_info aes[AP_RES_FDS]; pthread_rwlock_t lock; - struct gam * gam; struct nbs * nbs; struct ae * ae; struct nb_notifier nb_notifier; + + pthread_t listener; } dt; static int dt_neighbor_event(enum nb_event event, @@ -149,36 +149,46 @@ static int sdu_handler(int fd, return 0; } -int dt_init(void) +static void * dt_conn_handle(void * o) { - int i; - int j; - struct conn_info info; - enum pol_routing pr; + struct conn conn; - if (rib_read(BOOT_PATH "/dt/routing/type", &pr, sizeof(pr)) - != sizeof(pr)) { - log_err("Failed to read policy for routing."); - return -1; - } + (void) o; - if (dt_pci_init()) { - log_err("Failed to init shm dt_pci."); - return -1; + while (true) { + if (connmgr_wait(AEID_DT, &conn)) { + log_err("Failed to get next DT connection."); + continue; + } + + log_dbg("Got new connection."); + + nbs_add(dt.nbs, conn); } + return 0; +} + +int dt_init(enum pol_routing pr, + uint8_t addr_size, + uint8_t fd_size, + bool has_ttl) +{ + int i; + int j; + struct conn_info info; + memset(&info, 0, sizeof(info)); strcpy(info.ae_name, DT_AE); strcpy(info.protocol, DT_PROTO); info.pref_version = 1; - info.pref_syntax = PROTO_FIXED; - info.addr = ipcpi.dt_addr; + info.pref_syntax = PROTO_FIXED; + info.addr = ipcpi.dt_addr; - dt.ae = connmgr_ae_create(info); - if (dt.ae == NULL) { - log_err("Failed to create AE struct."); - goto fail_connmgr; + if (dt_pci_init(addr_size, fd_size, has_ttl)) { + log_err("Failed to init shm dt_pci."); + goto fail_pci_init; } dt.nbs = nbs_create(); @@ -193,6 +203,11 @@ int dt_init(void) goto fail_nbs_notifier; } + if (connmgr_ae_init(AEID_DT, &info, dt.nbs)) { + log_err("Failed to register with connmgr."); + goto fail_connmgr_ae_init; + }; + if (routing_init(pr, dt.nbs)) { log_err("Failed to init routing."); goto fail_routing; @@ -233,6 +248,8 @@ int dt_init(void) for (j = 0; j < QOS_CUBE_MAX; ++j) routing_i_destroy(dt.routing[j]); fail_routing_i: + connmgr_ae_fini(AEID_DT); + fail_connmgr_ae_init: for (i = 0; i < QOS_CUBE_MAX; ++i) pff_destroy(dt.pff[i]); fail_pff: @@ -242,9 +259,9 @@ int dt_init(void) fail_nbs_notifier: nbs_destroy(dt.nbs); fail_nbs: - connmgr_ae_destroy(dt.ae); - fail_connmgr: dt_pci_fini(); + fail_pci_init: + connmgr_ae_fini(AEID_DT); return -1; } @@ -268,28 +285,19 @@ void dt_fini(void) nbs_destroy(dt.nbs); - connmgr_ae_destroy(dt.ae); + connmgr_ae_fini(AEID_DT); } int dt_start(void) { - enum pol_gam pg; - - if (rib_read(BOOT_PATH "/dt/gam/type", &pg, sizeof(pg)) - != sizeof(pg)) { - log_err("Failed to read policy for ribmgr gam."); - return -1; - } - dt.sdu_sched = sdu_sched_create(sdu_handler); if (dt.sdu_sched == NULL) { log_err("Failed to create N-1 SDU scheduler."); return -1; } - dt.gam = gam_create(pg, dt.nbs, dt.ae); - if (dt.gam == NULL) { - log_err("Failed to init dt graph adjacency manager."); + if (pthread_create(&dt.listener, NULL, dt_conn_handle, NULL)) { + log_err("Failed to create listener thread."); sdu_sched_destroy(dt.sdu_sched); return -1; } @@ -299,8 +307,8 @@ int dt_start(void) void dt_stop(void) { - gam_destroy(dt.gam); - + pthread_cancel(dt.listener); + pthread_join(dt.listener, NULL); sdu_sched_destroy(dt.sdu_sched); } diff --git a/src/ipcpd/normal/dt.h b/src/ipcpd/normal/dt.h index 99918ea5..09716153 100644 --- a/src/ipcpd/normal/dt.h +++ b/src/ipcpd/normal/dt.h @@ -23,13 +23,20 @@ #ifndef OUROBOROS_IPCPD_NORMAL_DT_H #define OUROBOROS_IPCPD_NORMAL_DT_H +#include #include #include "dt_pci.h" +#define DT_AE "Data Transfer" +#define DT_PROTO "dtp" #define INVALID_ADDR 0 -int dt_init(void); +int dt_init(enum pol_routing pr, + uint8_t addr_size, + uint8_t fd_size, + bool has_ttl +); void dt_fini(void); diff --git a/src/ipcpd/normal/dt_pci.c b/src/ipcpd/normal/dt_pci.c index 9e6dfa89..5704a09a 100644 --- a/src/ipcpd/normal/dt_pci.c +++ b/src/ipcpd/normal/dt_pci.c @@ -44,19 +44,13 @@ struct { size_t fd_o; } dt_pci_info; -int dt_pci_init() +int dt_pci_init(uint8_t addr_size, + uint8_t fd_size, + bool has_ttl) { - /* read dt constants from the RIB */ - if (rib_read(BOOT_PATH "/dt/const/addr_size", - &dt_pci_info.addr_size, - sizeof(dt_pci_info.addr_size)) < 0 || - rib_read(BOOT_PATH "/dt/const/fd_size", - &dt_pci_info.fd_size, - sizeof(dt_pci_info.fd_size)) < 0 || - rib_read(BOOT_PATH "/dt/const/has_ttl", - &dt_pci_info.has_ttl, - sizeof(dt_pci_info.has_ttl)) < 0) - return -1; + dt_pci_info.addr_size = addr_size; + dt_pci_info.fd_size = fd_size; + dt_pci_info.has_ttl = has_ttl; dt_pci_info.qc_o = dt_pci_info.addr_size; dt_pci_info.ttl_o = dt_pci_info.qc_o + QOS_LEN; diff --git a/src/ipcpd/normal/dt_pci.h b/src/ipcpd/normal/dt_pci.h index 5f14527c..efb4d0c0 100644 --- a/src/ipcpd/normal/dt_pci.h +++ b/src/ipcpd/normal/dt_pci.h @@ -30,8 +30,6 @@ #include #include -#define DT_PROTO "dt" - /* Abstract syntax */ enum dtp_fields { DTP_DST = 0, /* DST ADDRESS */ @@ -54,7 +52,9 @@ struct dt_pci { uint32_t fd; }; -int dt_pci_init(void); +int dt_pci_init(uint8_t addr_size, + uint8_t fd_size, + bool has_ttl); void dt_pci_fini(void); diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index a33239a0..2f7dd9bc 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -22,19 +22,19 @@ #define _POSIX_C_SOURCE 199309L -#define OUROBOROS_PREFIX "enrollment" +#define OUROBOROS_PREFIX "Enrollment" #include #include -#include #include #include #include #include #include -#include "ae.h" #include "connmgr.h" +#include "enroll.h" +#include "ipcp.h" #include "ribconfig.h" #include @@ -42,302 +42,331 @@ #include #include -/* Symbolic, will return current time */ -#define TIME_NAME "localtime" -#define TIME_PATH DLR TIME_NAME +#include "enroll.pb-c.h" +typedef EnrollMsg enroll_msg_t; +typedef IpcpConfigMsg ipcp_config_msg_t; +typedef DifInfoMsg dif_info_msg_t; + +#define ENROLL_AE "Enrollment" +#define ENROLL_PROTO "OEP" /* Ouroboros enrollment protocol */ #define ENROLL_WARN_TIME_OFFSET 20 +#define ENROLL_BUF_LEN 1024 + +enum enroll_state { + ENROLL_NULL = 0, + ENROLL_INIT, + ENROLL_RUNNING +}; struct { - struct ae * ae; - struct cdap * cdap; - pthread_t listener; + struct ipcp_config conf; + enum enroll_state state; + pthread_t listener; } enroll; -static void * enroll_handle(void * o) +static int send_rcv_enroll_msg(int fd) { - struct cdap * cdap; - struct conn conn; - cdap_key_t key; - enum cdap_opcode oc; - char * name; - uint8_t * buf; - uint8_t * data; - ssize_t len; - uint32_t flags; + enroll_msg_t req = ENROLL_MSG__INIT; + enroll_msg_t * reply; + uint8_t buf[ENROLL_BUF_LEN]; + ssize_t len; + ssize_t delta_t; + struct timespec t0; + struct timespec rtt; - bool boot_r = false; - bool members_r = false; + req.code = ENROLL_CODE__ENROLL_REQ; - char * boot_ro = BOOT_PATH; - char * members_ro = MEMBERS_PATH; + len = enroll_msg__get_packed_size(&req); + if (len < 0) { + log_dbg("Failed pack request message."); + return -1; + } - cdap = (struct cdap *) o; + enroll_msg__pack(&req, buf); - assert(cdap); + clock_gettime(CLOCK_REALTIME, &t0); - while (true) { - if (connmgr_wait(enroll.ae, &conn)) { - log_err("Failed to get next connection."); - continue; - } + if (flow_write(fd, buf, len)) { + log_dbg("Failed to send request message."); + return -1; + } - if (cdap_add_flow(cdap, conn.flow_info.fd)) { - log_warn("Failed to add flow to CDAP."); - flow_dealloc(conn.flow_info.fd); - continue; - } + len = flow_read(fd, buf, ENROLL_BUF_LEN); + if (len < 0) { + log_dbg("No enrollment reply received."); + return -1; + } - while (!(boot_r && members_r)) { - key = cdap_request_wait(cdap, &oc, &name, &data, - (size_t *) &len , &flags); - assert(key >= 0); - assert(name); - - if (data != NULL) { - free(data); - log_warn("Received data with enroll request."); - } - - if (oc != CDAP_READ) { - log_warn("Invalid request."); - cdap_reply_send(cdap, key, -1, NULL, 0); - free(name); - continue; - } - - if (strcmp(name, boot_ro) == 0) { - boot_r = true; - } else if (strcmp(name, members_ro) == 0) { - members_r = true; - } else if (strcmp(name, TIME_PATH) == 0) { - struct timespec t; - uint64_t buf[2]; - clock_gettime(CLOCK_REALTIME, &t); - buf[0] = hton64(t.tv_sec); - buf[1] = hton64(t.tv_nsec); - cdap_reply_send(cdap, key, 0, buf, sizeof(buf)); - free(name); - continue; - } else { - log_warn("Illegal read: %s.", name); - cdap_reply_send(cdap, key, -1, NULL, 0); - free(name); - continue; - } - - len = rib_pack(name, &buf, PACK_HASH_ROOT); - if (len < 0) { - log_err("Failed to pack %s.", name); - cdap_reply_send(cdap, key, -1, NULL, 0); - free(name); - continue; - } - - log_dbg("Packed %s (%zu bytes).", name, len); - - free(name); - - if (cdap_reply_send(cdap, key, 0, buf, len)) { - log_err("Failed to send CDAP reply."); - free(buf); - continue; - } - - free(buf); - } + log_dbg("Received enrollment info (%zd bytes).", len); - log_dbg("Sent boot info to new member."); + reply = enroll_msg__unpack(NULL, len, buf); + if (reply == NULL) { + log_dbg("No enrollment response."); + return -1; + } - cdap_del_flow(cdap, conn.flow_info.fd); - flow_dealloc(conn.flow_info.fd); + if (reply->code != ENROLL_CODE__ENROLL_BOOT) { + log_dbg("Failed to unpack enrollment response."); + enroll_msg__free_unpacked(reply, NULL); + return -1; + } - boot_r = members_r = false; + if (!(reply->has_t_sec && reply->has_t_nsec)) { + log_dbg("No time in response message."); + enroll_msg__free_unpacked(reply, NULL); + return -1; } + clock_gettime(CLOCK_REALTIME, &rtt); + + delta_t = ts_diff_ms(&t0, &rtt); + + rtt.tv_sec = reply->t_sec; + rtt.tv_nsec = reply->t_nsec; + + if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET) + log_warn("Clock offset above threshold."); + + strcpy(enroll.conf.dif_info.dif_name, reply->conf->dif_info->dif_name); + enroll.conf.type = reply->conf->ipcp_type; + enroll.conf.addr_size = reply->conf->addr_size; + enroll.conf.fd_size = reply->conf->fd_size; + enroll.conf.has_ttl = reply->conf->has_ttl; + enroll.conf.addr_auth_type = reply->conf->addr_auth_type; + enroll.conf.routing_type = reply->conf->routing_type; + enroll.conf.dif_info.dir_hash_algo + = reply->conf->dif_info->dir_hash_algo; + + enroll_msg__free_unpacked(reply, NULL); + return 0; } -int enroll_boot(const char * dst) +static ssize_t enroll_pack(uint8_t ** buf) { - struct cdap * cdap; - cdap_key_t * key; - uint8_t * data; - size_t len; - struct conn conn; + enroll_msg_t msg = ENROLL_MSG__INIT; + ipcp_config_msg_t config = IPCP_CONFIG_MSG__INIT; + dif_info_msg_t dif_info = DIF_INFO_MSG__INIT; + struct timespec now; + ssize_t len; + + clock_gettime(CLOCK_REALTIME, &now); + + msg.code = ENROLL_CODE__ENROLL_BOOT; + msg.has_t_sec = true; + msg.t_sec = now.tv_sec; + msg.has_t_nsec = true; + msg.t_nsec = now.tv_nsec; + msg.conf = &config; + + config.ipcp_type = enroll.conf.type; + config.has_addr_size = true; + config.addr_size = enroll.conf.addr_size; + config.has_fd_size = true; + config.fd_size = enroll.conf.fd_size; + config.has_has_ttl = true; + config.has_ttl = enroll.conf.has_ttl; + config.has_addr_auth_type = true; + config.addr_auth_type = enroll.conf.addr_auth_type; + config.has_routing_type = true; + config.routing_type = enroll.conf.routing_type; + config.dif_info = &dif_info; + + dif_info.dif_name = (char *) enroll.conf.dif_info.dif_name; + dif_info.dir_hash_algo = enroll.conf.dif_info.dir_hash_algo; + + len = enroll_msg__get_packed_size(&msg); + + *buf = malloc(len); + if (*buf == NULL) + return -1; - struct timespec t0; - struct timespec rtt; + enroll_msg__pack(&msg, *buf); - ssize_t delta_t; + return len; +} - char * boot_ro = BOOT_PATH; - char * members_ro = MEMBERS_PATH; +static void * enroll_handle(void * o) +{ + struct conn conn; + uint8_t buf[ENROLL_BUF_LEN]; + uint8_t * reply; + ssize_t len; + enroll_msg_t * msg; - cdap = cdap_create(); - if (cdap == NULL) { - log_err("Failed to instantiate CDAP."); - return -1; - } + (void) o; - if (connmgr_alloc(enroll.ae, dst, NULL, &conn)) { - log_err("Failed to get connection."); - cdap_destroy(cdap); - return -1; - } + while (true) { + if (connmgr_wait(AEID_ENROLL, &conn)) { + log_err("Failed to get next connection."); + continue; + } - if (cdap_add_flow(cdap, conn.flow_info.fd)) { - log_warn("Failed to add flow to CDAP."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN); + if (len < 0) { + log_err("Failed to read from flow."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - log_dbg("Getting boot information from %s.", dst); + msg = enroll_msg__unpack(NULL, len, buf); + if (msg == NULL) { + log_err("Failed to unpack message."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - clock_gettime(CLOCK_REALTIME, &t0); + if (msg->code != ENROLL_CODE__ENROLL_REQ) { + log_err("Wrong message type."); + connmgr_dealloc(AEID_ENROLL, &conn); + enroll_msg__free_unpacked(msg, NULL); + continue; + } - key = cdap_request_send(cdap, CDAP_READ, TIME_PATH, NULL, 0, 0); - if (key == NULL || key[0] == INVALID_CDAP_KEY) { - log_err("Failed to send CDAP request."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + log_dbg("Enrolling a new neighbor."); - if (cdap_reply_wait(cdap, key[0], &data, &len)) { - log_err("Failed to get CDAP reply."); - free(key); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + enroll_msg__free_unpacked(msg, NULL); - free(key); + len = enroll_pack(&reply); + if (reply == NULL) { + log_err("Failed to pack enrollment message."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - clock_gettime(CLOCK_REALTIME, &rtt); + log_dbg("Sending enrollment info (%zd bytes).", len); - delta_t = ts_diff_ms(&t0, &rtt); + if (flow_write(conn.flow_info.fd, reply, len)) { + log_err("Failed respond to enrollment request."); + connmgr_dealloc(AEID_ENROLL, &conn); + free(reply); + continue; + } - assert(len == 2 * sizeof (uint64_t)); + free(reply); - rtt.tv_sec = ntoh64(((uint64_t *) data)[0]); - rtt.tv_nsec = ntoh64(((uint64_t *) data)[1]); + len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN); + if (len < 0) { + log_err("Failed to read from flow."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET) - log_warn("Clock offset above threshold."); + msg = enroll_msg__unpack(NULL, len, buf); + if (msg == NULL) { + log_err("Failed to unpack message."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - free(data); + if (msg->code != ENROLL_CODE__ENROLL_DONE) { + log_err("Wrong message type."); + enroll_msg__free_unpacked(msg, NULL); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - key = cdap_request_send(cdap, CDAP_READ, boot_ro, NULL, 0, 0); - if (key == NULL || key[0] == INVALID_CDAP_KEY) { - log_err("Failed to send CDAP request."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + log_dbg("Neighbor enrollment successful."); - if (cdap_reply_wait(cdap, key[0], &data, &len)) { - log_err("Failed to get CDAP reply."); - free(key); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; + connmgr_dealloc(AEID_ENROLL, &conn); } - free(key); + return 0; +} - log_dbg("Packed information received (%zu bytes).", len); +int enroll_boot(struct conn * conn, + const char * dst) +{ + log_dbg("Getting boot information from %s.", dst); - if (rib_unpack(data, len, UNPACK_CREATE)) { - log_warn("Error unpacking RIB data."); - rib_del(boot_ro); - free(data); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + if (send_rcv_enroll_msg(conn->flow_info.fd)) { + log_err("Failed to enroll."); return -1; } - log_dbg("Packed information inserted into RIB."); + return 0; +} - key = cdap_request_send(cdap, CDAP_READ, members_ro, NULL, 0, 0); - if (key == NULL || key[0] == INVALID_CDAP_KEY) { - log_err("Failed to send CDAP request."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } +int enroll_done(struct conn * conn) +{ + enroll_msg_t msg = ENROLL_MSG__INIT; + uint8_t buf[ENROLL_BUF_LEN]; + ssize_t len; - if (cdap_reply_wait(cdap, key[0], &data, &len)) { - log_err("Failed to get CDAP reply."); - free(key); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + msg.code = ENROLL_CODE__ENROLL_DONE; + + len = enroll_msg__get_packed_size(&msg); + if (len < 0) { + log_dbg("Failed pack request message."); return -1; } - free(key); - - log_dbg("Packed information received (%zu bytes).", len); + enroll_msg__pack(&msg, buf); - if (rib_unpack(data, len, UNPACK_CREATE)) { - log_warn("Error unpacking RIB data."); - rib_del(boot_ro); - free(data); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + if (flow_write(conn->flow_info.fd, buf, len)) { + log_dbg("Failed to send acknowledgment."); return -1; } - log_dbg("Packed information inserted into RIB."); + return 0; +} + +void enroll_bootstrap(const struct ipcp_config * conf) +{ + assert(conf); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + memcpy(&enroll.conf, conf, sizeof(enroll.conf)); +} - return 0; +struct ipcp_config * enroll_get_conf(void) +{ + return &enroll.conf; } int enroll_init(void) { struct conn_info info; - enroll.cdap = cdap_create(); - if (enroll.cdap == NULL) { - log_err("Failed to instantiate CDAP."); - return -1; - } - memset(&info, 0, sizeof(info)); strcpy(info.ae_name, ENROLL_AE); - strcpy(info.protocol, CDAP_PROTO); + strcpy(info.protocol, ENROLL_PROTO); info.pref_version = 1; info.pref_syntax = PROTO_GPB; + info.addr = 0; - enroll.ae = connmgr_ae_create(info); - if (enroll.ae == NULL) { - cdap_destroy(enroll.cdap); + if (connmgr_ae_init(AEID_ENROLL, &info, NULL)) { + log_err("Failed to register with connmgr."); return -1; } + enroll.state = ENROLL_INIT; + return 0; } void enroll_fini(void) { - pthread_join(enroll.listener, NULL); - cdap_destroy(enroll.cdap); - connmgr_ae_destroy(enroll.ae); + if (enroll.state == ENROLL_RUNNING) + pthread_join(enroll.listener, NULL); + + connmgr_ae_fini(AEID_ENROLL); } int enroll_start(void) { - if (pthread_create(&enroll.listener, NULL, enroll_handle, enroll.cdap)) + if (pthread_create(&enroll.listener, NULL, enroll_handle, NULL)) return -1; + enroll.state = ENROLL_RUNNING; + return 0; } void enroll_stop(void) { - pthread_cancel(enroll.listener); + if (enroll.state == ENROLL_RUNNING) + pthread_cancel(enroll.listener); + + enroll.state = ENROLL_INIT; } diff --git a/src/ipcpd/normal/enroll.h b/src/ipcpd/normal/enroll.h index 9b50f6bb..67c9912d 100644 --- a/src/ipcpd/normal/enroll.h +++ b/src/ipcpd/normal/enroll.h @@ -23,14 +23,25 @@ #ifndef OUROBOROS_IPCPD_NORMAL_ENROLL_H #define OUROBOROS_IPCPD_NORMAL_ENROLL_H -int enroll_init(void); +#include -void enroll_fini(void); +#include "ae.h" -int enroll_start(void); +int enroll_init(void); -void enroll_stop(void); +void enroll_fini(void); -int enroll_boot(const char * dst); +int enroll_start(void); + +void enroll_stop(void); + +void enroll_bootstrap(const struct ipcp_config * conf); + +int enroll_boot(struct conn * conn, + const char * dst); + +int enroll_done(struct conn * conn); + +struct ipcp_config * enroll_get_conf(void); #endif /* OUROBOROS_IPCPD_NORMAL_ENROLL_H */ diff --git a/src/ipcpd/normal/enroll.proto b/src/ipcpd/normal/enroll.proto new file mode 100644 index 00000000..2347fb8f --- /dev/null +++ b/src/ipcpd/normal/enroll.proto @@ -0,0 +1,39 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Enrollment message + * + * Dimitri Staessens + * Sander Vrijders + * + * 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., http://www.fsf.org/about/contact/. + */ + +syntax = "proto2"; + +import "ipcp_config.proto"; + +enum enroll_code { + ENROLL_REQ = 1; + ENROLL_BOOT = 2; + ENROLL_DONE = 4; +}; + +message enroll_msg { + required enroll_code code = 1; + optional ipcp_config_msg conf = 2; + optional int64 t_sec = 3; + optional uint32 t_nsec = 4; + optional int32 result = 5; +}; \ No newline at end of file diff --git a/src/ipcpd/normal/flow_alloc.proto b/src/ipcpd/normal/flow_alloc.proto index 717a1a81..eb078674 100644 --- a/src/ipcpd/normal/flow_alloc.proto +++ b/src/ipcpd/normal/flow_alloc.proto @@ -23,16 +23,16 @@ syntax = "proto2"; enum flow_alloc_code { - FLOW_REQ = 1; - FLOW_REPLY = 2; + FLOW_REQ = 1; + FLOW_REPLY = 2; }; message flow_alloc_msg { - required flow_alloc_code code = 1; - optional bytes hash = 2; - optional uint32 qc = 3; - optional sint32 response = 4; - optional uint32 r_fd = 5; - optional uint32 s_fd = 6; - optional uint64 s_addr = 7; + required flow_alloc_code code = 1; + optional bytes hash = 2; + optional uint32 qc = 3; + optional sint32 response = 4; + optional uint32 r_fd = 5; + optional uint32 s_fd = 6; + optional uint64 s_addr = 7; }; diff --git a/src/ipcpd/normal/gam.c b/src/ipcpd/normal/gam.c deleted file mode 100644 index 3b4cc5de..00000000 --- a/src/ipcpd/normal/gam.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Data transfer graph adjacency manager - * - * Dimitri Staessens - * Sander Vrijders - * - * 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., http://www.fsf.org/about/contact/. - */ - -#define _POSIX_C_SOURCE 200112L - -#define OUROBOROS_PREFIX "dt-gam" - -#include -#include -#include -#include -#include -#include - -#include "ipcp.h" -#include "gam.h" -#include "pol-gam-ops.h" -#include "pol/complete.h" - -#include -#include -#include -#include - -struct gam { - struct pol_gam_ops * ops; - void * ops_o; -}; - -struct gam * gam_create(enum pol_gam gam_type, - struct nbs * nbs, - struct ae * ae) -{ - struct gam * gam; - - gam = malloc(sizeof(*gam)); - if (gam == NULL) - return NULL; - - switch (gam_type) { - case COMPLETE: - gam->ops = &complete_ops; - break; - default: - log_err("Unknown gam policy: %d.", gam_type); - return NULL; - } - - gam->ops_o = gam->ops->create(nbs, ae); - if (gam->ops_o == NULL) { - free(gam); - return NULL; - } - - return gam; -} - -void gam_destroy(struct gam * gam) -{ - assert(gam); - - gam->ops->destroy(gam->ops_o); - free(gam); -} diff --git a/src/ipcpd/normal/gam.h b/src/ipcpd/normal/gam.h deleted file mode 100644 index 3dd01a75..00000000 --- a/src/ipcpd/normal/gam.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Data transfer graph adjacency manager - * - * Dimitri Staessens - * Sander Vrijders - * - * 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., http://www.fsf.org/about/contact/. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_GAM_H -#define OUROBOROS_IPCPD_NORMAL_GAM_H - -#include -#include - -#include "neighbors.h" - -struct gam * gam_create(enum pol_gam gam_type, - struct nbs * nbs, - struct ae * ae); - -void gam_destroy(struct gam * gam); - -#endif /* OUROBOROS_IPCPD_NORMAL_GAM_H */ diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 53762415..d9fbc2dd 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -54,50 +54,25 @@ #define THIS_TYPE IPCP_NORMAL -static int boot_components(void) +static int initialize_components(const struct ipcp_config * conf) { - char buf[256]; - ssize_t len; - enum pol_addr_auth pa; - char path[RIB_MAX_PATH_LEN + 1]; - - len = rib_read(BOOT_PATH "/general/dif_name", buf, 256); - if (len < 0) { - log_err("Failed to read DIF name: %zd.", len); - return -1; + if (rib_init()) { + log_err("Failed to initialize RIB."); + goto fail_rib_init; } - ipcpi.dif_name = strdup(buf); + ipcpi.dif_name = strdup(conf->dif_info.dif_name); if (ipcpi.dif_name == NULL) { log_err("Failed to set DIF name."); - return -1; + goto fail_dif_name; } - len = rib_read(BOOT_PATH "/general/dir_hash_algo", - &ipcpi.dir_hash_algo, sizeof(ipcpi.dir_hash_algo)); - if (len < 0) { - log_err("Failed to read hash length: %zd.", len); - goto fail_addr_auth; - } - - ipcpi.dir_hash_algo = ntoh32(ipcpi.dir_hash_algo); + ipcpi.dir_hash_algo = conf->dif_info.dir_hash_algo; assert(ipcp_dir_hash_len() != 0); - if (rib_add(MEMBERS_PATH, ipcpi.name)) { - log_err("Failed to add name to " MEMBERS_PATH); - goto fail_addr_auth; - } - - log_dbg("Starting components."); - - if (rib_read(BOOT_PATH "/dt/addr_auth/type", &pa, sizeof(pa)) - != sizeof(pa)) { - log_err("Failed to read policy for address authority."); - goto fail_addr_auth; - } - - if (addr_auth_init(pa)) { + if (addr_auth_init(conf->addr_auth_type, + &conf->addr_size)) { log_err("Failed to init address authority."); goto fail_addr_auth; } @@ -105,40 +80,84 @@ static int boot_components(void) ipcpi.dt_addr = addr_auth_address(); if (ipcpi.dt_addr == 0) { log_err("Failed to get a valid address."); - goto fail_dir; - } - - path[0] = '\0'; - rib_path_append(rib_path_append(path, MEMBERS_NAME), ipcpi.name); - if (rib_write(path, &ipcpi.dt_addr, sizeof(&ipcpi.dt_addr))) { - log_err("Failed to write address to member object."); - goto fail_dir; + goto fail_addr_auth; } log_dbg("IPCP got address %" PRIu64 ".", ipcpi.dt_addr); - log_dbg("Starting ribmgr."); - if (ribmgr_init()) { log_err("Failed to initialize RIB manager."); goto fail_ribmgr; } - log_dbg("Ribmgr started."); - - if (dt_init()) { - log_err("Failed to initialize data transfer ae."); + if (dt_init(conf->routing_type, + conf->addr_size, + conf->fd_size, + conf->has_ttl)) { + log_err("Failed to initialize data transfer component."); goto fail_dt; } if (fa_init()) { - log_err("Failed to initialize flow allocator ae."); + log_err("Failed to initialize flow allocator component."); goto fail_fa; } - if (dt_start()) { - log_err("Failed to start data transfer ae."); - goto fail_dt_start; + if (dir_init()) { + log_err("Failed to initialize directory."); + goto fail_dir; + } + + ipcp_set_state(IPCP_INIT); + + return 0; + + fail_dir: + fa_fini(); + fail_fa: + dt_fini(); + fail_dt: + ribmgr_fini(); + fail_ribmgr: + addr_auth_fini(); + fail_addr_auth: + free(ipcpi.dif_name); + fail_dif_name: + rib_fini(); + fail_rib_init: + return -1; +} + +static void finalize_components(void) +{ + dir_fini(); + + fa_fini(); + + dt_fini(); + + ribmgr_fini(); + + addr_auth_fini(); + + free(ipcpi.dif_name); + + enroll_fini(); + + connmgr_fini(); + + rib_fini(); +} + +static int start_components(void) +{ + assert(ipcp_get_state() == IPCP_INIT); + + ipcp_set_state(IPCP_OPERATIONAL); + + if (ribmgr_start()) { + log_err("Failed to start RIB manager."); + goto fail_ribmgr_start; } if (fa_start()) { @@ -146,20 +165,12 @@ static int boot_components(void) goto fail_fa_start; } - if (dir_init()) { - log_err("Failed to initialize directory."); - goto fail_dir; - } - if (enroll_start()) { - log_err("Failed to start enroll."); + log_err("Failed to start enrollment."); goto fail_enroll_start; } - ipcp_set_state(IPCP_OPERATIONAL); - if (connmgr_start()) { - ipcp_set_state(IPCP_INIT); log_err("Failed to start AP connection manager."); goto fail_connmgr_start; } @@ -169,184 +180,162 @@ static int boot_components(void) fail_connmgr_start: enroll_stop(); fail_enroll_start: - dir_fini(); - fail_dir: fa_stop(); fail_fa_start: - dt_stop(); - fail_dt_start: - fa_fini(); - fail_fa: - dt_fini(); - fail_dt: - ribmgr_fini(); - fail_ribmgr: - addr_auth_fini(); - fail_addr_auth: - free(ipcpi.dif_name); - + ribmgr_stop(); + fail_ribmgr_start: + ipcp_set_state(IPCP_INIT); return -1; } -void shutdown_components(void) +static void stop_components(void) { + assert(ipcp_get_state() == IPCP_OPERATIONAL || + ipcp_get_state() == IPCP_SHUTDOWN); + connmgr_stop(); enroll_stop(); - dir_fini(); - fa_stop(); - dt_stop(); + ribmgr_stop(); - fa_fini(); + ipcp_set_state(IPCP_INIT); +} - dt_fini(); +static int bootstrap_components(void) +{ + if (dir_bootstrap()) { + log_err("Failed to bootstrap directory."); + dt_stop(); + return -1; + } - ribmgr_fini(); + return 0; +} - addr_auth_fini(); +static int enroll_components(uint64_t peer) +{ + if (dir_enroll(peer)) { + log_err("Failed to enroll directory."); + return -1; + } - free(ipcpi.dif_name); + return 0; } static int normal_ipcp_enroll(const char * dst, struct dif_info * info) { - if (rib_add(RIB_ROOT, MEMBERS_NAME)) { - log_err("Failed to create members."); - return -1; + struct conn er_conn; + struct conn dt_conn; + + if (connmgr_alloc(AEID_ENROLL, dst, NULL, &er_conn)) { + log_err("Failed to get connection."); + goto fail_er_flow; } - /* Get boot state from peer */ - if (enroll_boot(dst)) { - log_err("Failed to boot IPCP components."); - return -1; + /* Get boot state from peer. */ + if (enroll_boot(&er_conn, dst)) { + log_err("Failed to get boot information."); + goto fail_enroll_boot; } - if (boot_components()) { - log_err("Failed to boot IPCP components."); - return -1; + if (initialize_components(enroll_get_conf())) { + log_err("Failed to initialize IPCP components."); + goto fail_enroll_boot; + } + + if (dt_start()) { + log_err("Failed to initialize IPCP components."); + goto fail_dt_start; + }; + + if (connmgr_alloc(AEID_DT, dst, NULL, &dt_conn)) { + log_err("Failed to create a data transfer flow."); + goto fail_dt_flow; + } + + if (start_components()) { + log_err("Failed to start components."); + goto fail_start_comp; + } + + if (enroll_components(dt_conn.conn_info.addr)) { + log_err("Failed to enroll components."); + goto fail_enroll_comp; } + if (enroll_done(&er_conn)) + log_warn("Failed to confirm enrollment with peer."); + + if (connmgr_dealloc(AEID_DT, &dt_conn)) + log_warn("Failed to deallocate data transfer flow."); + + if (connmgr_dealloc(AEID_ENROLL, &er_conn)) + log_warn("Failed to deallocate enrollment flow."); + log_dbg("Enrolled with %s.", dst); info->dir_hash_algo = ipcpi.dir_hash_algo; strcpy(info->dif_name, ipcpi.dif_name); return 0; -} - -const struct ros { - char * parent; - char * child; -} ros[] = { - /* BOOT INFO */ - {RIB_ROOT, BOOT_NAME}, - /* OTHER RIB STRUCTURES */ - {RIB_ROOT, MEMBERS_NAME}, - - /* GENERAL IPCP INFO */ - {BOOT_PATH, "general"}, - - {BOOT_PATH "/general", "dif_name"}, - {BOOT_PATH "/general", "dir_hash_algo"}, - - /* 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", "fd_size"}, - {BOOT_PATH "/dt/const", "has_ttl"}, - {BOOT_PATH "/dt", "addr_auth"}, - {BOOT_PATH "/dt/addr_auth", "type"}, - {BOOT_PATH "/dt", "routing"}, - {BOOT_PATH "/dt/routing", "type"}, - - /* RIB MGR COMPONENT */ - {BOOT_PATH, "rm"}, - {BOOT_PATH "/rm","gam"}, - {BOOT_PATH "/rm/gam", "type"}, - {BOOT_PATH "/rm/gam", "cacep"}, - - {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; + fail_enroll_comp: + stop_components(); + fail_start_comp: + connmgr_dealloc(AEID_DT, &dt_conn); + fail_dt_flow: + dt_stop(); + fail_dt_start: + finalize_components(); + fail_enroll_boot: + connmgr_dealloc(AEID_ENROLL, &er_conn); + fail_er_flow: + return -1; } static int normal_ipcp_bootstrap(const struct ipcp_config * conf) { - uint32_t hash_algo; - assert(conf); assert(conf->type == THIS_TYPE); - hash_algo = hton32((uint32_t) conf->dif_info.dir_hash_algo); + enroll_bootstrap(conf); - assert(ntoh32(hash_algo) != 0); - - if (normal_rib_init()) { - log_err("Failed to write initial structure to the RIB."); - return -1; + if (initialize_components(conf)) { + log_err("Failed to init IPCP components."); + goto fail_init; } - if (rib_write(BOOT_PATH "/general/dif_name", - conf->dif_info.dif_name, - strlen(conf->dif_info.dif_name) + 1) || - rib_write(BOOT_PATH "/general/dir_hash_algo", - &hash_algo, - sizeof(hash_algo)) || - rib_write(BOOT_PATH "/dt/const/addr_size", - &conf->addr_size, - sizeof(conf->addr_size)) || - rib_write(BOOT_PATH "/dt/const/fd_size", - &conf->fd_size, - sizeof(conf->fd_size)) || - rib_write(BOOT_PATH "/dt/const/has_ttl", - &conf->has_ttl, - sizeof(conf->has_ttl)) || - 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 "/dt/addr_auth/type", - &conf->addr_auth_type, - sizeof(conf->addr_auth_type)) || - rib_write(BOOT_PATH "/dt/routing/type", - &conf->routing_type, - sizeof(conf->routing_type))) { - log_err("Failed to write boot info to RIB."); - return -1; + if (dt_start()) { + log_err("Failed to initialize IPCP components."); + goto fail_dt_start; + }; + + if (start_components()) { + log_err("Failed to init IPCP components."); + goto fail_start; } - if (boot_components()) { - log_err("Failed to boot IPCP components."); - return -1; + if (bootstrap_components()) { + log_err("Failed to bootstrap IPCP components."); + goto fail_bootstrap; } log_dbg("Bootstrapped in DIF %s.", conf->dif_info.dif_name); return 0; + + fail_bootstrap: + stop_components(); + fail_start: + dt_stop(); + fail_dt_start: + finalize_components(); + fail_init: + return -1; } static int normal_ipcp_query(const uint8_t * dst) @@ -378,18 +367,14 @@ int main(int argc, goto fail_bind_api; } - if (rib_init()) { - log_err("Failed to initialize RIB."); - goto fail_rib_init; - } - + /* These components must be init at creation. */ if (connmgr_init()) { log_err("Failed to initialize connection manager."); goto fail_connmgr_init; } if (enroll_init()) { - log_err("Failed to initialize enroll component."); + log_err("Failed to initialize enrollment component."); goto fail_enroll_init; } @@ -406,14 +391,10 @@ int main(int argc, ipcp_shutdown(); - if (ipcp_get_state() == IPCP_SHUTDOWN) - shutdown_components(); - - enroll_fini(); - - connmgr_fini(); - - rib_fini(); + if (ipcp_get_state() == IPCP_SHUTDOWN) { + dt_stop(); + stop_components(); + } irm_unbind_api(getpid(), ipcpi.name); @@ -428,8 +409,6 @@ int main(int argc, fail_enroll_init: connmgr_fini(); fail_connmgr_init: - rib_fini(); - fail_rib_init: irm_unbind_api(getpid(), ipcpi.name); fail_bind_api: ipcp_fini(); diff --git a/src/ipcpd/normal/neighbors.c b/src/ipcpd/normal/neighbors.c index 5da0f0df..c32e9aa2 100644 --- a/src/ipcpd/normal/neighbors.c +++ b/src/ipcpd/normal/neighbors.c @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * Data transfer neighbors + * Neighbors * * Dimitri Staessens * Sander Vrijders diff --git a/src/ipcpd/normal/neighbors.h b/src/ipcpd/normal/neighbors.h index 7047d027..9c5a6e50 100644 --- a/src/ipcpd/normal/neighbors.h +++ b/src/ipcpd/normal/neighbors.h @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * Data transfer neighbors + * Neighbors * * Dimitri Staessens * Sander Vrijders @@ -29,7 +29,7 @@ #include #include -#include "connmgr.h" +#include "ae.h" enum nb_event { NEIGHBOR_ADDED, @@ -40,14 +40,14 @@ enum nb_event { typedef int (* nb_notify_t)(enum nb_event event, struct conn conn); -struct nb_notifier { +struct nb { struct list_head next; - nb_notify_t notify_call; + struct conn conn; }; -struct nb { +struct nb_notifier { struct list_head next; - struct conn conn; + nb_notify_t notify_call; }; struct nbs { diff --git a/src/ipcpd/normal/pol-addr-auth-ops.h b/src/ipcpd/normal/pol-addr-auth-ops.h index a3b39298..5d90c64f 100644 --- a/src/ipcpd/normal/pol-addr-auth-ops.h +++ b/src/ipcpd/normal/pol-addr-auth-ops.h @@ -24,7 +24,7 @@ #define OUROBOROS_IPCPD_NORMAL_POL_ADDR_AUTH_OPS_H struct pol_addr_auth_ops { - int (* init)(void); + int (* init)(const void * info); int (* fini)(void); diff --git a/src/ipcpd/normal/pol-gam-ops.h b/src/ipcpd/normal/pol-gam-ops.h deleted file mode 100644 index e63752c0..00000000 --- a/src/ipcpd/normal/pol-gam-ops.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Graph adjacency manager policy ops - * - * Dimitri Staessens - * Sander Vrijders - * - * 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., http://www.fsf.org/about/contact/. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H -#define OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H - -#include -#include - -struct pol_gam_ops { - void * (* create)(struct nbs * nbs, - struct ae * ae); - - void (* destroy)(void * o); -}; - -#endif /* OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H */ diff --git a/src/ipcpd/normal/pol/complete.c b/src/ipcpd/normal/pol/complete.c deleted file mode 100644 index 6c6e7372..00000000 --- a/src/ipcpd/normal/pol/complete.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Sets up a complete graph - * - * Dimitri Staessens - * Sander Vrijders - * - * 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., http://www.fsf.org/about/contact/. - */ - -#define _POSIX_C_SOURCE 200112L - -#define OUROBOROS_PREFIX "complete" - -#include -#include -#include -#include -#include -#include - -#include "neighbors.h" -#include "ribconfig.h" -#include "ipcp.h" -#include "ae.h" - -#include -#include -#include - -#define COMPLETE_REFRESH 1000 /* ms */ - -struct complete { - struct nbs * nbs; - struct ae * ae; - pthread_t allocator; - pthread_t listener; -}; - -static void * listener(void * o) -{ - struct complete * complete; - struct conn conn; - - complete = (struct complete *) o; - - while (true) { - if (connmgr_wait(complete->ae, &conn)) { - log_err("Error while getting next connection."); - continue; - } - - if (nbs_add(complete->nbs, conn)) { - log_err("Failed to add neighbor."); - continue; - } - } - - return (void *) 0; -} - -static void path_reset(char * path) -{ - path[strlen(MEMBERS_PATH)] = '\0'; -} - -static void * allocator(void * o) -{ - qosspec_t qs; - ssize_t len; - char ** children; - ssize_t i; - struct complete * complete; - struct conn conn; - uint64_t addr; - char path[RIB_MAX_PATH_LEN]; - struct timespec to = {(COMPLETE_REFRESH / 1000), - (COMPLETE_REFRESH % 1000) * 1000000}; - - strcpy(path, MEMBERS_PATH); - - complete = (struct complete *) o; - - qosspec_init(&qs); - - while (true) { - len = rib_children(MEMBERS_PATH, &children); - for (i = 0; i < len; ++i) { - if (strcmp(children[i], ipcpi.name) != 0) { - path_reset(path); - rib_path_append(path, children[i]); - if (rib_read(path, &addr, - sizeof(addr)) != - sizeof(addr)) { - log_err("Failed to read address."); - free(children[i]); - continue; - } - - if (nbs_has(complete->nbs, addr)) { - free(children[i]); - continue; - } - - if (connmgr_alloc(complete->ae, children[i], - &qs, &conn)) { - log_warn("Failed conn to neighbor."); - free(children[i]); - continue; - } - - if (nbs_add(complete->nbs, conn)) { - log_err("Failed to add neighbor."); - free(children[i]); - continue; - } - } - - free(children[i]); - } - - if (len > 0) - free(children); - - nanosleep(&to, NULL); - } - - return (void *) 0; -} - -void * complete_create(struct nbs * nbs, - struct ae * ae) -{ - struct complete * complete; - - complete = malloc(sizeof(*complete)); - if (complete == NULL) - return NULL; - - complete->nbs = nbs; - complete->ae = ae; - - if (pthread_create(&complete->allocator, NULL, - allocator, (void *) complete)) - return NULL; - - if (pthread_create(&complete->listener, NULL, - listener, (void *) complete)) - return NULL; - - return complete; -} - -void complete_destroy(void * ops_o) -{ - struct complete * complete; - - assert(ops_o); - - complete = (struct complete *) ops_o; - - pthread_cancel(complete->allocator); - pthread_cancel(complete->listener); - pthread_join(complete->allocator, NULL); - pthread_join(complete->listener, NULL); - - free(complete); -} diff --git a/src/ipcpd/normal/pol/complete.h b/src/ipcpd/normal/pol/complete.h deleted file mode 100644 index 54c4a9ef..00000000 --- a/src/ipcpd/normal/pol/complete.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Sets up a complete graph - * - * Dimitri Staessens - * Sander Vrijders - * - * 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., http://www.fsf.org/about/contact/. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H -#define OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H - -#include -#include - -#include "pol-gam-ops.h" - -void * complete_create(struct nbs * nbs, - struct ae * ae); - -void complete_destroy(void * ops_o); - -struct pol_gam_ops complete_ops = { - .create = complete_create, - .destroy = complete_destroy -}; - -#endif /* OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H */ diff --git a/src/ipcpd/normal/pol/flat.c b/src/ipcpd/normal/pol/flat.c index 1fece07f..7a5a785e 100644 --- a/src/ipcpd/normal/pol/flat.c +++ b/src/ipcpd/normal/pol/flat.c @@ -42,47 +42,21 @@ #define NAME_LEN 8 #define REC_DIF_SIZE 10000 -/* convert 32 bit addr to a hex string */ -static void addr_name(char * name, - uint32_t addr) -{ - sprintf(name, "%8x", (uint32_t) (addr)); -} - -static int addr_taken(char * name, - char ** members, - size_t len) -{ - size_t i; - char path[RIB_MAX_PATH_LEN + 1]; - - size_t reset; - strcpy(path, MEMBERS_PATH); - - 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'; - } - - return 0; -} +struct { + uint8_t addr_size; +} flat; #define INVALID_ADDRESS 0 -int flat_init(void) +int flat_init(const void * info) { + flat.addr_size = *((uint8_t *) info); + + if (flat.addr_size != 4) { + log_err("Flat address policy mandates 4 byte addresses."); + return -1; + } + return 0; } @@ -94,66 +68,12 @@ int flat_fini(void) uint64_t flat_address(void) { struct timespec t; - - char path[RIB_MAX_PATH_LEN]; - char name[NAME_LEN + 1]; - uint32_t addr; - uint8_t addr_size; - - char ** members; - ssize_t n_members; - - strcpy(path, MEMBERS_PATH); - - if (!rib_has(path)) { - log_err("Could not read members from RIB."); - return INVALID_ADDRESS; - } - - 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 (addr_size != 4) { - log_err("Flat address policy mandates 4 byte addresses."); - return INVALID_ADDRESS; - } - - n_members = rib_children(path, &members); - if (n_members > REC_DIF_SIZE) - log_warn("DIF exceeding recommended size for flat addresses."); - - rib_path_append(path, ipcpi.name); - - if (!rib_has(path)) { - log_err("This ipcp is not a member."); - freepp(char, members, n_members); - return INVALID_ADDRESS; - } + uint32_t addr; clock_gettime(CLOCK_REALTIME, &t); srand(t.tv_nsec); - assert(n_members > 0); - - do { - addr = (rand() % (RAND_MAX - 1) + 1) & 0xFFFFFFFF; - addr_name(name, addr); - } while (addr_taken(name, members, n_members)); - - freepp(char, members, n_members); - - if (rib_add(path, name)) { - log_err("Failed to add address to RIB."); - return INVALID_ADDRESS; - } - - if (rib_write(path, &addr, sizeof(addr))) { - log_err("Failed to write address in RIB."); - return INVALID_ADDRESS; - } + addr = (rand() % (RAND_MAX - 1) + 1) & 0xFFFFFFFF; return addr; } diff --git a/src/ipcpd/normal/pol/flat.h b/src/ipcpd/normal/pol/flat.h index af49d283..57af591e 100644 --- a/src/ipcpd/normal/pol/flat.h +++ b/src/ipcpd/normal/pol/flat.h @@ -25,8 +25,10 @@ #include "pol-addr-auth-ops.h" -int flat_init(void); +int flat_init(const void * info); + int flat_fini(void); + uint64_t flat_address(void); struct pol_addr_auth_ops flat_ops = { diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c index 9dfed5c0..6bc59d6b 100644 --- a/src/ipcpd/normal/pol/link_state.c +++ b/src/ipcpd/normal/pol/link_state.c @@ -130,9 +130,10 @@ static int link_state_neighbor_event(enum nb_event event, size_t len; uint8_t * data; - /* Only announce the flow if our address is bigger */ + /* Only announce the flow if our address is bigger if (ipcpi.dt_addr < conn.conn_info.addr) return 0; + */ path[0] = '\0'; sprintf(fso_name, "%" PRIu64 "-%" PRIu64, @@ -305,42 +306,42 @@ int link_state_init(struct nbs * nbs) { link_state.graph = graph_create(); if (link_state.graph == NULL) - return -1; + goto fail_graph; - if (rib_add(RIB_ROOT, ROUTING_NAME)) { - graph_destroy(link_state.graph); - return -1; - } + if (rib_add(RIB_ROOT, ROUTING_NAME)) + goto fail_rib_add; link_state.nbs = nbs; link_state.nb_notifier.notify_call = link_state_neighbor_event; - if (nbs_reg_notifier(link_state.nbs, &link_state.nb_notifier)) { - graph_destroy(link_state.graph); - rib_del(ROUTING_PATH); - return -1; - } + if (nbs_reg_notifier(link_state.nbs, &link_state.nb_notifier)) + goto fail_nbs_reg_notifier; link_state.set = ro_set_create(); - if (link_state.set == NULL) { - nbs_unreg_notifier(link_state.nbs, &link_state.nb_notifier); - graph_destroy(link_state.graph); - rib_del(ROUTING_PATH); - return -1; - } + if (link_state.set == NULL) + goto fail_ro_set_create; link_state.queue = rqueue_create(); - if (link_state.queue == NULL) { - ro_set_destroy(link_state.set); - nbs_unreg_notifier(link_state.nbs, &link_state.nb_notifier); - graph_destroy(link_state.graph); - rib_del(ROUTING_PATH); - return -1; - } + if (link_state.queue == NULL) + goto fail_rqueue_create; - pthread_create(&link_state.rib_listener, NULL, rib_listener, NULL); + if (pthread_create(&link_state.rib_listener, NULL, rib_listener, NULL)) + goto fail_listener_create; return 0; + + fail_listener_create: + ro_set_destroy(link_state.set); + fail_rqueue_create: + ro_set_destroy(link_state.set); + fail_ro_set_create: + nbs_unreg_notifier(link_state.nbs, &link_state.nb_notifier); + fail_nbs_reg_notifier: + rib_del(ROUTING_PATH); + fail_rib_add: + graph_destroy(link_state.graph); + fail_graph: + return -1; } void link_state_fini(void) diff --git a/src/ipcpd/normal/ribconfig.h b/src/ipcpd/normal/ribconfig.h index 3a9b6ecb..f6d10133 100644 --- a/src/ipcpd/normal/ribconfig.h +++ b/src/ipcpd/normal/ribconfig.h @@ -27,11 +27,7 @@ #define RIB_MAX_PATH_LEN 256 #define DLR "/" -#define BOOT_NAME "boot" -#define MEMBERS_NAME "members" #define ROUTING_NAME "fsdb" -#define BOOT_PATH DLR BOOT_NAME -#define MEMBERS_PATH DLR MEMBERS_NAME #define ROUTING_PATH DLR ROUTING_NAME #endif /* OUROBOROS_IPCPD_NORMAL_RIB_CONFIG_H */ diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index ab2aa430..a5e7d6ce 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -35,10 +35,11 @@ #include #include "ae.h" -#include "gam.h" +#include "connmgr.h" +#include "ipcp.h" +#include "neighbors.h" #include "ribconfig.h" #include "ribmgr.h" -#include "ipcp.h" #include #include @@ -46,10 +47,12 @@ #include #include +#define MGMT_AE "Management" #define RIB_SYNC_TIMEOUT 1 enum ribmgr_state { RIBMGR_NULL = 0, + RIBMGR_INIT, RIBMGR_OPERATIONAL, RIBMGR_SHUTDOWN }; @@ -60,7 +63,6 @@ struct { pthread_t reader; pthread_t sync; - struct gam * gam; struct nbs * nbs; struct ae * ae; @@ -300,9 +302,8 @@ static void * sync_rib(void *o) rib_path_append(path, children[--ch]); free(children[ch]); - /* Only sync fsdb and members */ - if (strcmp(path, MEMBERS_PATH) == 0 - || strcmp(path, ROUTING_PATH) == 0) + /* Sync fsdb */ + if (strcmp(path, ROUTING_PATH) == 0) ribmgr_sync(path); } @@ -314,7 +315,6 @@ static void * sync_rib(void *o) int ribmgr_init(void) { - enum pol_gam pg; struct conn_info info; memset(&info, 0, sizeof(info)); @@ -323,82 +323,90 @@ int ribmgr_init(void) strcpy(info.protocol, CDAP_PROTO); info.pref_version = 1; info.pref_syntax = PROTO_GPB; - /* NOTE: Use the same name as the DT AE of this IPCP */ - info.addr = ipcpi.dt_addr; + info.addr = 0; ribmgr.nbs = nbs_create(); if (ribmgr.nbs == NULL) { log_err("Failed to create neighbors."); - return -1; - } - - ribmgr.ae = connmgr_ae_create(info); - if (ribmgr.ae == NULL) { - log_err("Failed to create AE struct."); - nbs_destroy(ribmgr.nbs); - return -1; + goto fail_nbs_create; } - if (rib_read(BOOT_PATH "/rm/gam/type", &pg, sizeof(pg)) - != sizeof(pg)) { - log_err("Failed to read policy for ribmgr gam."); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; - } + if (connmgr_ae_init(AEID_MGMT, &info, ribmgr.nbs)) { + log_err("Failed to register with connmgr."); + goto fail_connmgr_ae_init; + }; ribmgr.cdap = cdap_create(); if (ribmgr.cdap == NULL) { log_err("Failed to create CDAP instance."); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; + goto fail_cdap_create; } ribmgr.nb_notifier.notify_call = ribmgr_neighbor_event; if (nbs_reg_notifier(ribmgr.nbs, &ribmgr.nb_notifier)) { log_err("Failed to register notifier."); - cdap_destroy(ribmgr.cdap); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; + goto fail_nbs_reg_notifier; } - ribmgr.gam = gam_create(pg, ribmgr.nbs, ribmgr.ae); - if (ribmgr.gam == NULL) { - log_err("Failed to create gam."); - nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier); - cdap_destroy(ribmgr.cdap); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; + if (pthread_rwlock_init(&ribmgr.state_lock, NULL)) { + log_err("Failed to init rwlock."); + goto fail_rwlock_init; } - pthread_rwlock_init(&ribmgr.state_lock, NULL); - - ribmgr.state = RIBMGR_OPERATIONAL; - - pthread_create(&ribmgr.sync, NULL, sync_rib, NULL); - - pthread_create(&ribmgr.reader, NULL, reader, NULL); + ribmgr.state = RIBMGR_INIT; return 0; + + fail_rwlock_init: + nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier); + fail_nbs_reg_notifier: + cdap_destroy(ribmgr.cdap); + fail_cdap_create: + connmgr_ae_fini(AEID_MGMT); + fail_connmgr_ae_init: + nbs_destroy(ribmgr.nbs); + fail_nbs_create: + return -1; } void ribmgr_fini(void) { - ribmgr_set_state(RIBMGR_SHUTDOWN); - - pthread_cancel(ribmgr.reader); - - pthread_join(ribmgr.reader, NULL); - pthread_join(ribmgr.sync, NULL); + if (ribmgr_get_state() == RIBMGR_SHUTDOWN) { + pthread_join(ribmgr.reader, NULL); + pthread_join(ribmgr.sync, NULL); + } nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier); cdap_destroy(ribmgr.cdap); - gam_destroy(ribmgr.gam); - connmgr_ae_destroy(ribmgr.ae); nbs_destroy(ribmgr.nbs); + + connmgr_ae_fini(AEID_MGMT); +} + +int ribmgr_start(void) +{ + ribmgr_set_state(RIBMGR_OPERATIONAL); + + if (pthread_create(&ribmgr.sync, NULL, sync_rib, NULL)) { + ribmgr_set_state(RIBMGR_NULL); + return -1; + } + + if (pthread_create(&ribmgr.reader, NULL, reader, NULL)) { + ribmgr_set_state(RIBMGR_SHUTDOWN); + pthread_cancel(ribmgr.reader); + return -1; + } + + return 0; +} + +void ribmgr_stop(void) +{ + if (ribmgr_get_state() == RIBMGR_OPERATIONAL) { + ribmgr_set_state(RIBMGR_SHUTDOWN); + pthread_cancel(ribmgr.reader); + } } int ribmgr_disseminate(char * path, diff --git a/src/ipcpd/normal/ribmgr.h b/src/ipcpd/normal/ribmgr.h index 7411aedd..20f87548 100644 --- a/src/ipcpd/normal/ribmgr.h +++ b/src/ipcpd/normal/ribmgr.h @@ -42,6 +42,10 @@ int ribmgr_init(void); void ribmgr_fini(void); +int ribmgr_start(void); + +void ribmgr_stop(void); + int ribmgr_disseminate(char * path, enum diss_target target, enum diss_freq freq, diff --git a/src/ipcpd/normal/routing.c b/src/ipcpd/normal/routing.c index c00ec67c..04e6fd76 100644 --- a/src/ipcpd/normal/routing.c +++ b/src/ipcpd/normal/routing.c @@ -29,36 +29,35 @@ #include "routing.h" #include "pol/link_state.h" -struct { - struct pol_routing_ops * ops; -} routing; + +struct pol_routing_ops * r_ops; int routing_init(enum pol_routing pr, struct nbs * nbs) { switch (pr) { case LINK_STATE: - routing.ops = &link_state_ops; + r_ops = &link_state_ops; break; default: log_err("Unknown routing type."); return -1; } - return routing.ops->init(nbs); + return r_ops->init(nbs); } struct routing_i * routing_i_create(struct pff * pff) { - return routing.ops->routing_i_create(pff); + return r_ops->routing_i_create(pff); } void routing_i_destroy(struct routing_i * instance) { - return routing.ops->routing_i_destroy(instance); + return r_ops->routing_i_destroy(instance); } void routing_fini(void) { - routing.ops->fini(); + r_ops->fini(); } diff --git a/src/ipcpd/normal/sdu_sched.c b/src/ipcpd/normal/sdu_sched.c index f3550d5c..045d536a 100644 --- a/src/ipcpd/normal/sdu_sched.c +++ b/src/ipcpd/normal/sdu_sched.c @@ -117,6 +117,8 @@ struct sdu_sched * sdu_sched_create(next_sdu_t callback) if (sdu_sched == NULL) goto fail_malloc; + assert(callback); + sdu_sched->callback = callback; for (i = 0; i < QOS_CUBE_MAX; ++i) { @@ -170,6 +172,8 @@ void sdu_sched_add(struct sdu_sched * sdu_sched, { qoscube_t qc; + /* assert(sdu_sched); */ + ipcp_flow_get_qoscube(fd, &qc); flow_set_add(sdu_sched->set[qc], fd); } @@ -179,6 +183,8 @@ void sdu_sched_del(struct sdu_sched * sdu_sched, { qoscube_t qc; + assert(sdu_sched); + ipcp_flow_get_qoscube(fd, &qc); flow_set_del(sdu_sched->set[qc], fd); } -- cgit v1.2.3 From 9de8dc4948cf7ce239232aae0889c39ffa39ede2 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Mon, 28 Aug 2017 18:54:22 +0200 Subject: tools: Add tool to connect IPCP components This enables user-written tools to instruct IPCPs to establish and tear down connections (a.k.a. adjacencies) between its internal components (Management and Data Transfer). For more info, do "irm ipcp connect" or "irm ipcp disconnect" on the command line. This commit exposes a deletion bug in the RIB where FSO's fail to unpack/parse. This will be fixed when the RIB is deprecated. --- include/ouroboros/cacep.h | 6 +- include/ouroboros/irm.h | 13 +++- src/ipcpd/ipcp.c | 28 ++++++++ src/ipcpd/ipcp.h | 6 ++ src/ipcpd/local/main.c | 4 +- src/ipcpd/normal/ae.h | 9 ++- src/ipcpd/normal/connmgr.c | 127 ++++++++++++++++++++++++++++++------ src/ipcpd/normal/connmgr.h | 6 ++ src/ipcpd/normal/dt.c | 3 +- src/ipcpd/normal/enroll.c | 14 ++-- src/ipcpd/normal/enroll.h | 3 +- src/ipcpd/normal/main.c | 5 +- src/ipcpd/shim-eth-llc/main.c | 2 + src/ipcpd/shim-udp/main.c | 4 +- src/irmd/ipcp.c | 61 +++++++++++++++++ src/irmd/ipcp.h | 8 +++ src/irmd/main.c | 82 +++++++++++++++++++++++ src/lib/ipcpd_messages.proto | 7 +- src/lib/irm.c | 66 +++++++++++++++++-- src/lib/irmd_messages.proto | 31 +++++---- src/tools/irm/CMakeLists.txt | 2 + src/tools/irm/irm_ipcp.c | 18 ++--- src/tools/irm/irm_ipcp_connect.c | 94 ++++++++++++++++++++++++++ src/tools/irm/irm_ipcp_disconnect.c | 94 ++++++++++++++++++++++++++ src/tools/irm/irm_ops.h | 6 ++ 25 files changed, 635 insertions(+), 64 deletions(-) create mode 100644 src/tools/irm/irm_ipcp_connect.c create mode 100644 src/tools/irm/irm_ipcp_disconnect.c (limited to 'src/ipcpd/normal') diff --git a/include/ouroboros/cacep.h b/include/ouroboros/cacep.h index d2b0de9a..4b557b46 100644 --- a/include/ouroboros/cacep.h +++ b/include/ouroboros/cacep.h @@ -29,9 +29,11 @@ #include #include +#define CACEP_BUF_STRLEN 64 + struct conn_info { - char ae_name[64]; - char protocol[64]; + char ae_name[CACEP_BUF_STRLEN + 1]; + char protocol[CACEP_BUF_STRLEN + 1]; uint32_t pref_version; enum proto_concrete_syntax pref_syntax; struct proto_field fixed_conc_syntax[PROTO_MAX_FIELDS]; diff --git a/include/ouroboros/irm.h b/include/ouroboros/irm.h index 5ad8f754..dc723fc0 100644 --- a/include/ouroboros/irm.h +++ b/include/ouroboros/irm.h @@ -28,8 +28,11 @@ #include -/* Name binding options */ +/* Normal IPCP components. */ +#define DT_AE "Data Transfer" +#define MGMT_AE "Management" +/* Name binding options. */ #define BIND_AP_AUTO 0x01 #define BIND_AP_UNIQUE 0x02 @@ -50,6 +53,14 @@ int irm_enroll_ipcp(pid_t api, int irm_bootstrap_ipcp(pid_t api, const struct ipcp_config * conf); +int irm_connect_ipcp(pid_t api, + const char * component, + const char * dst); + +int irm_disconnect_ipcp(pid_t api, + const char * component, + const char * dst); + int irm_bind_ap(const char * ap, const char * name, uint16_t opts, diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index d4b3a7fc..41ea4784 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -301,6 +301,32 @@ static void * mainloop(void * o) dif_info.dif_name = info.dif_name; } break; + case IPCP_MSG_CODE__IPCP_CONNECT: + ret_msg.has_result = true; + + if (ipcpi.ops->ipcp_connect == NULL) { + log_err("Connect unsupported."); + ret_msg.result = -ENOTSUP; + break; + } + + ret_msg.result = + ipcpi.ops->ipcp_connect(msg->dst_name, + msg->comp_name); + break; + case IPCP_MSG_CODE__IPCP_DISCONNECT: + ret_msg.has_result = true; + + if (ipcpi.ops->ipcp_disconnect == NULL) { + log_err("Disconnect unsupported."); + ret_msg.result = -ENOTSUP; + break; + } + + ret_msg.result = + ipcpi.ops->ipcp_disconnect(msg->dst_name, + msg->comp_name); + break; case IPCP_MSG_CODE__IPCP_REG: ret_msg.has_result = true; @@ -435,6 +461,8 @@ static void * mainloop(void * o) ipcpi.ops->ipcp_flow_dealloc(fd); break; default: + ret_msg.has_result = true; + ret_msg.result = -1; log_err("Don't know that message code"); break; } diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index cd18d198..1b2a0334 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -45,6 +45,12 @@ struct ipcp_ops { int (* ipcp_enroll)(const char * dst, struct dif_info * info); + int (* ipcp_connect)(const char * dst, + const char * component); + + int (* ipcp_disconnect)(const char * dst, + const char * component); + int (* ipcp_reg)(const uint8_t * hash); int (* ipcp_unreg)(const uint8_t * hash); diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index 37d23fc3..c6f88d78 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -323,7 +323,9 @@ static int ipcp_local_flow_dealloc(int fd) static struct ipcp_ops local_ops = { .ipcp_bootstrap = ipcp_local_bootstrap, - .ipcp_enroll = NULL, /* shim */ + .ipcp_enroll = NULL, + .ipcp_connect = NULL, + .ipcp_disconnect = NULL, .ipcp_reg = ipcp_local_reg, .ipcp_unreg = ipcp_local_unreg, .ipcp_query = ipcp_local_query, diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h index 4534cefa..3d3bdc27 100644 --- a/src/ipcpd/normal/ae.h +++ b/src/ipcpd/normal/ae.h @@ -27,6 +27,8 @@ #include "dt.h" +#define DST_MAX_STRLEN 64 + enum ae_id { AEID_DT = 0, AEID_ENROLL, @@ -36,9 +38,10 @@ enum ae_id { struct conn { struct conn_info conn_info; - struct flow_info { - int fd; - qosspec_t qs; + struct { + char dst[DST_MAX_STRLEN + 1]; + int fd; + qosspec_t qs; } flow_info; }; diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c index b6e5e31a..11f83247 100644 --- a/src/ipcpd/normal/connmgr.c +++ b/src/ipcpd/normal/connmgr.c @@ -48,7 +48,7 @@ enum connmgr_state { CONNMGR_RUNNING }; -struct ae_conn { +struct conn_el { struct list_head next; struct conn conn; }; @@ -58,15 +58,17 @@ struct ae { struct conn_info info; struct list_head conns; + struct list_head pending; + pthread_cond_t cond; pthread_mutex_t lock; }; struct { - struct ae aes[AEID_MAX]; - enum connmgr_state state; + struct ae aes[AEID_MAX]; + enum connmgr_state state; - pthread_t acceptor; + pthread_t acceptor; } connmgr; static int get_id_by_name(const char * name) @@ -85,23 +87,21 @@ static int add_ae_conn(enum ae_id id, qosspec_t qs, struct conn_info * rcv_info) { - struct ae_conn * ae_conn; + struct conn_el * el; - ae_conn = malloc(sizeof(*ae_conn)); - if (ae_conn == NULL) { + el = malloc(sizeof(*el)); + if (el == NULL) { log_err("Not enough memory."); return -1; } - ae_conn->conn.conn_info = *rcv_info; - ae_conn->conn.flow_info.fd = fd; - ae_conn->conn.flow_info.qs = qs; - - list_head_init(&ae_conn->next); + el->conn.conn_info = *rcv_info; + el->conn.flow_info.fd = fd; + el->conn.flow_info.qs = qs; pthread_mutex_lock(&connmgr.aes[id].lock); - list_add(&ae_conn->next, &connmgr.aes[id].conns); + list_add(&el->next, &connmgr.aes[id].pending); pthread_cond_signal(&connmgr.aes[id].cond); pthread_mutex_unlock(&connmgr.aes[id].lock); @@ -217,6 +217,7 @@ int connmgr_ae_init(enum ae_id id, } list_head_init(&ae->conns); + list_head_init(&ae->pending); memcpy(&connmgr.aes[id].info, info, sizeof(connmgr.aes[id].info)); @@ -241,7 +242,13 @@ void connmgr_ae_fini(enum ae_id id) pthread_mutex_lock(&ae->lock); list_for_each_safe(p, h, &ae->conns) { - struct ae_conn * e = list_entry(p, struct ae_conn, next); + struct conn_el * e = list_entry(p, struct conn_el, next); + list_del(&e->next); + free(e); + } + + list_for_each_safe(p, h, &ae->pending) { + struct conn_el * e = list_entry(p, struct conn_el, next); list_del(&e->next); free(e); } @@ -256,6 +263,84 @@ void connmgr_ae_fini(enum ae_id id) connmgr.aes[id].nbs = NULL; } +int connmgr_ipcp_connect(const char * dst, + const char * component) +{ + struct conn_el * ce; + int id; + + assert(dst); + assert(component); + + ce = malloc(sizeof(*ce)); + if (ce == NULL) { + log_dbg("Out of memory."); + return -1; + } + + id = get_id_by_name(component); + if (id < 0) { + log_dbg("No such component: %s", component); + free(ce); + return -1; + } + + /* FIXME: get the correct qos for the component. */ + if (connmgr_alloc(id, dst, NULL, &ce->conn)) { + free(ce); + return -1; + } + + if (strlen(dst) > DST_MAX_STRLEN) { + log_warn("Truncating dst length for connection."); + memcpy(ce->conn.flow_info.dst, dst, DST_MAX_STRLEN); + ce->conn.flow_info.dst[DST_MAX_STRLEN] = '\0'; + } else { + strcpy(ce->conn.flow_info.dst, dst); + } + + pthread_mutex_lock(&connmgr.aes[id].lock); + + list_add(&ce->next, &connmgr.aes[id].conns); + + pthread_mutex_unlock(&connmgr.aes[id].lock); + + return 0; +} + +int connmgr_ipcp_disconnect(const char * dst, + const char * component) +{ + struct list_head * p; + struct list_head * h; + int id; + + assert(dst); + assert(component); + + id = get_id_by_name(component); + if (id < 0) + return -1; + + pthread_mutex_lock(&connmgr.aes[id].lock); + + list_for_each_safe(p,h, &connmgr.aes[id].conns) { + struct conn_el * el = list_entry(p, struct conn_el, next); + if (strcmp(el->conn.flow_info.dst, dst) == 0) { + int ret; + pthread_mutex_unlock(&connmgr.aes[id].lock); + list_del(&el->next); + ret = connmgr_dealloc(id, &el->conn); + free(el); + return ret; + } + } + + pthread_mutex_unlock(&connmgr.aes[id].lock); + + return 0; +} + int connmgr_alloc(enum ae_id id, const char * dst, qosspec_t * qs, @@ -329,7 +414,7 @@ int connmgr_dealloc(enum ae_id id, int connmgr_wait(enum ae_id id, struct conn * conn) { - struct ae_conn * ae_conn; + struct conn_el * el; struct ae * ae; assert(id >= 0 && id < AEID_MAX); @@ -342,21 +427,21 @@ int connmgr_wait(enum ae_id id, pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock, (void *) &ae->lock); - while (list_is_empty(&ae->conns)) + while (list_is_empty(&ae->pending)) pthread_cond_wait(&ae->cond, &ae->lock); pthread_cleanup_pop(false); - ae_conn = list_first_entry((&ae->conns), struct ae_conn, next); - if (ae_conn == NULL) { + el = list_first_entry((&ae->pending), struct conn_el, next); + if (el == NULL) { pthread_mutex_unlock(&ae->lock); return -1; } - *conn = ae_conn->conn; + *conn = el->conn; - list_del(&ae_conn->next); - free(ae_conn); + list_del(&el->next); + free(el); pthread_mutex_unlock(&ae->lock); diff --git a/src/ipcpd/normal/connmgr.h b/src/ipcpd/normal/connmgr.h index 920058da..379877e6 100644 --- a/src/ipcpd/normal/connmgr.h +++ b/src/ipcpd/normal/connmgr.h @@ -43,6 +43,12 @@ int connmgr_ae_init(enum ae_id id, void connmgr_ae_fini(enum ae_id id); +int connmgr_ipcp_connect(const char * dst, + const char * component); + +int connmgr_ipcp_disconnect(const char * dst, + const char * component); + int connmgr_alloc(enum ae_id id, const char * dst, qosspec_t * qs, diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c index 19c2d3a6..aa089852 100644 --- a/src/ipcpd/normal/dt.c +++ b/src/ipcpd/normal/dt.c @@ -67,7 +67,6 @@ struct { pthread_rwlock_t lock; struct nbs * nbs; - struct ae * ae; struct nb_notifier nb_notifier; @@ -163,6 +162,8 @@ static void * dt_conn_handle(void * o) log_dbg("Got new connection."); + /* NOTE: connection acceptance policy could be here. */ + nbs_add(dt.nbs, conn); } diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index 2f7dd9bc..7f93ed3a 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -259,14 +259,17 @@ static void * enroll_handle(void * o) continue; } - if (msg->code != ENROLL_CODE__ENROLL_DONE) { + if (msg->code != ENROLL_CODE__ENROLL_DONE || !msg->has_result) { log_err("Wrong message type."); enroll_msg__free_unpacked(msg, NULL); connmgr_dealloc(AEID_ENROLL, &conn); continue; } - log_dbg("Neighbor enrollment successful."); + if (msg->result == 0) + log_dbg("Neighbor enrollment successful."); + else + log_dbg("Neigbor reported failed enrollment."); connmgr_dealloc(AEID_ENROLL, &conn); } @@ -287,13 +290,16 @@ int enroll_boot(struct conn * conn, return 0; } -int enroll_done(struct conn * conn) +int enroll_done(struct conn * conn, + int result) { enroll_msg_t msg = ENROLL_MSG__INIT; uint8_t buf[ENROLL_BUF_LEN]; ssize_t len; - msg.code = ENROLL_CODE__ENROLL_DONE; + msg.code = ENROLL_CODE__ENROLL_DONE; + msg.has_result = true; + msg.result = result; len = enroll_msg__get_packed_size(&msg); if (len < 0) { diff --git a/src/ipcpd/normal/enroll.h b/src/ipcpd/normal/enroll.h index 67c9912d..3b277e44 100644 --- a/src/ipcpd/normal/enroll.h +++ b/src/ipcpd/normal/enroll.h @@ -40,7 +40,8 @@ void enroll_bootstrap(const struct ipcp_config * conf); int enroll_boot(struct conn * conn, const char * dst); -int enroll_done(struct conn * conn); +int enroll_done(struct conn * conn, + int result); struct ipcp_config * enroll_get_conf(void); diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index d9fbc2dd..bef04b7a 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -263,11 +263,12 @@ static int normal_ipcp_enroll(const char * dst, } if (enroll_components(dt_conn.conn_info.addr)) { + enroll_done(&er_conn, -1); log_err("Failed to enroll components."); goto fail_enroll_comp; } - if (enroll_done(&er_conn)) + if (enroll_done(&er_conn, 0)) log_warn("Failed to confirm enrollment with peer."); if (connmgr_dealloc(AEID_DT, &dt_conn)) @@ -346,6 +347,8 @@ static int normal_ipcp_query(const uint8_t * dst) static struct ipcp_ops normal_ops = { .ipcp_bootstrap = normal_ipcp_bootstrap, .ipcp_enroll = normal_ipcp_enroll, + .ipcp_connect = connmgr_ipcp_connect, + .ipcp_disconnect = connmgr_ipcp_disconnect, .ipcp_reg = dir_reg, .ipcp_unreg = dir_unreg, .ipcp_query = normal_ipcp_query, diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index bcf5abe2..3d186d7a 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -1216,6 +1216,8 @@ static int eth_llc_ipcp_flow_dealloc(int fd) static struct ipcp_ops eth_llc_ops = { .ipcp_bootstrap = eth_llc_ipcp_bootstrap, .ipcp_enroll = NULL, + .ipcp_connect = NULL, + .ipcp_disconnect = NULL, .ipcp_reg = eth_llc_ipcp_reg, .ipcp_unreg = eth_llc_ipcp_unreg, .ipcp_query = eth_llc_ipcp_query, diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index 55fe19a6..0bf57741 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -1092,7 +1092,9 @@ static int ipcp_udp_flow_dealloc(int fd) static struct ipcp_ops udp_ops = { .ipcp_bootstrap = ipcp_udp_bootstrap, - .ipcp_enroll = NULL, /* shim */ + .ipcp_enroll = NULL, + .ipcp_connect = NULL, + .ipcp_disconnect = NULL, .ipcp_reg = ipcp_udp_reg, .ipcp_unreg = ipcp_udp_unreg, .ipcp_query = ipcp_udp_query, diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c index e1689b91..ed1ad924 100644 --- a/src/irmd/ipcp.c +++ b/src/irmd/ipcp.c @@ -281,6 +281,67 @@ int ipcp_enroll(pid_t api, return 0; } +int ipcp_connect(pid_t api, + const char * dst, + const char * component) +{ + ipcp_msg_t msg = IPCP_MSG__INIT; + ipcp_msg_t * recv_msg = NULL; + int ret = -1; + + msg.code = IPCP_MSG_CODE__IPCP_CONNECT; + msg.dst_name = (char *) dst; + msg.comp_name = (char *) component; + msg.has_api = true; + msg.api = api; + + recv_msg = send_recv_ipcp_msg(api, &msg); + if (recv_msg == NULL) { + log_dbg("bad msg"); + return -EIPCP; + } + + if (recv_msg->has_result == false) { + ipcp_msg__free_unpacked(recv_msg, NULL); + log_dbg("no result."); + return -EIPCP; + } + + ret = recv_msg->result; + ipcp_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + +int ipcp_disconnect(pid_t api, + const char * dst, + const char * component) +{ + ipcp_msg_t msg = IPCP_MSG__INIT; + ipcp_msg_t * recv_msg = NULL; + int ret = -1; + + msg.code = IPCP_MSG_CODE__IPCP_DISCONNECT; + msg.dst_name = (char *) dst; + msg.comp_name = (char *) component; + msg.has_api = true; + msg.api = api; + + recv_msg = send_recv_ipcp_msg(api, &msg); + if (recv_msg == NULL) + return -EIPCP; + + if (recv_msg->has_result == false) { + ipcp_msg__free_unpacked(recv_msg, NULL); + return -EIPCP; + } + + ret = recv_msg->result; + ipcp_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + int ipcp_reg(pid_t api, const uint8_t * hash, size_t len) diff --git a/src/irmd/ipcp.h b/src/irmd/ipcp.h index 67d0476f..9c861cde 100644 --- a/src/irmd/ipcp.h +++ b/src/irmd/ipcp.h @@ -42,6 +42,14 @@ int ipcp_bootstrap(pid_t api, ipcp_config_msg_t * conf, struct dif_info * info); +int ipcp_connect(pid_t api, + const char * dst, + const char * component); + +int ipcp_disconnect(pid_t api, + const char * dst, + const char * component); + int ipcp_reg(pid_t api, const uint8_t * hash, size_t len); diff --git a/src/irmd/main.c b/src/irmd/main.c index e72153ae..cc15e092 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -555,6 +555,76 @@ static int enroll_ipcp(pid_t api, return 0; } +static int connect_ipcp(pid_t api, + const char * dst, + const char * component) +{ + struct ipcp_entry * entry = NULL; + + pthread_rwlock_rdlock(&irmd.reg_lock); + + entry = get_ipcp_entry_by_api(api); + if (entry == NULL) { + pthread_rwlock_unlock(&irmd.reg_lock); + log_err("No such IPCP."); + return -EIPCP; + } + + if (entry->type != IPCP_NORMAL) { + pthread_rwlock_unlock(&irmd.reg_lock); + log_err("Cannot establish connections for this IPCP type."); + return -EIPCP; + } + + pthread_rwlock_unlock(&irmd.reg_lock); + + log_dbg("Connecting %s to %s.", component, dst); + + if (ipcp_connect(api, dst, component)) { + log_err("Could not connect IPCP."); + return -EPERM; + } + + log_info("Established %s connection between IPCP %d and %s.", + component, api, dst); + + return 0; +} + +static int disconnect_ipcp(pid_t api, + const char * dst, + const char * component) +{ + struct ipcp_entry * entry = NULL; + + pthread_rwlock_rdlock(&irmd.reg_lock); + + entry = get_ipcp_entry_by_api(api); + if (entry == NULL) { + pthread_rwlock_unlock(&irmd.reg_lock); + log_err("No such IPCP."); + return -EIPCP; + } + + if (entry->type != IPCP_NORMAL) { + pthread_rwlock_unlock(&irmd.reg_lock); + log_err("Cannot tear down connections for this IPCP type."); + return -EIPCP; + } + + pthread_rwlock_unlock(&irmd.reg_lock); + + if (ipcp_disconnect(api, dst, component)) { + log_err("Could not disconnect IPCP."); + return -EPERM; + } + + log_info("%s connection between IPCP %d and %s torn down.", + component, api, dst); + + return 0; +} + static int bind_ap(char * ap, char * name, uint16_t flags, @@ -1876,6 +1946,18 @@ void * mainloop(void * o) ret_msg.result = enroll_ipcp(msg->api, msg->dif_name[0]); break; + case IRM_MSG_CODE__IRM_CONNECT_IPCP: + ret_msg.has_result = true; + ret_msg.result = connect_ipcp(msg->api, + msg->dst_name, + msg->comp_name); + break; + case IRM_MSG_CODE__IRM_DISCONNECT_IPCP: + ret_msg.has_result = true; + ret_msg.result = disconnect_ipcp(msg->api, + msg->dst_name, + msg->comp_name); + break; case IRM_MSG_CODE__IRM_BIND_AP: ret_msg.has_result = true; ret_msg.result = bind_ap(msg->ap_name, diff --git a/src/lib/ipcpd_messages.proto b/src/lib/ipcpd_messages.proto index 2e6c0497..691b76ad 100644 --- a/src/lib/ipcpd_messages.proto +++ b/src/lib/ipcpd_messages.proto @@ -33,7 +33,9 @@ enum ipcp_msg_code { IPCP_FLOW_ALLOC = 6; IPCP_FLOW_ALLOC_RESP = 7; IPCP_FLOW_DEALLOC = 8; - IPCP_REPLY = 9; + IPCP_CONNECT = 9; + IPCP_DISCONNECT = 10; + IPCP_REPLY = 11; }; message ipcp_msg { @@ -47,5 +49,6 @@ message ipcp_msg { optional int32 api = 8; optional dif_info_msg dif_info = 9; optional int32 response = 10; - optional int32 result = 11; + optional string comp_name = 11; + optional int32 result = 12; }; diff --git a/src/lib/irm.c b/src/lib/irm.c index eec89338..ce17bf18 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -146,7 +146,65 @@ int irm_bootstrap_ipcp(pid_t api, if (recv_msg->has_result == false) { irm_msg__free_unpacked(recv_msg, NULL); - return -1; + return -EIRMD; + } + + ret = recv_msg->result; + irm_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + +int irm_connect_ipcp(pid_t api, + const char * dst, + const char * component) +{ + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * recv_msg = NULL; + int ret; + + msg.code = IRM_MSG_CODE__IRM_CONNECT_IPCP; + msg.dst_name = (char *) dst; + msg.comp_name = (char *) component; + msg.has_api = true; + msg.api = api; + + recv_msg = send_recv_irm_msg(&msg); + if (recv_msg == NULL) + return -EIRMD; + + if (recv_msg->has_result == false) { + irm_msg__free_unpacked(recv_msg, NULL); + return -EIRMD; + } + + ret = recv_msg->result; + irm_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + +int irm_disconnect_ipcp(pid_t api, + const char * dst, + const char * component) +{ + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * recv_msg = NULL; + int ret; + + msg.code = IRM_MSG_CODE__IRM_DISCONNECT_IPCP; + msg.dst_name = (char *) dst; + msg.comp_name = (char *) component; + msg.has_api = true; + msg.api = api; + + recv_msg = send_recv_irm_msg(&msg); + if (recv_msg == NULL) + return -EIRMD; + + if (recv_msg->has_result == false) { + irm_msg__free_unpacked(recv_msg, NULL); + return -EIRMD; } ret = recv_msg->result; @@ -158,15 +216,15 @@ int irm_bootstrap_ipcp(pid_t api, ssize_t irm_list_ipcps(const char * name, pid_t ** apis) { - irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t msg = IRM_MSG__INIT; irm_msg_t * recv_msg = NULL; - size_t nr = 0; + size_t nr = 0; size_t i; if (apis == NULL) return -EINVAL; - msg.code = IRM_MSG_CODE__IRM_LIST_IPCPS; + msg.code = IRM_MSG_CODE__IRM_LIST_IPCPS; msg.dst_name = (char *) name; recv_msg = send_recv_irm_msg(&msg); diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 117752c8..723f6fb3 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -31,19 +31,21 @@ enum irm_msg_code { IRM_LIST_IPCPS = 4; IRM_BOOTSTRAP_IPCP = 5; IRM_ENROLL_IPCP = 6; - IRM_BIND_AP = 7; - IRM_UNBIND_AP = 8; - IRM_API_ANNOUNCE = 9; - IRM_BIND_API = 10; - IRM_UNBIND_API = 11; - IRM_REG = 12; - IRM_UNREG = 13; - IRM_FLOW_ALLOC = 14; - IRM_FLOW_ACCEPT = 15; - IRM_FLOW_DEALLOC = 16; - IPCP_FLOW_REQ_ARR = 17; - IPCP_FLOW_ALLOC_REPLY = 18; - IRM_REPLY = 19; + IRM_CONNECT_IPCP = 7; + IRM_DISCONNECT_IPCP = 8; + IRM_BIND_AP = 9; + IRM_UNBIND_AP = 10; + IRM_API_ANNOUNCE = 11; + IRM_BIND_API = 12; + IRM_UNBIND_API = 13; + IRM_REG = 14; + IRM_UNREG = 15; + IRM_FLOW_ALLOC = 16; + IRM_FLOW_ACCEPT = 17; + IRM_FLOW_DEALLOC = 18; + IPCP_FLOW_REQ_ARR = 19; + IPCP_FLOW_ALLOC_REPLY = 20; + IRM_REPLY = 21; }; message irm_msg { @@ -63,5 +65,6 @@ message irm_msg { repeated sint32 apis = 14; optional uint32 timeo_sec = 15; optional uint32 timeo_nsec = 16; - optional sint32 result = 17; + optional string comp_name = 17; + optional sint32 result = 18; }; diff --git a/src/tools/irm/CMakeLists.txt b/src/tools/irm/CMakeLists.txt index 300ad982..895bc746 100644 --- a/src/tools/irm/CMakeLists.txt +++ b/src/tools/irm/CMakeLists.txt @@ -14,6 +14,8 @@ set(SOURCE_FILES irm_ipcp_destroy.c irm_ipcp_bootstrap.c irm_ipcp_enroll.c + irm_ipcp_connect.c + irm_ipcp_disconnect.c irm_unbind_ap.c irm_unbind_api.c irm_unbind_ipcp.c diff --git a/src/tools/irm/irm_ipcp.c b/src/tools/irm/irm_ipcp.c index 2850ac89..2f7b01c9 100644 --- a/src/tools/irm/irm_ipcp.c +++ b/src/tools/irm/irm_ipcp.c @@ -45,17 +45,19 @@ static const struct cmd { const char * cmd; int (* func)(int argc, char ** argv); } cmds[] = { - { "create", do_create_ipcp }, - { "destroy", do_destroy_ipcp }, - { "bootstrap", do_bootstrap_ipcp }, - { "enroll", do_enroll_ipcp }, - { "help", do_help }, - { NULL, NULL } + { "create", do_create_ipcp }, + { "destroy", do_destroy_ipcp }, + { "bootstrap", do_bootstrap_ipcp }, + { "enroll", do_enroll_ipcp }, + { "connect", do_connect_ipcp }, + { "disconnect", do_disconnect_ipcp }, + { "help", do_help }, + { NULL, NULL } }; static int do_cmd(const char * argv0, - int argc, - char ** argv) + int argc, + char ** argv) { const struct cmd * c; diff --git a/src/tools/irm/irm_ipcp_connect.c b/src/tools/irm/irm_ipcp_connect.c new file mode 100644 index 00000000..168c8d17 --- /dev/null +++ b/src/tools/irm/irm_ipcp_connect.c @@ -0,0 +1,94 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Connect components of normal IPC Processes + * + * Dimitri Staessens + * Sander Vrijders + * + * 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., http://www.fsf.org/about/contact/. + */ + +#include + +#include "irm_ops.h" +#include "irm_utils.h" + +#include +#include +#include + +#define DT "dt" +#define MGMT "mgmt" + +static void usage(void) +{ + printf("Usage: irm ipcp connect\n" + " name \n" + " comp \n" + " dst \n" + "where COMPONENT = {" DT " " MGMT "},\n\n"); +} + +int do_connect_ipcp(int argc, + char ** argv) +{ + char * name = NULL; + char * dst_name = NULL; + char * comp_name = NULL; + pid_t * apis = NULL; + ssize_t len = 0; + + while (argc > 0) { + if (strcmp(*argv, "name") == 0) { + name = *(argv + 1); + } else if (matches(*argv, "dst") == 0) { + dst_name = *(argv + 1); + } else if (matches(*argv, "comp") == 0) { + comp_name = *(argv + 1); + } else { + printf("\"%s\" is unknown, try \"irm " + "ipcpi connect\".\n", *argv); + return -1; + } + + argc -= 2; + argv += 2; + } + + if (name == NULL || dst_name == NULL || comp_name == NULL) { + usage(); + return -1; + } + + len = irm_list_ipcps(name, &apis); + if (len != 1) + return -1; + + if (!strcmp(comp_name, DT)) + comp_name = DT_AE; + + if (!strcmp(comp_name , MGMT)) + comp_name = MGMT_AE; + + if (irm_connect_ipcp(apis[0], dst_name, comp_name)) { + free(apis); + return -1; + } + + if (apis != NULL) + free(apis); + + return 0; +} diff --git a/src/tools/irm/irm_ipcp_disconnect.c b/src/tools/irm/irm_ipcp_disconnect.c new file mode 100644 index 00000000..8f83f3e8 --- /dev/null +++ b/src/tools/irm/irm_ipcp_disconnect.c @@ -0,0 +1,94 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Connect components of normal IPC Processes + * + * Dimitri Staessens + * Sander Vrijders + * + * 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., http://www.fsf.org/about/contact/. + */ + +#include + +#include "irm_ops.h" +#include "irm_utils.h" + +#include +#include +#include + +#define DT "dt" +#define MGMT "mgmt" + +static void usage(void) +{ + printf("Usage: irm ipcp disconnect\n" + " name \n" + " comp \n" + " dst \n" + "where COMPONENT = {" DT " " MGMT "},\n\n"); +} + +int do_disconnect_ipcp(int argc, + char ** argv) +{ + char * name = NULL; + char * dst_name = NULL; + char * comp_name = NULL; + pid_t * apis = NULL; + ssize_t len = 0; + + while (argc > 0) { + if (strcmp(*argv, "name") == 0) { + name = *(argv + 1); + } else if (matches(*argv, "dst") == 0) { + dst_name = *(argv + 1); + } else if (matches(*argv, "comp") == 0) { + comp_name = *(argv + 1); + } else { + printf("\"%s\" is unknown, try \"irm " + "ipcpi connect\".\n", *argv); + return -1; + } + + argc -= 2; + argv += 2; + } + + if (name == NULL || dst_name == NULL || comp_name == NULL) { + usage(); + return -1; + } + + len = irm_list_ipcps(name, &apis); + if (len != 1) + return -1; + + if (!strcmp(comp_name, DT)) + comp_name = DT_AE; + + if (!strcmp(comp_name , MGMT)) + comp_name = MGMT_AE; + + if (irm_disconnect_ipcp(apis[0], dst_name, comp_name)) { + free(apis); + return -1; + } + + if (apis != NULL) + free(apis); + + return 0; +} diff --git a/src/tools/irm/irm_ops.h b/src/tools/irm/irm_ops.h index 749ea13d..a2bc40b4 100644 --- a/src/tools/irm/irm_ops.h +++ b/src/tools/irm/irm_ops.h @@ -35,6 +35,12 @@ int do_bootstrap_ipcp(int argc, int do_enroll_ipcp(int argc, char ** argv); +int do_connect_ipcp(int argc, + char ** argv); + +int do_disconnect_ipcp(int argc, + char ** argv); + int bind_cmd(int argc, char ** argv); -- cgit v1.2.3 From 999b5dec615ce4cfb30ee909bdd16e79a5e2a1ce Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Mon, 28 Aug 2017 20:12:55 +0200 Subject: ipcpd: Address comments on 176698e --- src/ipcpd/normal/connmgr.c | 3 +-- src/ipcpd/normal/dt.c | 2 +- src/ipcpd/normal/main.c | 2 +- src/ipcpd/normal/pol/link_state.c | 5 ----- src/ipcpd/normal/sdu_sched.c | 2 +- 5 files changed, 4 insertions(+), 10 deletions(-) (limited to 'src/ipcpd/normal') diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c index 11f83247..fa43b97a 100644 --- a/src/ipcpd/normal/connmgr.c +++ b/src/ipcpd/normal/connmgr.c @@ -207,9 +207,8 @@ int connmgr_ae_init(enum ae_id id, ae = connmgr.aes + id; - if (pthread_mutex_init(&ae->lock, NULL)) { + if (pthread_mutex_init(&ae->lock, NULL)) return -1; - } if (pthread_cond_init(&ae->cond, NULL)) { pthread_mutex_destroy(&ae->lock); diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c index aa089852..282f6bee 100644 --- a/src/ipcpd/normal/dt.c +++ b/src/ipcpd/normal/dt.c @@ -207,7 +207,7 @@ int dt_init(enum pol_routing pr, if (connmgr_ae_init(AEID_DT, &info, dt.nbs)) { log_err("Failed to register with connmgr."); goto fail_connmgr_ae_init; - }; + } if (routing_init(pr, dt.nbs)) { log_err("Failed to init routing."); diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index bef04b7a..0a41f883 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -250,7 +250,7 @@ static int normal_ipcp_enroll(const char * dst, if (dt_start()) { log_err("Failed to initialize IPCP components."); goto fail_dt_start; - }; + } if (connmgr_alloc(AEID_DT, dst, NULL, &dt_conn)) { log_err("Failed to create a data transfer flow."); diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c index 6bc59d6b..512ced7f 100644 --- a/src/ipcpd/normal/pol/link_state.c +++ b/src/ipcpd/normal/pol/link_state.c @@ -130,11 +130,6 @@ static int link_state_neighbor_event(enum nb_event event, size_t len; uint8_t * data; - /* Only announce the flow if our address is bigger - if (ipcpi.dt_addr < conn.conn_info.addr) - return 0; - */ - path[0] = '\0'; sprintf(fso_name, "%" PRIu64 "-%" PRIu64, ipcpi.dt_addr, conn.conn_info.addr); diff --git a/src/ipcpd/normal/sdu_sched.c b/src/ipcpd/normal/sdu_sched.c index 045d536a..10b0f02f 100644 --- a/src/ipcpd/normal/sdu_sched.c +++ b/src/ipcpd/normal/sdu_sched.c @@ -172,7 +172,7 @@ void sdu_sched_add(struct sdu_sched * sdu_sched, { qoscube_t qc; - /* assert(sdu_sched); */ + assert(sdu_sched); ipcp_flow_get_qoscube(fd, &qc); flow_set_add(sdu_sched->set[qc], fd); -- cgit v1.2.3