diff options
Diffstat (limited to 'src/ipcpd/raptor')
-rw-r--r-- | src/ipcpd/raptor/CMakeLists.txt | 50 | ||||
-rw-r--r-- | src/ipcpd/raptor/main.c | 1114 |
2 files changed, 0 insertions, 1164 deletions
diff --git a/src/ipcpd/raptor/CMakeLists.txt b/src/ipcpd/raptor/CMakeLists.txt deleted file mode 100644 index 1883d9bb..00000000 --- a/src/ipcpd/raptor/CMakeLists.txt +++ /dev/null @@ -1,50 +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) - -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - find_path(RAPTOR_KERNEL_MODULE - NAMES - raptor.ko.gz - raptor.ko.xz - HINTS - /lib/modules/${CMAKE_SYSTEM_VERSION}/extra - ) - - mark_as_advanced(RAPTOR_KERNEL_MODULE) - - if (RAPTOR_KERNEL_MODULE) - set(DISABLE_RAPTOR FALSE CACHE BOOL - "Disable support for raptor devices") - if (NOT DISABLE_RAPTOR) - message(STATUS "Kernel module for raptor found. Building raptor.") - set(IPCP_RAPTOR_TARGET ipcpd-raptor CACHE INTERNAL "") - - set(RAPTOR_SOURCES - # Add source files here - ${CMAKE_CURRENT_SOURCE_DIR}/main.c) - - add_executable(ipcpd-raptor ${RAPTOR_SOURCES} ${IPCP_SOURCES}) - target_link_libraries(ipcpd-raptor LINK_PUBLIC ouroboros-dev) - - include(AddCompileFlags) - if (CMAKE_BUILD_TYPE MATCHES "Debug*") - add_compile_flags(ipcpd-raptor -DCONFIG_OUROBOROS_DEBUG) - endif () - - install(TARGETS ipcpd-raptor RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}) - else () - message(STATUS "Raptor support disabled by user") - endif () - endif () -endif () diff --git a/src/ipcpd/raptor/main.c b/src/ipcpd/raptor/main.c deleted file mode 100644 index bfb5af92..00000000 --- a/src/ipcpd/raptor/main.c +++ /dev/null @@ -1,1114 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2021 - * - * IPC process using the Raptor FPGA. - * - * Alexander D'hoore <[email protected]> - * Dimitri Staessens <[email protected]> - * Sander Vrijders <[email protected]> - * - * 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 _DEFAULT_SOURCE - -#include "config.h" - -#define OUROBOROS_PREFIX "ipcpd/raptor" - -#include <ouroboros/hash.h> -#include <ouroboros/errno.h> -#include <ouroboros/list.h> -#include <ouroboros/utils.h> -#include <ouroboros/bitmap.h> -#include <ouroboros/dev.h> -#include <ouroboros/local-dev.h> -#include <ouroboros/ipcp-dev.h> -#include <ouroboros/fqueue.h> -#include <ouroboros/logs.h> -#include <ouroboros/time_utils.h> - -#include "ipcp.h" -#include "shim-data.h" - -#include <net/if.h> -#include <signal.h> -#include <stdlib.h> -#include <pthread.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <malloc.h> - -#ifdef __linux__ -#include <linux/if_packet.h> -#include <linux/if_ether.h> -#endif - -#include <poll.h> -#include <sys/mman.h> - -#define THIS_TYPE IPCP_RAPTOR -#define MGMT_EID 0x01 -#define MAC_SIZE 6 -#define MAX_EIDS 64 - -#define EVENT_WAIT_TIMEOUT 100 /* us */ -#define NAME_QUERY_TIMEOUT 2000 /* ms */ -#define MGMT_TIMEOUT 100 /* ms */ - -#define IOCTL_SEND 0xAD420000 -#define IOCTL_RECV 0xAD430000 -#define IOCTL_SEND_DONE 0xAD440000 -#define IOCTL_RECV_DONE 0xAD450000 -#define IOCTL_RECV_NEED 0xAD460000 - -#define RAPTOR_PAGE ((1 << 12) - 200) /* 4kB - 200 */ -#define RAPTOR_PAGE_MASK (~0xFFF) - -#define RAPTOR_BATCH 100 -#define RAPTOR_HEADER 3 - -#define FLOW_REQ 0 -#define FLOW_REPLY 1 -#define NAME_QUERY_REQ 2 -#define NAME_QUERY_REPLY 3 - -struct mgmt_msg { - uint8_t code; - uint8_t seid; - uint8_t deid; - int8_t response; - /* QoS parameters from spec, aligned */ - uint32_t loss; - uint64_t bandwidth; - uint32_t ber; - uint32_t max_gap; - uint32_t delay; - uint8_t in_order; - uint8_t availability; -} __attribute__((packed)); - -struct ef { - int8_t eid; - int8_t r_eid; -}; - -struct mgmt_frame { - struct list_head next; - uint8_t buf[RAPTOR_PAGE]; - size_t len; -}; - -struct { - struct shim_data * shim_data; - - int ioctl_fd; - - struct bmp * eids; - fset_t * np1_flows; - fqueue_t * fq; - int * ef_to_fd; - struct ef * fd_to_ef; - pthread_rwlock_t flows_lock; - - pthread_t send_thread; - pthread_t recv_thread; - pthread_t send_done_thread; - pthread_t recv_done_thread; - - /* Handle mgmt frames in a different thread */ - pthread_t mgmt_handler; - pthread_mutex_t mgmt_lock; - pthread_cond_t mgmt_cond; - struct list_head mgmt_frames; - -} raptor_data; - -static int raptor_data_init(void) -{ - int i; - int ret = -ENOMEM; - pthread_condattr_t cattr; - - raptor_data.fd_to_ef = - malloc(sizeof(*raptor_data.fd_to_ef) * SYS_MAX_FLOWS); - if (raptor_data.fd_to_ef == NULL) - goto fail_fd_to_ef; - - raptor_data.ef_to_fd = - malloc(sizeof(*raptor_data.ef_to_fd) * MAX_EIDS); - if (raptor_data.ef_to_fd == NULL) - goto fail_ef_to_fd; - - raptor_data.eids = bmp_create(MAX_EIDS, 2); - if (raptor_data.eids == NULL) - goto fail_eids; - - raptor_data.np1_flows = fset_create(); - if (raptor_data.np1_flows == NULL) - goto fail_np1_flows; - - raptor_data.fq = fqueue_create(); - if (raptor_data.fq == NULL) - goto fail_fq; - - for (i = 0; i < MAX_EIDS; ++i) - raptor_data.ef_to_fd[i] = -1; - - for (i = 0; i < SYS_MAX_FLOWS; ++i) { - raptor_data.fd_to_ef[i].eid = -1; - raptor_data.fd_to_ef[i].r_eid = -1; - } - - raptor_data.shim_data = shim_data_create(); - if (raptor_data.shim_data == NULL) - goto fail_shim_data; - - ret = -1; - - if (pthread_rwlock_init(&raptor_data.flows_lock, NULL)) - goto fail_flows_lock; - - if (pthread_mutex_init(&raptor_data.mgmt_lock, NULL)) - goto fail_mgmt_lock; - - if (pthread_condattr_init(&cattr)) - goto fail_condattr; - -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - - if (pthread_cond_init(&raptor_data.mgmt_cond, &cattr)) - goto fail_mgmt_cond; - - pthread_condattr_destroy(&cattr); - - list_head_init(&raptor_data.mgmt_frames); - - return 0; - - fail_mgmt_cond: - pthread_condattr_destroy(&cattr); - fail_condattr: - pthread_mutex_destroy(&raptor_data.mgmt_lock); - fail_mgmt_lock: - pthread_rwlock_destroy(&raptor_data.flows_lock); - fail_flows_lock: - shim_data_destroy(raptor_data.shim_data); - fail_shim_data: - fqueue_destroy(raptor_data.fq); - fail_fq: - fset_destroy(raptor_data.np1_flows); - fail_np1_flows: - bmp_destroy(raptor_data.eids); - fail_eids: - free(raptor_data.ef_to_fd); - fail_ef_to_fd: - free(raptor_data.fd_to_ef); - fail_fd_to_ef: - return ret; -} - -static void raptor_data_fini(void) -{ - close(raptor_data.ioctl_fd); - pthread_cond_destroy(&raptor_data.mgmt_cond); - pthread_mutex_destroy(&raptor_data.mgmt_lock); - pthread_rwlock_destroy(&raptor_data.flows_lock); - fqueue_destroy(raptor_data.fq); - fset_destroy(raptor_data.np1_flows); - bmp_destroy(raptor_data.eids); - free(raptor_data.fd_to_ef); - free(raptor_data.ef_to_fd); -} - -static int raptor_send_frame(struct shm_du_buff * sdb, - uint8_t deid) -{ - uint8_t * frame; - size_t frame_len; - uint8_t * payload; - size_t len; - - payload = shm_du_buff_head(sdb); - len = shm_du_buff_tail(sdb) - shm_du_buff_head(sdb); - - frame_len = RAPTOR_HEADER + len; - - if (frame_len >= RAPTOR_PAGE) { - log_err("Payload too large."); - return -1; - } - - frame = memalign(1 << 12, 1 << 12); - if (frame == NULL) { - log_err("frame == NULL"); - return -1; - } - - if ((uint64_t)frame & 0xFFF) { - log_err("page offset not zero"); - return -1; - } - - frame[0] = (frame_len & 0x00FF) >> 0; - frame[1] = (frame_len & 0xFF00) >> 8; - frame[2] = deid; - - memcpy(&frame[RAPTOR_HEADER], payload, len); - - if (ioctl(raptor_data.ioctl_fd, IOCTL_SEND | 1, &frame) != 1) { - log_err("Ioctl send failed."); - free(frame); - return -1; - } - - return 0; -} - -static int raptor_eid_alloc(uint8_t seid, - const uint8_t * hash, - qosspec_t qs) -{ - struct mgmt_msg * msg; - struct shm_du_buff * sdb; - - if (ipcp_sdb_reserve(&sdb, sizeof(*msg) + ipcp_dir_hash_len()) < 0) { - log_err("failed to reserve sdb for management frame."); - return -1; - } - - msg = (struct mgmt_msg *) shm_du_buff_head(sdb); - msg->code = FLOW_REQ; - msg->seid = seid; - msg->delay = hton32(qs.delay); - msg->bandwidth = hton64(qs.bandwidth); - msg->availability = qs.availability; - msg->loss = hton32(qs.loss); - msg->ber = hton32(qs.ber); - msg->in_order = qs.in_order; - msg->max_gap = hton32(qs.max_gap); - - memcpy(msg + 1, hash, ipcp_dir_hash_len()); - - if (raptor_send_frame(sdb, MGMT_EID)) { - log_err("Failed to send management frame."); - ipcp_sdb_release(sdb); - return -1; - } - - ipcp_sdb_release(sdb); - - return 0; -} - -static int raptor_eid_alloc_resp(uint8_t seid, - uint8_t deid, - int response) -{ - struct mgmt_msg * msg; - struct shm_du_buff * sdb; - - if (ipcp_sdb_reserve(&sdb, sizeof(*msg)) < 0) { - log_err("Failed to reserve sdb for management frame."); - return -1; - } - - msg = (struct mgmt_msg *) shm_du_buff_head(sdb); - msg->code = FLOW_REPLY; - msg->seid = seid; - msg->deid = deid; - msg->response = response; - - if (raptor_send_frame(sdb, MGMT_EID)) { - log_err("Failed to send management frame."); - ipcp_sdb_release(sdb); - return -1; - } - - ipcp_sdb_release(sdb); - - return 0; -} - -static int raptor_eid_req(uint8_t r_eid, - const uint8_t * dst, - qosspec_t qs) -{ - struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 1000}; - struct timespec abstime; - int fd; - - clock_gettime(PTHREAD_COND_CLOCK, &abstime); - - pthread_mutex_lock(&ipcpi.alloc_lock); - - while (ipcpi.alloc_id != -1 && ipcp_get_state() == IPCP_OPERATIONAL) { - ts_add(&abstime, &ts, &abstime); - pthread_cond_timedwait(&ipcpi.alloc_cond, - &ipcpi.alloc_lock, - &abstime); - } - - if (ipcp_get_state() != IPCP_OPERATIONAL) { - log_dbg("Won't allocate over non-operational IPCP."); - pthread_mutex_unlock(&ipcpi.alloc_lock); - return -1; - } - - /* reply to IRM, called under lock to prevent race */ - fd = ipcp_flow_req_arr(getpid(), dst, ipcp_dir_hash_len(), qs); - if (fd < 0) { - pthread_mutex_unlock(&ipcpi.alloc_lock); - log_err("Could not get new flow from IRMd."); - return -1; - } - - pthread_rwlock_wrlock(&raptor_data.flows_lock); - - raptor_data.fd_to_ef[fd].r_eid = r_eid; - - ipcpi.alloc_id = fd; - pthread_cond_broadcast(&ipcpi.alloc_cond); - - pthread_rwlock_unlock(&raptor_data.flows_lock); - pthread_mutex_unlock(&ipcpi.alloc_lock); - - log_dbg("New flow request, fd %d, remote EID %d.", fd, r_eid); - - return 0; -} - -static int raptor_eid_alloc_reply(uint8_t seid, - int deid, - int response) -{ - int ret = 0; - int fd = -1; - - pthread_rwlock_wrlock(&raptor_data.flows_lock); - - fd = raptor_data.ef_to_fd[deid]; - if (fd < 0) { - pthread_rwlock_unlock(& raptor_data.flows_lock); - log_err("No flow found with that EID."); - return -1; /* -EFLOWNOTFOUND */ - } - - if (response) - bmp_release(raptor_data.eids, raptor_data.fd_to_ef[fd].eid); - else - raptor_data.fd_to_ef[fd].r_eid = seid; - - pthread_rwlock_unlock(&raptor_data.flows_lock); - - log_dbg("Flow reply, fd %d, SEID %d, DEID %d.", fd, seid, deid); - - if ((ret = ipcp_flow_alloc_reply(fd, response)) < 0) - return -1; - - return ret; - -} - -static int raptor_name_query_req(const uint8_t * hash) -{ - struct mgmt_msg * msg; - struct shm_du_buff * sdb; - - if (!shim_data_reg_has(raptor_data.shim_data, hash)) - return 0; - - if (ipcp_sdb_reserve(&sdb, sizeof(*msg) + ipcp_dir_hash_len()) < 0) { - log_err("Failed to reserve sdb for management frame."); - return -1; - } - - msg = (struct mgmt_msg *) shm_du_buff_head(sdb); - msg->code = NAME_QUERY_REPLY; - - memcpy(msg + 1, hash, ipcp_dir_hash_len()); - - if (raptor_send_frame(sdb, MGMT_EID)) { - log_err("Failed to send management frame."); - ipcp_sdb_release(sdb); - return -1; - } - - ipcp_sdb_release(sdb); - - return 0; -} - -static int raptor_name_query_reply(const uint8_t * hash) -{ - shim_data_dir_add_entry(raptor_data.shim_data, hash, 0); - - shim_data_dir_query_respond(raptor_data.shim_data, hash); - - return 0; -} - -static int raptor_mgmt_frame(const uint8_t * buf, - size_t len) -{ - struct mgmt_msg * msg = (struct mgmt_msg *) buf; - uint8_t * hash = (uint8_t *) (msg + 1); - qosspec_t qs; - - switch (msg->code) { - case FLOW_REQ: - if (len != sizeof(*msg) + ipcp_dir_hash_len()) { - log_err("Corrupt message received."); - return -1; - } - - qs.delay = ntoh32(msg->delay); - qs.bandwidth = ntoh64(msg->bandwidth); - qs.availability = msg->availability; - qs.loss = ntoh32(msg->loss); - qs.ber = ntoh32(msg->ber); - qs.in_order = msg->in_order; - qs.max_gap = ntoh32(msg->max_gap); - - if (shim_data_reg_has(raptor_data.shim_data, hash)) - raptor_eid_req(msg->seid, hash, qs); - break; - case FLOW_REPLY: - if (len != sizeof(*msg)) { - log_err("Corrupt message received."); - return -1; - } - - raptor_eid_alloc_reply(msg->seid, msg->deid, msg->response); - break; - case NAME_QUERY_REQ: - if (len != sizeof(*msg) + ipcp_dir_hash_len()) { - log_err("Corrupt message received."); - return -1; - } - - raptor_name_query_req(hash); - break; - case NAME_QUERY_REPLY: - if (len != sizeof(*msg) + ipcp_dir_hash_len()) { - log_err("Corrupt message received."); - return -1; - } - - raptor_name_query_reply(hash); - break; - default: - log_err("Unknown message received %d.", msg->code); - return -1; - } - - return 0; -} - -static void * raptor_mgmt_handler(void * o) -{ - int ret; - struct timespec timeout = {(MGMT_TIMEOUT / 1000), - (MGMT_TIMEOUT % 1000) * MILLION}; - struct timespec abstime; - struct mgmt_frame * frame; - - (void) o; - - while (true) { - ret = 0; - - if (ipcp_get_state() != IPCP_OPERATIONAL) - break; - - clock_gettime(PTHREAD_COND_CLOCK, &abstime); - ts_add(&abstime, &timeout, &abstime); - - pthread_mutex_lock(&raptor_data.mgmt_lock); - - while (list_is_empty(&raptor_data.mgmt_frames) && - ret != -ETIMEDOUT) - ret = -pthread_cond_timedwait(&raptor_data.mgmt_cond, - &raptor_data.mgmt_lock, - &abstime); - - if (ret == -ETIMEDOUT) { - pthread_mutex_unlock(&raptor_data.mgmt_lock); - continue; - } - - frame = list_first_entry((&raptor_data.mgmt_frames), - struct mgmt_frame, next); - if (frame == NULL) { - pthread_mutex_unlock(&raptor_data.mgmt_lock); - continue; - } - - list_del(&frame->next); - pthread_mutex_unlock(&raptor_data.mgmt_lock); - - raptor_mgmt_frame(frame->buf, frame->len); - free(frame); - } - - return NULL; -} - -static void raptor_recv_frame(uint8_t * frame) -{ - uint8_t deid; - uint8_t * payload; - size_t frame_len; - size_t length; - int fd; - struct mgmt_frame * mgmt_frame; - struct shm_du_buff * sdb; - size_t idx; - - sdb = (struct shm_du_buff *)((uint64_t) frame & RAPTOR_PAGE_MASK); - idx = shm_du_buff_get_idx(sdb); - - frame_len = frame[0] | (frame[1] << 8); - if (frame_len < RAPTOR_HEADER) { - log_err("Received packet smaller than header alone."); - ipcp_sdb_release(sdb); - return; - } - - if (frame_len >= RAPTOR_PAGE) { - log_err("Received packet too large."); - ipcp_sdb_release(sdb); - return; - } - - deid = frame[2]; - payload = &frame[RAPTOR_HEADER]; - length = frame_len - RAPTOR_HEADER; - - shm_du_buff_head_release(sdb, RAPTOR_HEADER); - shm_du_buff_tail_release(sdb, RAPTOR_PAGE - frame_len); - - if (deid == MGMT_EID) { - pthread_mutex_lock(&raptor_data.mgmt_lock); - - mgmt_frame = malloc(sizeof(*mgmt_frame)); - if (mgmt_frame == NULL) { - pthread_mutex_unlock(&raptor_data.mgmt_lock); - ipcp_sdb_release(sdb); - return; - } - - memcpy(mgmt_frame->buf, payload, length); - mgmt_frame->len = length; - list_add(&mgmt_frame->next, &raptor_data.mgmt_frames); - pthread_cond_signal(&raptor_data.mgmt_cond); - pthread_mutex_unlock(&raptor_data.mgmt_lock); - - ipcp_sdb_release(sdb); - } else { - pthread_rwlock_rdlock(&raptor_data.flows_lock); - - fd = raptor_data.ef_to_fd[deid]; - if (fd < 0) { - pthread_rwlock_unlock(&raptor_data.flows_lock); - ipcp_sdb_release(sdb); - return; - } - - pthread_rwlock_unlock(&raptor_data.flows_lock); - - local_flow_write(fd, idx); - } -} - -static void * raptor_recv_done_thread(void * o) -{ - uint8_t * frames[RAPTOR_BATCH]; - int count; - int i; - - (void) o; - - while (true) { - if (ipcp_get_state() != IPCP_OPERATIONAL) - break; - - count = ioctl(raptor_data.ioctl_fd, - IOCTL_RECV_DONE | RAPTOR_BATCH, frames); - - if (count <= 0) - continue; - - for (i = 0; i < count; i++) - raptor_recv_frame(frames[i]); - } - - return NULL; -} - -static void * raptor_send_thread(void * o) -{ - struct timespec timeout = {0, EVENT_WAIT_TIMEOUT * 1000}; - int fd; - struct shm_du_buff * sdb; - uint8_t deid; - - (void) o; - - while (fevent(raptor_data.np1_flows, raptor_data.fq, &timeout)) { - if (ipcp_get_state() != IPCP_OPERATIONAL) - break; - - pthread_rwlock_rdlock(&raptor_data.flows_lock); - while ((fd = fqueue_next(raptor_data.fq)) >= 0) { - if (ipcp_flow_read(fd, &sdb)) { - log_err("Bad read from fd %d.", fd); - continue; - } - - deid = raptor_data.fd_to_ef[fd].r_eid; - - raptor_send_frame(sdb, deid); - } - pthread_rwlock_unlock(&raptor_data.flows_lock); - } - - return NULL; -} - -static void * raptor_send_done_thread(void * o) -{ - uint8_t * frames[RAPTOR_BATCH]; - int count; - int i; - - (void) o; - - while (true) { - if (ipcp_get_state() != IPCP_OPERATIONAL) - break; - - count = ioctl(raptor_data.ioctl_fd, - IOCTL_SEND_DONE | RAPTOR_BATCH, frames); - - if (count <= 0) - continue; - - for (i = 0; i < count; i++) - free(frames[i]); - } - - return NULL; -} - -static void * raptor_recv_thread(void * o) -{ - struct shm_du_buff * sdb; - uint8_t * frames[RAPTOR_BATCH]; - uint8_t ** head; - int needed = 0; - int count; - int i; - - (void) o; - - while (true) { - if (ipcp_get_state() != IPCP_OPERATIONAL) - break; - - needed = ioctl(raptor_data.ioctl_fd, - IOCTL_RECV_NEED | RAPTOR_BATCH, NULL); - - if (needed <= 0) - continue; - - for (i = 0; i < needed; i++) { - if (ipcp_sdb_reserve(&sdb, RAPTOR_PAGE) < 0) { - log_err("Recv thread: reserve sdb failed."); - return NULL; - } - - if ((uint64_t)sdb & (~RAPTOR_PAGE_MASK)) { - log_err("Recv thread: sdb not at offset 0."); - return NULL; - } - - frames[i] = shm_du_buff_head(sdb); - - if ((uint64_t)frames[i] & 0x7) { - log_err("Recv thread: frame not aligned."); - return NULL; - } - } - - head = frames; - - do { - count = ioctl(raptor_data.ioctl_fd, - IOCTL_RECV | needed, head); - if (count <= 0) - continue; - - assert(count <= needed); - - needed -= count; - head += count; - - } while (needed > 0 && ipcp_get_state() == IPCP_OPERATIONAL); - } - - return NULL; -} - -static int raptor_bootstrap(const struct ipcp_config * conf) -{ - assert(conf); - assert(conf->type == THIS_TYPE); - - (void) conf; - - raptor_data.ioctl_fd = open("/dev/raptor", 0); - if (raptor_data.ioctl_fd < 0) { - log_err("Failed to open /dev/raptor."); - goto fail_ioctl; - } - - ipcp_set_state(IPCP_OPERATIONAL); - - if (pthread_create(&raptor_data.mgmt_handler, - NULL, - raptor_mgmt_handler, - NULL)) { - ipcp_set_state(IPCP_INIT); - goto fail_mgmt_handler; - } - - if (pthread_create(&raptor_data.send_thread, - NULL, - raptor_send_thread, - NULL)) { - ipcp_set_state(IPCP_INIT); - goto fail_send_thread; - } - - if (pthread_create(&raptor_data.recv_thread, - NULL, - raptor_recv_thread, - NULL)) { - ipcp_set_state(IPCP_INIT); - goto fail_recv_thread; - } - - if (pthread_create(&raptor_data.send_done_thread, - NULL, - raptor_send_done_thread, - NULL)) { - ipcp_set_state(IPCP_INIT); - goto fail_send_done_thread; - } - - if (pthread_create(&raptor_data.recv_done_thread, - NULL, - raptor_recv_done_thread, - NULL)) { - ipcp_set_state(IPCP_INIT); - goto fail_recv_done_thread; - } - - log_dbg("Bootstrapped raptor IPCP with api %d.", getpid()); - - return 0; - - fail_recv_done_thread: - pthread_join(raptor_data.send_done_thread, NULL); - fail_send_done_thread: - pthread_join(raptor_data.recv_thread, NULL); - fail_recv_thread: - pthread_join(raptor_data.send_thread, NULL); - fail_send_thread: - pthread_join(raptor_data.mgmt_handler, NULL); - fail_mgmt_handler: - close(raptor_data.ioctl_fd); - fail_ioctl: - return -1; -} - -static int raptor_reg(const uint8_t * hash) -{ - uint8_t * hash_dup; - - hash_dup = ipcp_hash_dup(hash); - if (hash_dup == NULL) { - log_err("Failed to duplicate hash."); - return -ENOMEM; - } - - if (shim_data_reg_add_entry(raptor_data.shim_data, hash_dup)) { - log_err("Failed to add " HASH_FMT " to local registry.", - HASH_VAL(hash)); - free(hash_dup); - return -1; - } - - log_dbg("Registered " HASH_FMT ".", HASH_VAL(hash)); - - return 0; -} - -static int raptor_unreg(const uint8_t * hash) -{ - shim_data_reg_del_entry(raptor_data.shim_data, hash); - - return 0; -} - -static int raptor_query(const uint8_t * hash) -{ - struct timespec timeout = {(NAME_QUERY_TIMEOUT / 1000), - (NAME_QUERY_TIMEOUT % 1000) * MILLION}; - struct mgmt_msg * msg; - struct dir_query * query; - int ret; - struct shm_du_buff * sdb; - - if (shim_data_dir_has(raptor_data.shim_data, hash)) - return 0; - - if (ipcp_sdb_reserve(&sdb, sizeof(*msg) + ipcp_dir_hash_len()) < 0) { - log_err("failed to reserve sdb for management frame."); - return -1; - } - - msg = (struct mgmt_msg *) shm_du_buff_head(sdb); - msg->code = NAME_QUERY_REQ; - - memcpy(msg + 1, hash, ipcp_dir_hash_len()); - - query = shim_data_dir_query_create(raptor_data.shim_data, hash); - if (query == NULL) { - ipcp_sdb_release(sdb); - return -1; - } - - if (raptor_send_frame(sdb, MGMT_EID)) { - log_err("Failed to send management frame."); - ipcp_sdb_release(sdb); - return -1; - } - - ret = shim_data_dir_query_wait(query, &timeout); - - shim_data_dir_query_destroy(raptor_data.shim_data, query); - - return ret; -} - -static int raptor_flow_alloc(int fd, - const uint8_t * hash, - qosspec_t qs) -{ - uint8_t seid = 0; - - log_dbg("Allocating flow to " HASH_FMT ".", HASH_VAL(hash)); - - assert(hash); - - if (!shim_data_dir_has(raptor_data.shim_data, hash)) { - log_err("Destination unreachable."); - return -1; - } - - pthread_rwlock_wrlock(&raptor_data.flows_lock); - - seid = bmp_allocate(raptor_data.eids); - if (!bmp_is_id_valid(raptor_data.eids, seid)) { - pthread_rwlock_unlock(&raptor_data.flows_lock); - return -1; - } - - raptor_data.fd_to_ef[fd].eid = seid; - raptor_data.ef_to_fd[seid] = fd; - - pthread_rwlock_unlock(&raptor_data.flows_lock); - - if (raptor_eid_alloc(seid, hash, qs) < 0) { - pthread_rwlock_wrlock(&raptor_data.flows_lock); - bmp_release(raptor_data.eids, raptor_data.fd_to_ef[fd].eid); - raptor_data.fd_to_ef[fd].eid = -1; - raptor_data.ef_to_fd[seid] = -1; - pthread_rwlock_unlock(&raptor_data.flows_lock); - return -1; - } - - fset_add(raptor_data.np1_flows, fd); - - log_dbg("Pending flow with fd %d on EID %d.", fd, seid); - - return 0; -} - -static int raptor_flow_alloc_resp(int fd, - int response) -{ - struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 1000}; - struct timespec abstime; - uint8_t seid = 0; - uint8_t r_eid = 0; - - clock_gettime(PTHREAD_COND_CLOCK, &abstime); - - pthread_mutex_lock(&ipcpi.alloc_lock); - - while (ipcpi.alloc_id != fd && ipcp_get_state() == IPCP_OPERATIONAL) { - ts_add(&abstime, &ts, &abstime); - pthread_cond_timedwait(&ipcpi.alloc_cond, - &ipcpi.alloc_lock, - &abstime); - } - - if (ipcp_get_state() != IPCP_OPERATIONAL) { - pthread_mutex_unlock(&ipcpi.alloc_lock); - return -1; - } - - ipcpi.alloc_id = -1; - pthread_cond_broadcast(&ipcpi.alloc_cond); - - pthread_mutex_unlock(&ipcpi.alloc_lock); - - pthread_rwlock_wrlock(&raptor_data.flows_lock); - - seid = bmp_allocate(raptor_data.eids); - if (!bmp_is_id_valid(raptor_data.eids, seid)) { - pthread_rwlock_unlock(&raptor_data.flows_lock); - return -1; - } - - raptor_data.fd_to_ef[fd].eid = seid; - r_eid = raptor_data.fd_to_ef[fd].r_eid; - raptor_data.ef_to_fd[seid] = fd; - - pthread_rwlock_unlock(&raptor_data.flows_lock); - - if (raptor_eid_alloc_resp(seid, r_eid, response) < 0) { - pthread_rwlock_wrlock(&raptor_data.flows_lock); - bmp_release(raptor_data.eids, raptor_data.fd_to_ef[fd].eid); - pthread_rwlock_unlock(&raptor_data.flows_lock); - return -1; - } - - fset_add(raptor_data.np1_flows, fd); - - log_dbg("Accepted flow, fd %d, EID %d.", fd, (uint8_t)seid); - - return 0; -} - -static int raptor_flow_dealloc(int fd) -{ - uint8_t eid; - - ipcp_flow_fini(fd); - - pthread_rwlock_wrlock(&raptor_data.flows_lock); - - fset_del(raptor_data.np1_flows, fd); - - eid = raptor_data.fd_to_ef[fd].eid; - bmp_release(raptor_data.eids, eid); - raptor_data.fd_to_ef[fd].eid = -1; - raptor_data.fd_to_ef[fd].r_eid = -1; - - raptor_data.ef_to_fd[eid] = -1; - - pthread_rwlock_unlock(&raptor_data.flows_lock); - - flow_dealloc(fd); - - log_dbg("Flow with fd %d deallocated.", fd); - - return 0; -} - -static struct ipcp_ops raptor_ops = { - .ipcp_bootstrap = raptor_bootstrap, - .ipcp_enroll = NULL, - .ipcp_reg = raptor_reg, - .ipcp_unreg = raptor_unreg, - .ipcp_query = raptor_query, - .ipcp_flow_alloc = raptor_flow_alloc, - .ipcp_flow_join = NULL, - .ipcp_flow_alloc_resp = raptor_flow_alloc_resp, - .ipcp_flow_dealloc = raptor_flow_dealloc -}; - -int main(int argc, - char * argv[]) -{ - if (ipcp_init(argc, argv, &raptor_ops) < 0) { - log_err("Failed to init IPCP."); - goto fail_init; - } - - if (raptor_data_init() < 0) { - log_err("Failed to init shim-eth-llc data."); - goto fail_data_init; - } - - if (ipcp_boot() < 0) { - log_err("Failed to boot IPCP."); - goto fail_boot; - } - - if (ipcp_create_r(getpid(), 0)) { - log_err("Failed to notify IRMd we are initialized."); - ipcp_set_state(IPCP_NULL); - goto fail_create_r; - } - - log_info("Raptor created."); - - ipcp_shutdown(); - - if (ipcp_get_state() == IPCP_SHUTDOWN) { - pthread_join(raptor_data.send_thread, NULL); - pthread_join(raptor_data.recv_thread, NULL); - pthread_join(raptor_data.send_done_thread, NULL); - pthread_join(raptor_data.recv_done_thread, NULL); - pthread_join(raptor_data.mgmt_handler, NULL); - } - - raptor_data_fini(); - - ipcp_fini(); - - exit(EXIT_SUCCESS); - - fail_create_r: - ipcp_shutdown(); - fail_boot: - raptor_data_fini(); - fail_data_init: - ipcp_fini(); - fail_init: - ipcp_create_r(getpid(), -1); - exit(EXIT_FAILURE); -} |