diff options
Diffstat (limited to 'src/ipcpd')
39 files changed, 367 insertions, 877 deletions
diff --git a/src/ipcpd/CMakeLists.txt b/src/ipcpd/CMakeLists.txt index 0ead1fed..6356b1ba 100644 --- a/src/ipcpd/CMakeLists.txt +++ b/src/ipcpd/CMakeLists.txt @@ -1,14 +1,22 @@ +set(IPCP_ACCEPT_TIMEOUT 100 CACHE STRING + "Timeout for accept in IPCP mainloop threads (ms)") +set(IPCP_SCHED_THREADS 2 CACHE STRING + "Number of scheduler threads in the normal IPCP") +set(IPCP_MIN_THREADS 4 CACHE STRING + "Minimum number of worker threads in the IPCP") +set(IPCP_ADD_THREADS 4 CACHE STRING + "Number of extra threads to start when an IPCP faces thread starvation") + set(IPCP_SOURCES # Add source files here ${CMAKE_CURRENT_SOURCE_DIR}/ipcp.c ${CMAKE_CURRENT_SOURCE_DIR}/shim-data.c - ${CMAKE_CURRENT_SOURCE_DIR}/timerwheel.c ) add_subdirectory(local) add_subdirectory(normal) add_subdirectory(shim-udp) add_subdirectory(shim-eth-llc) -if (NOT APPLE) - add_subdirectory(tests) -endif () + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY) diff --git a/src/ipcpd/timerwheel.h b/src/ipcpd/config.h.in index 37a6d06a..0bef20be 100644 --- a/src/ipcpd/timerwheel.h +++ b/src/ipcpd/config.h.in @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * Ring buffer for incoming SDUs + * IPC process configuration * * Dimitri Staessens <dimitri.staessens@ugent.be> * Sander Vrijders <sander.vrijders@ugent.be> @@ -20,20 +20,30 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef OUROBOROS_IPCPD_TIMERWHEEL_H -#define OUROBOROS_IPCPD_TIMERWHEEL_H +#define PTHREAD_COND_CLOCK @PTHREAD_COND_CLOCK@ -struct timerwheel; +#define SYS_MAX_FLOWS @SYS_MAX_FLOWS@ +#define AP_RES_FDS @AP_RES_FDS@ +#define AP_MAX_FLOWS @AP_MAX_FLOWS@ -struct timerwheel * timerwheel_create(unsigned int resolution, - unsigned int max_delay); +#define IPCP_ACCEPT_TIMEOUT @IPCP_ACCEPT_TIMEOUT@ -void timerwheel_destroy(struct timerwheel * tw); +#define SOCKET_TIMEOUT @SOCKET_TIMEOUT@ -int timerwheel_add(struct timerwheel * tw, - void (* func)(void *), - void * arg, - size_t arg_len, - unsigned int delay); /* ms */ +#define SHM_BUFFER_SIZE @SHM_BUFFER_SIZE@ -#endif /* OUROBOROS_IPCPD_TIMERWHEEL_H */ +#define IPCP_MIN_THREADS @IPCP_MIN_THREADS@ +#define IPCP_ADD_THREADS @IPCP_ADD_THREADS@ + +/* normal IPCP */ +#define IPCP_SCHED_THREADS @IPCP_SCHED_THREADS@ +#define PFT_SIZE @PFT_SIZE@ + +/* shim-udp */ +#define NSUPDATE_EXEC "@NSUPDATE_EXECUTABLE@" +#define NSLOOKUP_EXEC "@NSLOOKUP_EXECUTABLE@" + +/* shim-eth-llc */ +#cmakedefine HAVE_NETMAP +#cmakedefine HAVE_BPF +#cmakedefine HAVE_RAW_SOCKETS diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 368c6eb8..300c22f4 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -20,9 +20,13 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L +#define __XSI_VISIBLE 500 + +#include "config.h" + #define OUROBOROS_PREFIX "ipcpd/ipcp" -#include <ouroboros/config.h> #include <ouroboros/hash.h> #include <ouroboros/logs.h> #include <ouroboros/time_utils.h> @@ -533,7 +537,6 @@ int ipcp_init(int argc, ipcpi.irmd_fd = -1; ipcpi.state = IPCP_NULL; - ipcpi.shim_data = NULL; ipcpi.sock_path = ipcp_sock_path(getpid()); if (ipcpi.sock_path == NULL) @@ -597,20 +600,10 @@ int ipcp_init(int argc, ipcpi.alloc_id = -1; ipcpi.csockfd = -1; - if (type != IPCP_NORMAL) { - ipcpi.shim_data = shim_data_create(); - if (ipcpi.shim_data == NULL) { - ret = -ENOMEM; - goto fail_shim_data; - } - } - pthread_condattr_destroy(&cattr); return 0; - fail_shim_data: - pthread_cond_destroy(&ipcpi.acc_cond); fail_acc_cond: pthread_cond_destroy(&ipcpi.cmd_cond); fail_cmd_cond: @@ -702,8 +695,6 @@ void ipcp_fini() free(ipcpi.sock_path); - shim_data_destroy(ipcpi.shim_data); - pthread_cond_destroy(&ipcpi.state_cond); pthread_mutex_destroy(&ipcpi.state_mtx); pthread_cond_destroy(&ipcpi.alloc_cond); diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index 422670d7..cd18d198 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -20,16 +20,14 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef IPCPD_IPCP_H -#define IPCPD_IPCP_H +#ifndef OUROBOROS_IPCPD_IPCP_H +#define OUROBOROS_IPCPD_IPCP_H -#include <ouroboros/config.h> #include <ouroboros/hash.h> #include <ouroboros/ipcp.h> +#include <ouroboros/qoscube.h> #include <ouroboros/sockets.h> -#include "shim-data.h" - #include <pthread.h> #include <time.h> #include <signal.h> @@ -80,8 +78,6 @@ struct ipcp { struct ipcp_ops * ops; int irmd_fd; - struct shim_data * shim_data; - enum ipcp_state state; pthread_rwlock_t state_lock; pthread_mutex_t state_mtx; @@ -136,4 +132,4 @@ uint8_t * ipcp_hash_dup(const uint8_t * hash); void ipcp_hash_str(char buf[], const uint8_t * hash); -#endif +#endif /* OUROBOROS_IPCPD_IPCP_H */ diff --git a/src/ipcpd/local/CMakeLists.txt b/src/ipcpd/local/CMakeLists.txt index 824b4ca6..925092bd 100644 --- a/src/ipcpd/local/CMakeLists.txt +++ b/src/ipcpd/local/CMakeLists.txt @@ -12,7 +12,7 @@ include_directories(${CURRENT_BINARY_PARENT_DIR}) include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) -set(IPCP_LOCAL_TARGET ipcpd-local CACHE STRING "IPCP_LOCAL") +set(IPCP_LOCAL_TARGET ipcpd-local CACHE INTERNAL "") set(SHIM_LOCAL_SOURCES # Add source files here diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index 241a47eb..37d23fc3 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #define OUROBOROS_PREFIX "ipcpd-local" -#include <ouroboros/config.h> #include <ouroboros/hash.h> #include <ouroboros/logs.h> #include <ouroboros/errno.h> @@ -33,6 +36,7 @@ #include <ouroboros/local-dev.h> #include "ipcp.h" +#include "shim-data.h" #include <string.h> #include <stdlib.h> @@ -44,18 +48,20 @@ #define THIS_TYPE IPCP_LOCAL struct { - int in_out[IRMD_MAX_FLOWS]; - flow_set_t * flows; - fqueue_t * fq; + struct shim_data * shim_data; - pthread_rwlock_t lock; - pthread_t sduloop; + int in_out[SYS_MAX_FLOWS]; + flow_set_t * flows; + fqueue_t * fq; + + pthread_rwlock_t lock; + pthread_t sduloop; } local_data; static int local_data_init(void) { int i; - for (i = 0; i < IRMD_MAX_FLOWS; ++i) + for (i = 0; i < SYS_MAX_FLOWS; ++i) local_data.in_out[i] = -1; local_data.flows = flow_set_create(); @@ -68,12 +74,20 @@ static int local_data_init(void) return -ENOMEM; } + local_data.shim_data = shim_data_create(); + if (local_data.shim_data == NULL) { + fqueue_destroy(local_data.fq); + flow_set_destroy(local_data.flows); + return -ENOMEM; + } + pthread_rwlock_init(&local_data.lock, NULL); return 0; } static void local_data_fini(void){ + shim_data_destroy(local_data.shim_data); flow_set_destroy(local_data.flows); fqueue_destroy(local_data.fq); pthread_rwlock_destroy(&local_data.lock); @@ -142,7 +156,7 @@ static int ipcp_local_reg(const uint8_t * hash) return -ENOMEM; } - if (shim_data_reg_add_entry(ipcpi.shim_data, hash_dup)) { + if (shim_data_reg_add_entry(local_data.shim_data, hash_dup)) { log_dbg("Failed to add " HASH_FMT " to local registry.", HASH_VAL(hash)); free(hash_dup); @@ -156,7 +170,7 @@ static int ipcp_local_reg(const uint8_t * hash) static int ipcp_local_unreg(const uint8_t * hash) { - shim_data_reg_del_entry(ipcpi.shim_data, hash); + shim_data_reg_del_entry(local_data.shim_data, hash); log_info("Unregistered " HASH_FMT ".", HASH_VAL(hash)); @@ -167,7 +181,7 @@ static int ipcp_local_query(const uint8_t * hash) { int ret; - ret = (shim_data_reg_has(ipcpi.shim_data, hash) ? 0 : -1); + ret = (shim_data_reg_has(local_data.shim_data, hash) ? 0 : -1); return ret; } diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index 8c2d4efc..7a40e94c 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -12,7 +12,7 @@ include_directories(${CURRENT_BINARY_PARENT_DIR}) include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) -set(IPCP_NORMAL_TARGET ipcpd-normal CACHE STRING "IPCP_NORMAL_TARGET") +set(IPCP_NORMAL_TARGET ipcpd-normal CACHE INTERNAL "") protobuf_generate_c(FLOW_ALLOC_SRCS FLOW_ALLOC_HDRS flow_alloc.proto) protobuf_generate_c(KAD_PROTO_SRCS KAD_PROTO_HDRS kademlia.proto) @@ -20,6 +20,10 @@ protobuf_generate_c(KAD_PROTO_SRCS KAD_PROTO_HDRS kademlia.proto) # Add GPB sources of policies last protobuf_generate_c(FSO_SRCS FSO_HDRS pol/fso.proto) +math(EXPR PFT_EXPR "1 << 12") +set(PFT_SIZE ${PFT_EXPR} CACHE STRING + "Size of the PDU forwarding table") + set(SOURCE_FILES # Add source files here addr_auth.c @@ -56,4 +60,7 @@ endif (CMAKE_BUILD_TYPE MATCHES Debug) install(TARGETS ipcpd-normal RUNTIME DESTINATION sbin) add_subdirectory(pol/tests) -add_subdirectory(tests) + +if (NOT GNU) + add_subdirectory(tests) +endif () diff --git a/src/ipcpd/normal/addr_auth.c b/src/ipcpd/normal/addr_auth.c index 56b41384..e327e2fa 100644 --- a/src/ipcpd/normal/addr_auth.c +++ b/src/ipcpd/normal/addr_auth.c @@ -22,7 +22,6 @@ #define OUROBOROS_PREFIX "addr_auth" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include "addr_auth.h" diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c index 1513c12a..a83d71c3 100644 --- a/src/ipcpd/normal/connmgr.c +++ b/src/ipcpd/normal/connmgr.c @@ -20,14 +20,16 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "normal-ipcp" -#include <ouroboros/config.h> -#include <ouroboros/logs.h> #include <ouroboros/dev.h> #include <ouroboros/cacep.h> #include <ouroboros/cdap.h> #include <ouroboros/errno.h> +#include <ouroboros/list.h> +#include <ouroboros/logs.h> #include "ae.h" #include "connmgr.h" @@ -58,15 +60,39 @@ struct { pthread_t acceptor; struct list_head aes; - pthread_mutex_t aes_lock; + pthread_rwlock_t aes_lock; } connmgr; -static int add_ae_conn(struct ae * ae, + +static int get_info_by_name(const char * name, + struct conn_info * info) +{ + struct list_head * p; + + 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); + + return -1; +} + +static int add_ae_conn(const char * name, int fd, qosspec_t qs, struct conn_info * rcv_info) { - struct ae_conn * ae_conn = NULL; + struct ae_conn * ae_conn; + struct list_head * p; + struct ae * ae = NULL; ae_conn = malloc(sizeof(*ae_conn)); if (ae_conn == NULL) { @@ -74,40 +100,45 @@ static int add_ae_conn(struct ae * ae, return -1; } - ae_conn->conn.conn_info = *rcv_info; + 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); + pthread_rwlock_wrlock(&connmgr.aes_lock); + + list_for_each(p, &connmgr.aes) { + ae = list_entry(p, struct ae, next); + if (strcmp(ae->info.ae_name, name) == 0) + break; + } + + /* 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); - return 0; -} + pthread_mutex_unlock(&ae->conn_lock); -static struct ae * find_ae_by_name(char * name) -{ - struct list_head * p = NULL; + pthread_rwlock_unlock(&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) - return ae; - } - - return NULL; + return 0; } 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; - struct ae * ae = NULL; (void) o; @@ -132,25 +163,23 @@ static void * flow_acceptor(void * o) continue; } - pthread_mutex_lock(&connmgr.aes_lock); - ae = find_ae_by_name(rcv_info.ae_name); - pthread_mutex_unlock(&connmgr.aes_lock); - - if (ae != NULL) { - if (cacep_snd(fd, &ae->info)) { - log_err("Failed to respond to req."); - flow_dealloc(fd); - continue; - } - - if (add_ae_conn(ae, fd, qs, &rcv_info)) { - log_err("Failed to add ae conn."); - flow_dealloc(fd); - continue; - } - } else { + if (get_info_by_name(rcv_info.ae_name, &snd_info)) { + log_err("Failed to get info for %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."); + flow_dealloc(fd); + continue; + } + + if (add_ae_conn(rcv_info.ae_name, fd, qs, &rcv_info)) { + log_err("Failed to add new connection."); + flow_dealloc(fd); + continue; } } @@ -159,11 +188,11 @@ static void * flow_acceptor(void * o) int connmgr_init(void) { - list_head_init(&connmgr.aes); - - if (pthread_mutex_init(&connmgr.aes_lock, NULL)) + if (pthread_rwlock_init(&connmgr.aes_lock, NULL)) return -1; + list_head_init(&connmgr.aes); + return 0; } @@ -178,13 +207,12 @@ int connmgr_start(void) void connmgr_stop(void) { pthread_cancel(connmgr.acceptor); - pthread_join(connmgr.acceptor, NULL); } static void destroy_ae(struct ae * ae) { - struct list_head * p = NULL; - struct list_head * h = NULL; + struct list_head * p; + struct list_head * h; pthread_mutex_lock(&ae->conn_lock); @@ -204,20 +232,22 @@ static void destroy_ae(struct ae * ae) void connmgr_fini(void) { - struct list_head * p = NULL; - struct list_head * n = NULL; + struct list_head * p; + struct list_head * h; + + pthread_join(connmgr.acceptor, NULL); - pthread_mutex_lock(&connmgr.aes_lock); + pthread_rwlock_wrlock(&connmgr.aes_lock); - list_for_each_safe(p, n, &connmgr.aes) { + list_for_each_safe(p, h, &connmgr.aes) { struct ae * e = list_entry(p, struct ae, next); list_del(&e->next); destroy_ae(e); } - pthread_mutex_unlock(&connmgr.aes_lock); + pthread_rwlock_unlock(&connmgr.aes_lock); - pthread_mutex_destroy(&connmgr.aes_lock); + pthread_rwlock_destroy(&connmgr.aes_lock); } struct ae * connmgr_ae_create(struct conn_info info) @@ -226,42 +256,46 @@ struct ae * connmgr_ae_create(struct conn_info info) ae = malloc(sizeof(*ae)); if (ae == NULL) - return 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)) { - free(ae); - return NULL; - } + if (pthread_mutex_init(&ae->conn_lock, NULL)) + goto fail_mutex_init; - if (pthread_cond_init(&ae->conn_cond, NULL)) { - pthread_mutex_destroy(&ae->conn_lock); - free(ae); - return NULL; - } + if (pthread_cond_init(&ae->conn_cond, NULL)) + goto fail_cond_init; + + pthread_rwlock_wrlock(&connmgr.aes_lock); - pthread_mutex_lock(&connmgr.aes_lock); list_add(&ae->next, &connmgr.aes); - pthread_mutex_unlock(&connmgr.aes_lock); + + pthread_rwlock_unlock(&connmgr.aes_lock); return ae; + + fail_cond_init: + pthread_mutex_destroy(&ae->conn_lock); + fail_mutex_init: + free(ae); + fail_malloc: + return NULL; } void connmgr_ae_destroy(struct ae * ae) { assert(ae); - pthread_mutex_lock(&connmgr.aes_lock); + pthread_rwlock_wrlock(&connmgr.aes_lock); list_del(&ae->next); - destroy_ae(ae); + pthread_rwlock_unlock(&connmgr.aes_lock); - pthread_mutex_unlock(&connmgr.aes_lock); + destroy_ae(ae); } int connmgr_alloc(struct ae * ae, @@ -311,7 +345,7 @@ int connmgr_alloc(struct ae * ae, int connmgr_wait(struct ae * ae, struct conn * conn) { - struct ae_conn * ae_conn = NULL; + struct ae_conn * ae_conn; assert(ae); assert(conn); diff --git a/src/ipcpd/normal/dht.c b/src/ipcpd/normal/dht.c index f41541d2..65e26406 100644 --- a/src/ipcpd/normal/dht.c +++ b/src/ipcpd/normal/dht.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #define OUROBOROS_PREFIX "dht" -#include <ouroboros/config.h> #include <ouroboros/hash.h> #include <ouroboros/bitmap.h> #include <ouroboros/errno.h> diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index 231ba110..feae7013 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "directory" -#include <ouroboros/config.h> #include <ouroboros/endian.h> #include <ouroboros/errno.h> #include <ouroboros/logs.h> diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c index 290c409d..173266f4 100644 --- a/src/ipcpd/normal/dt.c +++ b/src/ipcpd/normal/dt.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #define OUROBOROS_PREFIX "dt-ae" -#include <ouroboros/config.h> #include <ouroboros/bitmap.h> #include <ouroboros/errno.h> #include <ouroboros/logs.h> diff --git a/src/ipcpd/normal/dt_pci.c b/src/ipcpd/normal/dt_pci.c index e139cf91..9e6dfa89 100644 --- a/src/ipcpd/normal/dt_pci.c +++ b/src/ipcpd/normal/dt_pci.c @@ -20,7 +20,6 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#include <ouroboros/config.h> #include <ouroboros/errno.h> #include <ouroboros/rib.h> diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index be1596d0..a33239a0 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -19,9 +19,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., http://www.fsf.org/about/contact/. */ + +#define _POSIX_C_SOURCE 199309L + #define OUROBOROS_PREFIX "enrollment" -#include <ouroboros/config.h> #include <ouroboros/endian.h> #include <ouroboros/errno.h> #include <ouroboros/cdap.h> @@ -322,6 +324,7 @@ int enroll_init(void) void enroll_fini(void) { + pthread_join(enroll.listener, NULL); cdap_destroy(enroll.cdap); connmgr_ae_destroy(enroll.ae); } @@ -337,5 +340,4 @@ int enroll_start(void) void enroll_stop(void) { pthread_cancel(enroll.listener); - pthread_join(enroll.listener, NULL); } diff --git a/src/ipcpd/normal/fa.c b/src/ipcpd/normal/fa.c index 2488f017..682dc5c6 100644 --- a/src/ipcpd/normal/fa.c +++ b/src/ipcpd/normal/fa.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #define OUROBOROS_PREFIX "flow-allocator" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/fqueue.h> #include <ouroboros/rib.h> diff --git a/src/ipcpd/normal/gam.c b/src/ipcpd/normal/gam.c index 9997506c..3b4cc5de 100644 --- a/src/ipcpd/normal/gam.c +++ b/src/ipcpd/normal/gam.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "dt-gam" -#include <ouroboros/config.h> #include <ouroboros/cdap.h> #include <ouroboros/dev.h> #include <ouroboros/logs.h> diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 27fefdb6..53762415 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200809L + +#include "config.h" + #define OUROBOROS_PREFIX "normal-ipcp" -#include <ouroboros/config.h> #include <ouroboros/endian.h> #include <ouroboros/logs.h> #include <ouroboros/ipcp-dev.h> @@ -156,6 +159,7 @@ static int boot_components(void) 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; } @@ -163,7 +167,6 @@ static int boot_components(void) return 0; fail_connmgr_start: - ipcp_set_state(IPCP_INIT); enroll_stop(); fail_enroll_start: dir_fini(); diff --git a/src/ipcpd/normal/neighbors.c b/src/ipcpd/normal/neighbors.c index 0ac5e958..5da0f0df 100644 --- a/src/ipcpd/normal/neighbors.c +++ b/src/ipcpd/normal/neighbors.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 199309L + #define OUROBOROS_PREFIX "neighbors" -#include <ouroboros/config.h> #include <ouroboros/qoscube.h> #include <ouroboros/ipcp-dev.h> #include <ouroboros/errno.h> diff --git a/src/ipcpd/normal/pff.c b/src/ipcpd/normal/pff.c index acf4db1a..d6c9ddee 100644 --- a/src/ipcpd/normal/pff.c +++ b/src/ipcpd/normal/pff.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #define OUROBOROS_PREFIX "pff" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/hashtable.h> #include <ouroboros/errno.h> diff --git a/src/ipcpd/normal/pol/complete.c b/src/ipcpd/normal/pol/complete.c index e31f345a..6c6e7372 100644 --- a/src/ipcpd/normal/pol/complete.c +++ b/src/ipcpd/normal/pol/complete.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "complete" -#include <ouroboros/config.h> #include <ouroboros/qoscube.h> #include <ouroboros/rib.h> #include <ouroboros/dev.h> diff --git a/src/ipcpd/normal/pol/flat.c b/src/ipcpd/normal/pol/flat.c index 966d0d03..1fece07f 100644 --- a/src/ipcpd/normal/pol/flat.c +++ b/src/ipcpd/normal/pol/flat.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "flat-addr-auth" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/errno.h> #include <ouroboros/time_utils.h> diff --git a/src/ipcpd/normal/pol/graph.c b/src/ipcpd/normal/pol/graph.c index 7ec9c035..3611f0b0 100644 --- a/src/ipcpd/normal/pol/graph.c +++ b/src/ipcpd/normal/pol/graph.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "graph" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/errno.h> #include <ouroboros/list.h> diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c index 322b22d7..9dfed5c0 100644 --- a/src/ipcpd/normal/pol/link_state.c +++ b/src/ipcpd/normal/pol/link_state.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "link-state-routing" -#include <ouroboros/config.h> #include <ouroboros/errno.h> #include <ouroboros/list.h> #include <ouroboros/logs.h> diff --git a/src/ipcpd/normal/pol/tests/graph_test.c b/src/ipcpd/normal/pol/tests/graph_test.c index 30201800..87574187 100644 --- a/src/ipcpd/normal/pol/tests/graph_test.c +++ b/src/ipcpd/normal/pol/tests/graph_test.c @@ -20,7 +20,8 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#include <ouroboros/config.h> +#define _POSIX_C_SOURCE 200112L + #include <ouroboros/utils.h> #include <stdio.h> diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index ee81581f..ab2aa430 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "rib-manager" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/cdap.h> #include <ouroboros/list.h> diff --git a/src/ipcpd/normal/routing.c b/src/ipcpd/normal/routing.c index 5bf985fb..c00ec67c 100644 --- a/src/ipcpd/normal/routing.c +++ b/src/ipcpd/normal/routing.c @@ -20,9 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + #define OUROBOROS_PREFIX "routing" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include "routing.h" diff --git a/src/ipcpd/normal/sdu_sched.c b/src/ipcpd/normal/sdu_sched.c index b46f2563..f3550d5c 100644 --- a/src/ipcpd/normal/sdu_sched.c +++ b/src/ipcpd/normal/sdu_sched.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 199309L + +#include "config.h" + #define OUROBOROS_PREFIX "sdu-scheduler" -#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/errno.h> diff --git a/src/ipcpd/shim-data.c b/src/ipcpd/shim-data.c index 0b81a36a..747a210b 100644 --- a/src/ipcpd/shim-data.c +++ b/src/ipcpd/shim-data.c @@ -20,7 +20,10 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#include <ouroboros/config.h> +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #include <ouroboros/list.h> #include <ouroboros/time_utils.h> #include <ouroboros/errno.h> diff --git a/src/ipcpd/shim-data.h b/src/ipcpd/shim-data.h index 4fd1ad3d..983f97f6 100644 --- a/src/ipcpd/shim-data.h +++ b/src/ipcpd/shim-data.h @@ -20,8 +20,8 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef IPCPD_IPCP_DATA_H -#define IPCPD_IPCP_DATA_H +#ifndef OUROBOROS_IPCPD_IPCP_DATA_H +#define OUROBOROS_IPCPD_IPCP_DATA_H #include <ouroboros/qoscube.h> #include <ouroboros/list.h> @@ -93,4 +93,4 @@ void shim_data_dir_query_destroy(struct dir_query * query); int shim_data_dir_query_wait(struct dir_query * query, const struct timespec * timeout); -#endif /* IPCPD_SHIM_DATA_H */ +#endif /* OUROBOROS_IPCPD_SHIM_DATA_H */ diff --git a/src/ipcpd/shim-eth-llc/CMakeLists.txt b/src/ipcpd/shim-eth-llc/CMakeLists.txt index 21003cf0..e10a715f 100644 --- a/src/ipcpd/shim-eth-llc/CMakeLists.txt +++ b/src/ipcpd/shim-eth-llc/CMakeLists.txt @@ -15,26 +15,59 @@ include_directories(${CMAKE_BINARY_DIR}/include) find_path(NETMAP_C_INCLUDE_DIR net/netmap_user.h HINTS /usr/include /usr/local/include - ) +) + +mark_as_advanced(NETMAP_C_INCLUDE_DIR) + +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(DISABLE_RAW_SOCKETS FALSE CACHE BOOL + "Disable raw socket support for LLC shim") + if (NOT DISABLE_RAW_SOCKETS) + message(STATUS "Raw socket support for shim-eth-llc enabled") + set(HAVE_RAW_SOCKETS TRUE PARENT_SCOPE) + set(HAVE_LLC TRUE) + else () + message(STATUS "Raw socket support for shim-eth-llc disabled by user") + endif () +endif () -find_path(BPF_C_INCLUDE_DIR - net/bpf.h - HINTS /usr/include /usr/local/include +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + find_path(BPF_C_INCLUDE_DIR + net/bpf.h + HINTS /usr/include /usr/local/include ) -if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND - NOT BPF_C_INCLUDE_DIR STREQUAL "BPF_C_INCLUDE_DIR-NOTFOUND") - message(STATUS "Found Berkeley Packet Filter headers in ${BPF_C_INCLUDE_DIR}") - set(HAVE_BPF "1" CACHE STRING "Have Berkeley Packet Filter") + mark_as_advanced(BPF_C_INCLUDE_DIR) + + if (BPF_C_INCLUDE_DIR) + set(DISABLE_BPF FALSE CACHE BOOL + "Disable Berkeley Packet Filter support for LLC shim") + if (NOT DISABLE_BPF) + message(STATUS "Berkeley Packet Filter support " + "for shim-eth-llc enabled") + set(HAVE_BPF TRUE PARENT_SCOPE) + set(HAVE_LLC TRUE) + else () + message(STATUS "Berkeley Packet Filter support " + "for shim-eth-llc disabled by user") + endif () + endif () endif () -if (NOT NETMAP_C_INCLUDE_DIR STREQUAL "NETMAP_C_INCLUDE_DIR-NOTFOUND") - message(STATUS "Found netmap headers in ${NETMAP_C_INCLUDE_DIR}") - set(HAVE_NETMAP "1" CACHE STRING "Have netmap") - test_and_set_c_compiler_flag_global(-std=c99) +if (NETMAP_C_INCLUDE_DIR) + set(DISABLE_NETMAP FALSE CACHE BOOL + "Disable netmap support for LLC shim") + if (NOT DISABLE_NETMAP) + message(STATUS "Netmap support for shim-eth-llc enabled") + set(HAVE_NETMAP TRUE PARENT_SCOPE) + test_and_set_c_compiler_flag_global(-std=c99) + set(HAVE_LLC TRUE) + else () + message(STATUS "Netmap support for shim-eth-llc disabled by user") + endif () endif () -if (HAVE_NETMAP OR HAVE_BPF OR CMAKE_SYSTEM_NAME STREQUAL "Linux") +if (HAVE_LLC) message(STATUS "Supported raw Ethernet API found, building shim-eth-llc") protobuf_generate_c(SHIM_ETH_LLC_PROTO_SRCS SHIM_ETH_LLC_PROTO_HDRS shim_eth_llc_messages.proto) @@ -44,8 +77,7 @@ if (HAVE_NETMAP OR HAVE_BPF OR CMAKE_SYSTEM_NAME STREQUAL "Linux") ${CMAKE_CURRENT_SOURCE_DIR}/main.c ) - set(IPCP_SHIM_ETH_LLC_TARGET ipcpd-shim-eth-llc - CACHE STRING "IPCP_SHIM_ETH_LLC_TARGET") + set(IPCP_SHIM_ETH_LLC_TARGET ipcpd-shim-eth-llc CACHE INTERNAL "") add_executable(ipcpd-shim-eth-llc ${SHIM_ETH_LLC_SOURCES} ${IPCP_SOURCES} ${SHIM_ETH_LLC_PROTO_SRCS}) @@ -55,7 +87,8 @@ if (HAVE_NETMAP OR HAVE_BPF OR CMAKE_SYSTEM_NAME STREQUAL "Linux") endif () if (HAVE_NETMAP AND NOT APPLE) - target_include_directories(ipcpd-shim-eth-llc PUBLIC ${NETMAP_C_INCLUDE_DIR}) + target_include_directories(ipcpd-shim-eth-llc PUBLIC + ${NETMAP_C_INCLUDE_DIR}) endif () target_link_libraries(ipcpd-shim-eth-llc LINK_PUBLIC ouroboros diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index 55406a00..bcf5abe2 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -20,9 +20,17 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#ifdef __APPLE__ +#define _BSD_SOURCE +#define _DARWIN_C_SOURCE +#else +#define _POSIX_C_SOURCE 200112L +#endif + +#include "config.h" + #define OUROBOROS_PREFIX "ipcpd/shim-eth-llc" -#include <ouroboros/config.h> #include <ouroboros/hash.h> #include <ouroboros/errno.h> #include <ouroboros/list.h> @@ -35,6 +43,7 @@ #include <ouroboros/time_utils.h> #include "ipcp.h" +#include "shim-data.h" #include "shim_eth_llc_messages.pb-c.h" #include <signal.h> @@ -79,6 +88,7 @@ #endif #define THIS_TYPE IPCP_SHIM_ETH_LLC + #define MGMT_SAP 0x01 #define MAC_SIZE 6 #define LLC_HEADER_SIZE 3 @@ -117,6 +127,8 @@ struct mgmt_frame { }; struct { + struct shim_data * shim_data; + #if defined(HAVE_NETMAP) struct nm_desc * nmd; uint8_t hw_addr[MAC_SIZE]; @@ -125,7 +137,7 @@ struct { #elif defined(HAVE_BPF) int bpf; uint8_t hw_addr[MAC_SIZE]; -#elif defined __linux__ +#elif defined HAVE_RAW_SOCKETS int s_fd; struct sockaddr_ll device; #endif /* HAVE_NETMAP */ @@ -154,7 +166,7 @@ static int eth_llc_data_init(void) int ret = -ENOMEM; pthread_condattr_t cattr; - eth_llc_data.fd_to_ef = malloc(sizeof(struct ef) * IRMD_MAX_FLOWS); + eth_llc_data.fd_to_ef = malloc(sizeof(struct ef) * SYS_MAX_FLOWS); if (eth_llc_data.fd_to_ef == NULL) goto fail_fd_to_ef; @@ -177,12 +189,16 @@ static int eth_llc_data_init(void) for (i = 0; i < MAX_SAPS; ++i) eth_llc_data.ef_to_fd[i] = -1; - for (i = 0; i < IRMD_MAX_FLOWS; ++i) { + for (i = 0; i < SYS_MAX_FLOWS; ++i) { eth_llc_data.fd_to_ef[i].sap = -1; eth_llc_data.fd_to_ef[i].r_sap = -1; memset(ð_llc_data.fd_to_ef[i].r_addr, 0, MAC_SIZE); } + eth_llc_data.shim_data = shim_data_create(); + if (eth_llc_data.shim_data == NULL) + goto fail_shim_data; + ret = -1; if (pthread_rwlock_init(ð_llc_data.flows_lock, NULL)) @@ -206,6 +222,7 @@ static int eth_llc_data_init(void) list_head_init(ð_llc_data.mgmt_frames); return 0; + fail_mgmt_cond: pthread_condattr_destroy(&cattr); fail_condattr: @@ -213,6 +230,8 @@ static int eth_llc_data_init(void) fail_mgmt_lock: pthread_rwlock_destroy(ð_llc_data.flows_lock); fail_flows_lock: + shim_data_destroy(eth_llc_data.shim_data); + fail_shim_data: fqueue_destroy(eth_llc_data.fq); fail_fq: flow_set_destroy(eth_llc_data.np1_flows); @@ -232,12 +251,13 @@ void eth_llc_data_fini(void) nm_close(eth_llc_data.nmd); #elif defined(HAVE_BPF) close(eth_llc_data.bpf); -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) close(eth_llc_data.s_fd); #endif pthread_cond_destroy(ð_llc_data.mgmt_cond); pthread_mutex_destroy(ð_llc_data.mgmt_lock); pthread_rwlock_destroy(ð_llc_data.flows_lock); + shim_data_destroy(eth_llc_data.shim_data); fqueue_destroy(eth_llc_data.fq); flow_set_destroy(eth_llc_data.np1_flows); bmp_destroy(eth_llc_data.saps); @@ -280,7 +300,7 @@ static int eth_llc_ipcp_send_frame(const uint8_t * dst_addr, memcpy(llc_frame->src_hwaddr, #if defined(HAVE_NETMAP) || defined(HAVE_BPF) eth_llc_data.hw_addr, -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) eth_llc_data.device.sll_addr, #endif /* HAVE_NETMAP */ MAC_SIZE); @@ -306,7 +326,7 @@ static int eth_llc_ipcp_send_frame(const uint8_t * dst_addr, return -1; } -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) if (sendto(eth_llc_data.s_fd, frame, frame_len, @@ -475,7 +495,7 @@ static int eth_llc_ipcp_name_query_req(const uint8_t * hash, { shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; - if (shim_data_reg_has(ipcpi.shim_data, hash)) { + if (shim_data_reg_has(eth_llc_data.shim_data, hash)) { msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY; msg.has_hash = true; msg.hash.len = ipcp_dir_hash_len(); @@ -495,11 +515,11 @@ static int eth_llc_ipcp_name_query_reply(const uint8_t * hash, memcpy(&address, r_addr, MAC_SIZE); - shim_data_dir_add_entry(ipcpi.shim_data, hash, address); + shim_data_dir_add_entry(eth_llc_data.shim_data, hash, address); - pthread_mutex_lock(&ipcpi.shim_data->dir_queries_lock); + pthread_mutex_lock(ð_llc_data.shim_data->dir_queries_lock); - list_for_each(pos, &ipcpi.shim_data->dir_queries) { + list_for_each(pos, ð_llc_data.shim_data->dir_queries) { struct dir_query * e = list_entry(pos, struct dir_query, next); if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0) { @@ -507,7 +527,7 @@ static int eth_llc_ipcp_name_query_reply(const uint8_t * hash, } } - pthread_mutex_unlock(&ipcpi.shim_data->dir_queries_lock); + pthread_mutex_unlock(ð_llc_data.shim_data->dir_queries_lock); return 0; } @@ -526,7 +546,7 @@ static int eth_llc_ipcp_mgmt_frame(const uint8_t * buf, switch (msg->code) { case SHIM_ETH_LLC_MSG_CODE__FLOW_REQ: - if (shim_data_reg_has(ipcpi.shim_data, msg->hash.data)) { + if (shim_data_reg_has(eth_llc_data.shim_data, msg->hash.data)) { eth_llc_ipcp_sap_req(msg->ssap, r_addr, msg->hash.data, @@ -614,7 +634,7 @@ static void * eth_llc_ipcp_sdu_reader(void * o) struct nm_pkthdr hdr; #elif defined(HAVE_BPF) uint8_t buf[BPF_BLEN]; -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) uint8_t buf[ETH_FRAME_SIZE]; #endif int frame_len = 0; @@ -641,7 +661,7 @@ static void * eth_llc_ipcp_sdu_reader(void * o) } #elif defined(HAVE_BPF) frame_len = read(eth_llc_data.bpf, buf, BPF_BLEN); -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) frame_len = recv(eth_llc_data.s_fd, buf, SHIM_ETH_LLC_MAX_SDU_SIZE, 0); #endif @@ -659,7 +679,7 @@ static void * eth_llc_ipcp_sdu_reader(void * o) #if !defined(HAVE_BPF) #if defined(HAVE_NETMAP) if (memcmp(eth_llc_data.hw_addr, - #elif defined(__linux__) + #elif defined(HAVE_RAW_SOCKETS) if (memcmp(eth_llc_data.device.sll_addr, #endif /* HAVE_NETMAP */ llc_frame->dst_hwaddr, @@ -792,7 +812,7 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) int disable = 0; int blen; struct timeval tv = {0, EVENT_WAIT_TIMEOUT}; -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) struct timeval tv = {0, EVENT_WAIT_TIMEOUT}; #endif /* HAVE_NETMAP */ @@ -825,8 +845,10 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) log_dbg("Interface %s found.", conf->if_name); #if defined(HAVE_NETMAP) || defined(HAVE_BPF) - memcpy(eth_llc_data.hw_addr, LLADDR((struct sockaddr_dl *)(ifa)->ifa_addr), MAC_SIZE); - #else + memcpy(eth_llc_data.hw_addr, + LLADDR((struct sockaddr_dl *) (ifa)->ifa_addr), + MAC_SIZE); + #elif defined (HAVE_RAW_SOCKETS) memcpy(&ifr.ifr_addr, ifa->ifa_addr, sizeof(*ifa->ifa_addr)); #endif break; @@ -927,7 +949,7 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) } log_info("Using Berkeley Packet Filter."); -#elif defined(__linux__) +#elif defined(HAVE_RAW_SOCKETS) memset(&(eth_llc_data.device), 0, sizeof(eth_llc_data.device)); eth_llc_data.device.sll_ifindex = idx; eth_llc_data.device.sll_family = AF_PACKET; @@ -991,7 +1013,7 @@ static int eth_llc_ipcp_reg(const uint8_t * hash) return -ENOMEM; } - if (shim_data_reg_add_entry(ipcpi.shim_data, hash_dup)) { + if (shim_data_reg_add_entry(eth_llc_data.shim_data, hash_dup)) { log_err("Failed to add " HASH_FMT " to local registry.", HASH_VAL(hash)); free(hash_dup); @@ -1005,7 +1027,7 @@ static int eth_llc_ipcp_reg(const uint8_t * hash) static int eth_llc_ipcp_unreg(const uint8_t * hash) { - shim_data_reg_del_entry(ipcpi.shim_data, hash); + shim_data_reg_del_entry(eth_llc_data.shim_data, hash); return 0; } @@ -1019,7 +1041,7 @@ static int eth_llc_ipcp_query(const uint8_t * hash) struct dir_query * query; int ret; - if (shim_data_dir_has(ipcpi.shim_data, hash)) + if (shim_data_dir_has(eth_llc_data.shim_data, hash)) return 0; msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ; @@ -1033,18 +1055,18 @@ static int eth_llc_ipcp_query(const uint8_t * hash) if (query == NULL) return -1; - pthread_mutex_lock(&ipcpi.shim_data->dir_queries_lock); - list_add(&query->next, &ipcpi.shim_data->dir_queries); - pthread_mutex_unlock(&ipcpi.shim_data->dir_queries_lock); + pthread_mutex_lock(ð_llc_data.shim_data->dir_queries_lock); + list_add(&query->next, ð_llc_data.shim_data->dir_queries); + pthread_mutex_unlock(ð_llc_data.shim_data->dir_queries_lock); eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); ret = shim_data_dir_query_wait(query, &timeout); - pthread_mutex_lock(&ipcpi.shim_data->dir_queries_lock); + pthread_mutex_lock(ð_llc_data.shim_data->dir_queries_lock); list_del(&query->next); shim_data_dir_query_destroy(query); - pthread_mutex_unlock(&ipcpi.shim_data->dir_queries_lock); + pthread_mutex_unlock(ð_llc_data.shim_data->dir_queries_lock); return ret; } @@ -1066,11 +1088,11 @@ static int eth_llc_ipcp_flow_alloc(int fd, return -1; } - if (!shim_data_dir_has(ipcpi.shim_data, hash)) { + if (!shim_data_dir_has(eth_llc_data.shim_data, hash)) { log_err("Destination unreachable."); return -1; } - addr = shim_data_dir_get_addr(ipcpi.shim_data, hash); + addr = shim_data_dir_get_addr(eth_llc_data.shim_data, hash); pthread_rwlock_wrlock(ð_llc_data.flows_lock); diff --git a/src/ipcpd/shim-udp/CMakeLists.txt b/src/ipcpd/shim-udp/CMakeLists.txt index 3ff8dd5f..eff3f5d0 100644 --- a/src/ipcpd/shim-udp/CMakeLists.txt +++ b/src/ipcpd/shim-udp/CMakeLists.txt @@ -15,18 +15,14 @@ include_directories(${CMAKE_BINARY_DIR}/include) protobuf_generate_c(SHIM_UDP_PROTO_SRCS SHIM_UDP_PROTO_HDRS shim_udp_messages.proto) -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/shim_udp_config.h.in" - "${CMAKE_CURRENT_BINARY_DIR}/shim_udp_config.h") - -set(IPCP_SHIM_UDP_TARGET ipcpd-shim-udp CACHE STRING "IPCP_SHIM_UDP_TARGET") +set(IPCP_SHIM_UDP_TARGET ipcpd-shim-udp CACHE INTERNAL "") set(SHIM_UDP_SOURCES # Add source files here ${CMAKE_CURRENT_SOURCE_DIR}/main.c) add_executable(ipcpd-shim-udp ${SHIM_UDP_SOURCES} ${IPCP_SOURCES} - ${SHIM_UDP_PROTO_SRCS} "${CMAKE_CURRENT_BINARY_DIR}/shim_udp_config.h") + ${SHIM_UDP_PROTO_SRCS}) target_link_libraries(ipcpd-shim-udp LINK_PUBLIC ouroboros ${PROTOBUF_C_LIBRARY}) @@ -40,10 +36,12 @@ find_program(NSLOOKUP_EXECUTABLE NAMES nslookup DOC "The nslookup tool that resolves DNS names") +mark_as_advanced(NSLOOKUP_EXECUTABLE NSUPDATE_EXECUTABLE) + include(AddCompileFlags) -if (${NSUPDATE_EXECUTABLE} STREQUAL "NSUPDATE_EXECUTABLE-NOTFOUND") +if (NOT NSUPDATE_EXECUTABLE) message(STATUS "Could not find nsupdate. Disabling DDNS functionality.") -elseif (${NSLOOKUP_EXECUTABLE} STREQUAL "NSLOOKUP_EXECUTABLE-NOTFOUND") +elseif (NOT NSLOOKUP_EXECUTABLE) message(STATUS "Could not find nslookup. Disabling DNS lookups.") else () message(STATUS "Found nsupdate: ${NSUPDATE_EXECUTABLE}") @@ -56,6 +54,3 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) endif (CMAKE_BUILD_TYPE MATCHES Debug) install(TARGETS ipcpd-shim-udp RUNTIME DESTINATION sbin) - -# Enable once ipcp-shim-udp has tests -# add_subdirectory(tests) diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index 195e3bc0..55fe19a6 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -20,9 +20,12 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ +#define _POSIX_C_SOURCE 200112L + +#include "config.h" + #define OUROBOROS_PREFIX "ipcpd/shim-udp" -#include <ouroboros/config.h> #include <ouroboros/hash.h> #include <ouroboros/list.h> #include <ouroboros/utils.h> @@ -32,9 +35,9 @@ #include <ouroboros/errno.h> #include <ouroboros/logs.h> -#include "shim_udp_messages.pb-c.h" #include "ipcp.h" -#include "shim_udp_config.h" +#include "shim-data.h" +#include "shim_udp_messages.pb-c.h" #include <string.h> #include <sys/socket.h> @@ -68,6 +71,8 @@ struct uf { }; struct { + struct shim_data * shim_data; + uint32_t ip_addr; uint32_t dns_addr; /* listen server */ @@ -79,7 +84,7 @@ struct { fd_set flow_fd_s; /* bidir mappings of (n - 1) file descriptor to (n) flow descriptor */ int uf_to_fd[FD_SETSIZE]; - struct uf fd_to_uf[IRMD_MAX_FLOWS]; + struct uf fd_to_uf[SYS_MAX_FLOWS]; pthread_rwlock_t flows_lock; pthread_t sduloop; @@ -98,7 +103,7 @@ static int udp_data_init(void) for (i = 0; i < FD_SETSIZE; ++i) udp_data.uf_to_fd[i] = -1; - for (i = 0; i < IRMD_MAX_FLOWS; ++i) { + for (i = 0; i < SYS_MAX_FLOWS; ++i) { udp_data.fd_to_uf[i].skfd = -1; udp_data.fd_to_uf[i].udp = -1; } @@ -115,6 +120,13 @@ static int udp_data_init(void) return -ENOMEM; } + udp_data.shim_data = shim_data_create(); + if (udp_data.shim_data == NULL) { + fqueue_destroy(udp_data.fq); + flow_set_destroy(udp_data.np1_flows); + return -ENOMEM; + } + pthread_rwlock_init(&udp_data.flows_lock, NULL); pthread_cond_init(&udp_data.fd_set_cond, NULL); pthread_mutex_init(&udp_data.fd_set_lock, NULL); @@ -127,6 +139,8 @@ static void udp_data_fini(void) flow_set_destroy(udp_data.np1_flows); fqueue_destroy(udp_data.fq); + shim_data_destroy(udp_data.shim_data); + pthread_rwlock_destroy(&udp_data.flows_lock); pthread_mutex_destroy(&udp_data.fd_set_lock); pthread_cond_destroy(&udp_data.fd_set_cond); @@ -322,7 +336,7 @@ static int udp_port_to_fd(int udp_port) { int i; - for (i = 0; i < IRMD_MAX_FLOWS; ++i) + for (i = 0; i < SYS_MAX_FLOWS; ++i) if (udp_data.fd_to_uf[i].udp == udp_port) return i; @@ -765,7 +779,7 @@ static int ipcp_udp_reg(const uint8_t * hash) return -ENOMEM; } - if (shim_data_reg_add_entry(ipcpi.shim_data, hash_dup)) { + if (shim_data_reg_add_entry(udp_data.shim_data, hash_dup)) { log_err("Failed to add " HASH_FMT " to local registry.", HASH_VAL(hash)); free(hash_dup); @@ -794,7 +808,7 @@ static int ipcp_udp_reg(const uint8_t * hash) dnsstr, hashstr, DNS_TTL, ipstr); if (ddns_send(cmd)) { - shim_data_reg_del_entry(ipcpi.shim_data, hash_dup); + shim_data_reg_del_entry(udp_data.shim_data, hash_dup); return -1; } } @@ -835,7 +849,7 @@ static int ipcp_udp_unreg(const uint8_t * hash) } #endif - shim_data_reg_del_entry(ipcpi.shim_data, hash); + shim_data_reg_del_entry(udp_data.shim_data, hash); log_dbg("Unregistered " HASH_FMT ".", HASH_VAL(hash)); @@ -855,7 +869,7 @@ static int ipcp_udp_query(const uint8_t * hash) ipcp_hash_str(hashstr, hash); - if (shim_data_dir_has(ipcpi.shim_data, hash)) + if (shim_data_dir_has(udp_data.shim_data, hash)) return 0; #ifdef CONFIG_OUROBOROS_ENABLE_DNS @@ -880,7 +894,7 @@ static int ipcp_udp_query(const uint8_t * hash) } #endif - if (shim_data_dir_add_entry(ipcpi.shim_data, hash, ip_addr)) { + if (shim_data_dir_add_entry(udp_data.shim_data, hash, ip_addr)) { log_err("Failed to add directory entry."); return -1; } @@ -926,12 +940,12 @@ static int ipcp_udp_flow_alloc(int fd, return -1; } - if (!shim_data_dir_has(ipcpi.shim_data, dst)) { + if (!shim_data_dir_has(udp_data.shim_data, dst)) { log_dbg("Could not resolve destination."); close(skfd); return -1; } - ip_addr = (uint32_t) shim_data_dir_get_addr(ipcpi.shim_data, dst); + ip_addr = (uint32_t) shim_data_dir_get_addr(udp_data.shim_data, dst); /* connect to server (store the remote IP address in the fd) */ memset((char *) &r_saddr, 0, sizeof(r_saddr)); diff --git a/src/ipcpd/shim-udp/shim_udp_config.h.in b/src/ipcpd/shim-udp/shim_udp_config.h.in deleted file mode 100644 index c32210e9..00000000 --- a/src/ipcpd/shim-udp/shim_udp_config.h.in +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Configuration information specific for the shim UDP - * - * Sander Vrijders <sander.vrijders@intec.ugent.be> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#ifndef OUROBOROS_SHIM_UDP_CONFIG -#define OUROBOROS_SHIM_UDP_CONFIG - -#define NSUPDATE_EXEC "@NSUPDATE_EXECUTABLE@" -#define NSLOOKUP_EXEC "@NSLOOKUP_EXECUTABLE@" - -#endif diff --git a/src/ipcpd/shim-udp/tests/CMakeLists.txt b/src/ipcpd/shim-udp/tests/CMakeLists.txt deleted file mode 100644 index bdd7defb..00000000 --- a/src/ipcpd/shim-udp/tests/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -get_filename_component(PARENT_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) -get_filename_component(PARENT_BINARY_PATH ${CMAKE_CURRENT_BINARY_DIR} DIRECTORY) -get_filename_component(PARENT_DIR ${PARENT_SOURCE_PATH} NAME) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -include_directories(${PARENT_SOURCE_PATH}) -include_directories(${PARENT_BINARY_PATH}) - -include_directories(${CMAKE_SOURCE_DIR}/include) -include_directories(${CMAKE_BINARY_DIR}/include) - -create_test_sourcelist(${PARENT_DIR}_tests test_suite.c - # Add new tests here - shim_udp_test.c -) - -add_executable(${PARENT_DIR}_test EXCLUDE_FROM_ALL ${IPCP_SOURCES} ${${PARENT_DIR}_tests}) -target_link_libraries(${PARENT_DIR}_test ouroboros) - -include(MacroAddCompileFlags) -MACRO_ADD_COMPILE_FLAGS(${PARENT_DIR}_test -DMAKE_CHECK) - -add_dependencies(check ${PARENT_DIR}_test) - -set(tests_to_run ${${PARENT_DIR}_tests}) -remove(tests_to_run test_suite.c) - -foreach(test ${tests_to_run}) - get_filename_component(test_name ${test} NAME_WE) - add_test(${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name}) -endforeach(test) diff --git a/src/ipcpd/shim-udp/tests/shim_udp_test.c b/src/ipcpd/shim-udp/tests/shim_udp_test.c deleted file mode 100644 index 88669a9e..00000000 --- a/src/ipcpd/shim-udp/tests/shim_udp_test.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Test of the Shim UDP IPCP Daemon - * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#include <ouroboros/config.h> -#include <ouroboros/ipcp.h> -#include <ouroboros/utils.h> -#include <ouroboros/shm_du_map.h> -#include <sys/types.h> -#include <stdlib.h> -#include "main.c" - -#include <ouroboros/logs.h> - -struct ipcp * _ipcp; - -int shim_udp_test(int argc, char ** argv) -{ - struct shm_du_map * dum; - char * ipcp_name = "test-shim-ipcp"; - int i = 0; - - char bogus[16]; - memset(&bogus, 0, 16); - - struct ipcp_config conf; - memset(&conf, 0, sizeof conf); - conf.dif_name = strdup("test-dif"); - conf.type = IPCP_SHIM_UDP; - conf.ip_addr = 0; - - dum = shm_du_map_create(); - if (dum == NULL) { - log_err("Failed to create shared memory."); - exit(1); - } - - _ipcp = ipcp_udp_create(ipcp_name); - if (_ipcp == NULL) { - log_err("Could not instantiate shim IPCP."); - shm_du_map_destroy(dum); - exit(1); - } - - if (ipcp_udp_bootstrap(&conf)) { - log_err("Could not bootstrap."); - } - - if (ipcp_udp_name_reg("bogus name")) { - log_err("Failed to register application."); - shm_du_map_destroy(dum); - exit(1); - } - - if (ipcp_udp_name_unreg("bogus name")) { - log_err("Failed to unregister application."); - shm_du_map_destroy(dum); - exit(1); - } - - for (i = 0; i < 1000; ++i) { - sprintf(bogus, "bogus name %4d", i); - if (ipcp_udp_name_reg(bogus)) { - log_err("Failed to register application %s.", bogus); - shm_du_map_destroy(dum); - exit(1); - } - } - - for (i = 0; i < 1000; ++i) { - sprintf(bogus, "bogus name %4d", i); - if(ipcp_udp_name_unreg(bogus)) { - log_err("Failed to unregister application %s.", bogus); - shm_du_map_destroy(dum); - exit(1); - } - } - - shm_du_map_destroy(dum); - - exit(0); -} diff --git a/src/ipcpd/tests/CMakeLists.txt b/src/ipcpd/tests/CMakeLists.txt deleted file mode 100644 index 9b5eeaa1..00000000 --- a/src/ipcpd/tests/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -get_filename_component(CURRENT_SOURCE_PARENT_DIR - ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) -get_filename_component(CURRENT_BINARY_PARENT_DIR - ${CMAKE_CURRENT_BINARY_DIR} DIRECTORY) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -include_directories(${CURRENT_SOURCE_PARENT_DIR}) -include_directories(${CURRENT_BINARY_PARENT_DIR}) - -include_directories(${CMAKE_SOURCE_DIR}/include) -include_directories(${CMAKE_BINARY_DIR}/include) - -get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) -get_filename_component(PARENT_DIR ${PARENT_PATH} NAME) - -create_test_sourcelist(${PARENT_DIR}_tests test_suite.c - # Add new tests here - timerwheel_test.c - ) - -add_executable(${PARENT_DIR}_test EXCLUDE_FROM_ALL ${${PARENT_DIR}_tests}) -target_link_libraries(${PARENT_DIR}_test ouroboros) - -add_dependencies(check ${PARENT_DIR}_test) - -set(tests_to_run ${${PARENT_DIR}_tests}) -remove(tests_to_run test_suite.c) - -foreach (test ${tests_to_run}) - get_filename_component(test_name ${test} NAME_WE) - add_test(${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name}) -endforeach (test) diff --git a/src/ipcpd/tests/timerwheel_test.c b/src/ipcpd/tests/timerwheel_test.c deleted file mode 100644 index 6ba1b890..00000000 --- a/src/ipcpd/tests/timerwheel_test.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Test of the timer wheel - * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#include "timerwheel.c" - -#include <pthread.h> -#include <time.h> -#include <stdlib.h> -#include <stdio.h> - -#define MAX_ELEMENTS 100 -#define MAX_RESOLUTION 10 /* ms */ -#define MAX_ADDITIONS 1000 - -int total; - -int add(void * o) -{ - total += *((int *) o); - return 0; -} - -int timerwheel_test(int argc, char ** argv) -{ - struct timerwheel * tw; - long resolution; - long elements; - struct timespec wait; - - int additions; - - int check_total = 0; - - int i; - - (void) argc; - (void) argv; - - total = 0; - - srand(time(NULL)); - - resolution = rand() % (MAX_RESOLUTION - 1) + 1; - elements = rand() % (MAX_ELEMENTS - 10) + 10; - - tw = timerwheel_create(resolution, resolution * elements); - if (tw == NULL) { - printf("Failed to create timerwheel.\n"); - return -1; - } - - wait.tv_sec = (resolution * elements) / 1000; - wait.tv_nsec = ((resolution * elements) % 1000) * MILLION; - - additions = rand() % MAX_ADDITIONS + 1000; - - for (i = 0; i < additions; ++i) { - int delay = rand() % (resolution * elements); - int var = rand() % 5; - check_total += var; - if (timerwheel_add(tw, - (void (*)(void *)) add, - (void *) &var, - sizeof(var), - delay)) { - printf("Failed to add function."); - return -1; - } - } - - nanosleep(&wait, NULL); - - /* On some systems and VMs, the scheduler may be too slow. */ - if (total != check_total) - nanosleep(&wait, NULL); - - timerwheel_destroy(tw); - - if (total != check_total) { - printf("Totals do not match.\n"); - return -1; - } - - return 0; -} diff --git a/src/ipcpd/timerwheel.c b/src/ipcpd/timerwheel.c deleted file mode 100644 index 6086181a..00000000 --- a/src/ipcpd/timerwheel.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Timerwheel - * - * Dimitri Staessens <dimitri.staessens@ugent.be> - * Sander Vrijders <sander.vrijders@ugent.be> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#include <ouroboros/config.h> -#include <ouroboros/time_utils.h> -#include <ouroboros/errno.h> -#include <ouroboros/list.h> - -#include <pthread.h> -#include <stdlib.h> -#include <assert.h> -#include <string.h> - -#define FRAC 10 /* accuracy of the timer */ - -#define tw_used(tw) ((tw->head + tw->elements - tw->tail) & (tw->elements - 1)); -#define tw_free(tw) (tw_used(tw) + 1 < tw->elements) -#define tw_empty(tw) (tw->head == tw->tail) - -enum tw_state { - TW_NULL = 0, - TW_RUNNING, - TW_DESTROY -}; - -struct tw_f { - struct list_head next; - void (* func)(void *); - void * arg; -}; - -struct tw_el { - struct list_head funcs; - struct timespec expiry; -}; - -struct timerwheel { - struct tw_el * wheel; - - struct timespec intv; - - size_t pos; - - struct list_head wq; - - pthread_cond_t work; - pthread_mutex_t lock; - - int resolution; - unsigned int elements; - - enum tw_state state; - pthread_mutex_t s_lock; - - pthread_t ticker; - pthread_t worker; -}; - -static void tw_el_fini(struct tw_el * e) -{ - struct list_head * p; - struct list_head * h; - - list_for_each_safe(p, h, &e->funcs) { - struct tw_f * f = list_entry(p, struct tw_f, next); - list_del(&f->next); - if (f->arg != NULL) - free(f->arg); - } -} - -static enum tw_state tw_get_state(struct timerwheel * tw) -{ - enum tw_state state; - - assert(tw); - - pthread_mutex_lock(&tw->s_lock); - - state = tw->state; - - pthread_mutex_unlock(&tw->s_lock); - - return state; -} - -static void tw_set_state(struct timerwheel * tw, enum tw_state state) -{ - assert(tw); - assert(state != TW_NULL); - - pthread_mutex_lock(&tw->s_lock); - - tw->state = state; - - pthread_mutex_unlock(&tw->s_lock); -} - -static void * worker(void * o) -{ - struct list_head * p; - struct list_head * h; - - struct timerwheel * tw = (struct timerwheel *) o; - struct timespec dl; - struct timespec now; - - clock_gettime(PTHREAD_COND_CLOCK, &now); - - ts_add(&now, &tw->intv, &dl); - - pthread_mutex_lock(&tw->lock); - - while (tw_get_state(tw) == TW_RUNNING) { - if (pthread_cond_timedwait(&tw->work, &tw->lock, &dl) - == ETIMEDOUT) - ts_add(&dl, &tw->intv, &dl); - - list_for_each_safe(p, h, &tw->wq) { - struct tw_f * f = list_entry(p, struct tw_f, next); - list_del(&f->next); - pthread_mutex_unlock(&tw->lock); - f->func(f->arg); - if (f->arg != NULL) - free(f->arg); - free(f); - - pthread_mutex_lock(&tw->lock); - } - } - - pthread_mutex_unlock(&tw->lock); - - return (void *) o; -} - -static void * movement(void * o) -{ - struct timerwheel * tw = (struct timerwheel *) o; - struct timespec now = {0, 0}; - long ms = tw->resolution * tw->elements; - struct timespec total = {ms / 1000, - (ms % 1000) * MILLION}; - struct list_head * p; - struct list_head * h; - - while (tw_get_state(tw) == TW_RUNNING) { - clock_gettime(CLOCK_MONOTONIC, &now); - - pthread_mutex_lock(&tw->lock); - - if (ts_diff_us(&tw->wheel[tw->pos].expiry, &now) < 0) { - pthread_mutex_unlock(&tw->lock); - nanosleep(&tw->intv, NULL); - continue; - } - - list_for_each_safe(p, h, &tw->wheel[tw->pos].funcs) { - struct tw_f * f = list_entry(p, struct tw_f, next); - list_del(&f->next); - list_add(&f->next, &tw->wq); - } - - ts_add(&tw->wheel[tw->pos].expiry, - &total, - &tw->wheel[tw->pos].expiry); - - tw->pos = (tw->pos + 1) & (tw->elements - 1); - - pthread_cond_signal(&tw->work); - - pthread_mutex_unlock(&tw->lock); - } - - return (void *) 0; -} - -struct timerwheel * timerwheel_create(unsigned int resolution, - unsigned int max_delay) -{ - struct timespec now = {0, 0}; - struct timespec res_ts = {resolution / 1000, - (resolution % 1000) * MILLION}; - unsigned long i; - - struct timerwheel * tw; - - pthread_condattr_t cattr; - - assert(resolution != 0); - - tw = malloc(sizeof(*tw)); - if (tw == NULL) - return NULL; - - if (pthread_mutex_init(&tw->lock, NULL)) - return NULL; - - tw->elements = 1; - - while (tw->elements < max_delay / resolution) - tw->elements <<= 1; - - tw->wheel = malloc(sizeof(*tw->wheel) * tw->elements); - if (tw->wheel == NULL) { - free(tw); - return NULL; - } - - tw->resolution = resolution; - - tw->intv.tv_sec = (tw->resolution / FRAC) / 1000; - tw->intv.tv_nsec = ((tw->resolution / FRAC) % 1000) * MILLION; - - list_head_init(&tw->wq); - - if (pthread_mutex_init(&tw->lock, NULL)) { - free(tw->wheel); - free(tw); - return NULL; - } - - if (pthread_mutex_init(&tw->s_lock, NULL)) { - pthread_mutex_destroy(&tw->lock); - free(tw->wheel); - free(tw); - return NULL; - } - - if (pthread_condattr_init(&cattr)) { - pthread_mutex_destroy(&tw->lock); - free(tw->wheel); - free(tw); - return NULL; - } -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - if (pthread_cond_init(&tw->work, &cattr)) { - pthread_mutex_destroy(&tw->s_lock); - pthread_mutex_destroy(&tw->lock); - free(tw->wheel); - free(tw); - return NULL; - } - - tw->pos = 0; - tw->state = TW_RUNNING; - - clock_gettime(CLOCK_MONOTONIC, &now); - now.tv_nsec -= (now.tv_nsec % MILLION); - - for (i = 0; i < tw->elements; ++i) { - list_head_init(&tw->wheel[i].funcs); - tw->wheel[i].expiry = now; - ts_add(&now, &res_ts, &now); - } - - if (pthread_create(&tw->worker, NULL, worker, (void *) tw)) { - pthread_cond_destroy(&tw->work); - pthread_mutex_destroy(&tw->s_lock); - pthread_mutex_destroy(&tw->lock); - free(tw->wheel); - free(tw); - return NULL; - } - - if (pthread_create(&tw->ticker, NULL, movement, (void *) tw)) { - tw_set_state(tw, TW_DESTROY); - pthread_join(tw->worker, NULL); - pthread_cond_destroy(&tw->work); - pthread_mutex_destroy(&tw->s_lock); - pthread_mutex_destroy(&tw->lock); - free(tw->wheel); - free(tw); - return NULL; - } - - return tw; -} - -void timerwheel_destroy(struct timerwheel * tw) -{ - unsigned long i; - - struct list_head * p; - struct list_head * h; - - tw_set_state(tw, TW_DESTROY); - - pthread_join(tw->ticker, NULL); - pthread_join(tw->worker, NULL); - - for (i = 0; i < tw->elements; ++i) - tw_el_fini(&tw->wheel[i]); - - pthread_mutex_lock(&tw->lock); - - list_for_each_safe(p, h, &tw->wq) { - struct tw_f * f = list_entry(p, struct tw_f, next); - list_del(&f->next); - if (f->arg != NULL) - free(f->arg); - free(f); - } - - pthread_mutex_unlock(&tw->lock); - - pthread_cond_destroy(&tw->work); - pthread_mutex_destroy(&tw->lock); - pthread_mutex_destroy(&tw->s_lock); - - free(tw->wheel); - free(tw); -} - -int timerwheel_add(struct timerwheel * tw, - void (* func)(void *), - void * arg, - size_t arg_len, - unsigned int delay) -{ - int pos; - struct tw_f * f = malloc(sizeof(*f)); - if (f == NULL) - return -ENOMEM; - - f->func = func; - f->arg = malloc(arg_len); - if (f->arg == NULL) { - free(f); - return -ENOMEM; - } - - memcpy(f->arg, arg, arg_len); - - assert(delay < tw->elements * tw->resolution); - - pthread_mutex_lock(&tw->lock); - - pos = (tw->pos + delay / tw->resolution) & (tw->elements - 1); - list_add(&f->next, &tw->wheel[pos].funcs); - - pthread_mutex_unlock(&tw->lock); - - return 0; -} |