diff options
Diffstat (limited to 'src/ipcpd/normal')
39 files changed, 2237 insertions, 898 deletions
diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index f2e48cbc..06292c50 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -14,33 +14,37 @@ include_directories(${CMAKE_BINARY_DIR}/include)  set(IPCP_NORMAL_TARGET ipcpd-normal CACHE STRING "IPCP_NORMAL_TARGET") -protobuf_generate_c(FLOW_ALLOC_SRCS FLOW_ALLOC_HDRS -  flow_alloc.proto) +protobuf_generate_c(FLOW_ALLOC_SRCS FLOW_ALLOC_HDRS flow_alloc.proto) +protobuf_generate_c(FSO_SRCS FSO_HDRS fso.proto)  set(SOURCE_FILES    # Add source files here    addr_auth.c +  connmgr.c    dir.c    enroll.c    fmgr.c    frct.c    gam.c +  graph.c    main.c +  neighbors.c    pff.c    ribmgr.c +  routing.c    shm_pci.c    # Add policies last    pol/complete.c    pol/flat.c    ) -add_executable (ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES} -  ${FLOW_ALLOC_SRCS}) -target_link_libraries (ipcpd-normal LINK_PUBLIC ouroboros) +add_executable(ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES} +  ${FLOW_ALLOC_SRCS} ${FSO_SRCS}) +target_link_libraries(ipcpd-normal LINK_PUBLIC ouroboros) -include(MacroAddCompileFlags) +include(AddCompileFlags)  if (CMAKE_BUILD_TYPE MATCHES Debug) -  macro_add_compile_flags(ipcpd-normal -DCONFIG_OUROBOROS_DEBUG) +  add_compile_flags(ipcpd-normal -DCONFIG_OUROBOROS_DEBUG)  endif (CMAKE_BUILD_TYPE MATCHES Debug)  install(TARGETS ipcpd-normal RUNTIME DESTINATION sbin) diff --git a/src/ipcpd/normal/addr_auth.c b/src/ipcpd/normal/addr_auth.c index 210744af..5b3c6170 100644 --- a/src/ipcpd/normal/addr_auth.c +++ b/src/ipcpd/normal/addr_auth.c @@ -3,7 +3,8 @@   *   * Address authority   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -25,47 +26,36 @@  #include <ouroboros/logs.h>  #include "addr_auth.h" +#include "pol-addr-auth-ops.h"  #include "pol/flat.h"  #include <stdlib.h>  #include <assert.h> -struct addr_auth * addr_auth_create(enum pol_addr_auth type) -{ -        struct addr_auth * tmp; - -        tmp = malloc(sizeof(*tmp)); -        if (tmp == NULL) { -                log_err("Failed to malloc addr auth."); -                return NULL; -        } +struct addr_auth { +        struct pol_addr_auth_ops * ops; +} addr_auth; +int addr_auth_init(enum pol_addr_auth type) +{          switch (type) {          case FLAT_RANDOM: -                tmp->address = flat_address; -                tmp->type = type; +                addr_auth.ops = &flat_ops;                  break;          default:                  log_err("Unknown address authority type."); -                free(tmp); -                return NULL; +                return -1;          } -        return tmp; +        return addr_auth.ops->init();  } -int addr_auth_destroy(struct addr_auth * instance) +uint64_t addr_auth_address(void)  { -        assert(instance); - -        switch (instance->type) { -        case FLAT_RANDOM: -                break; -        default: -                log_err("Unknown address authority type."); -        } - -        free(instance); +        return addr_auth.ops->address(); +} -        return 0; +int addr_auth_fini(void) +{ +        return addr_auth.ops->fini();  } diff --git a/src/ipcpd/normal/addr_auth.h b/src/ipcpd/normal/addr_auth.h index 8d67bc66..fbe7d790 100644 --- a/src/ipcpd/normal/addr_auth.h +++ b/src/ipcpd/normal/addr_auth.h @@ -3,7 +3,8 @@   *   * Address authority   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -26,13 +27,10 @@  #include <stdint.h> -struct addr_auth { -        enum pol_addr_auth type; -        uint64_t (* address)(void); -}; +int      addr_auth_init(enum pol_addr_auth type); -struct addr_auth * addr_auth_create(enum pol_addr_auth type); +int      addr_auth_fini(void); -int                addr_auth_destroy(struct addr_auth * instance); +uint64_t addr_auth_address(void);  #endif /* OUROBOROS_IPCPD_NORMAL_ADDR_AUTH_H */ diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h index 882625dd..aafef625 100644 --- a/src/ipcpd/normal/ae.h +++ b/src/ipcpd/normal/ae.h @@ -3,8 +3,8 @@   *   * Application Entities for the normal IPC process   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c new file mode 100644 index 00000000..b97d2b23 --- /dev/null +++ b/src/ipcpd/normal/connmgr.c @@ -0,0 +1,358 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Handles AE connections + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#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 "ae.h" +#include "connmgr.h" +#include "enroll.h" +#include "fmgr.h" +#include "frct.h" +#include "ipcp.h" +#include "ribmgr.h" + +#include <pthread.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +struct ae_conn { +        struct list_head next; +        struct conn      conn; +}; + +struct ae { +        struct list_head next; +        struct conn_info info; + +        struct list_head conn_list; +        pthread_cond_t   conn_cond; +        pthread_mutex_t  conn_lock; +}; + +struct { +        pthread_t        acceptor; + +        struct list_head aes; +        pthread_mutex_t  aes_lock; +} connmgr; + +static int add_ae_conn(struct ae *        ae, +                       int                fd, +                       qosspec_t          qs, +                       struct conn_info * rcv_info) +{ +        struct ae_conn * ae_conn = NULL; + +        ae_conn = malloc(sizeof(*ae_conn)); +        if (ae_conn == 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); + +        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; +} + +static struct ae * find_ae_by_name(char * name) +{ +        struct list_head * p = NULL; + +        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; +} + +static void * flow_acceptor(void * o) +{ +        int               fd; +        qosspec_t         qs; +        struct conn_info  rcv_info; +        struct conn_info  fail_info; +        struct ae *       ae = NULL; + +        (void) o; + +        memset(&fail_info, 0, sizeof(fail_info)); + +        while (true) { +                pthread_rwlock_rdlock(&ipcpi.state_lock); + +                if (ipcp_get_state() != IPCP_OPERATIONAL) { +                        pthread_rwlock_unlock(&ipcpi.state_lock); +                        log_info("Shutting down flow acceptor."); +                        return 0; +                } + +                pthread_rwlock_unlock(&ipcpi.state_lock); + +                fd = flow_accept(&qs); +                if (fd < 0) { +                        if (fd != -EIRMD) +                                log_warn("Flow accept failed: %d", fd); +                        continue; +                } + +                if (flow_alloc_resp(fd, 0)) { +                        log_err("Failed to respond to flow alloc request."); +                        continue; +                } + +                if (cacep_rcv(fd, &rcv_info)) { +                        log_err("Error establishing application connection."); +                        flow_dealloc(fd); +                        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 { +                        cacep_snd(fd, &fail_info); +                        flow_dealloc(fd); +                } +        } + +        return (void *) 0; +} + +int connmgr_init(void) +{ +        list_head_init(&connmgr.aes); + +        if (pthread_mutex_init(&connmgr.aes_lock, NULL)) +                return -1; + +        return 0; +} + +int connmgr_start(void) +{ +        pthread_create(&connmgr.acceptor, NULL, flow_acceptor, NULL); + +        return 0; +} + +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; + +        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); + +        pthread_cond_destroy(&ae->conn_cond); +        pthread_mutex_destroy(&ae->conn_lock); + +        free(ae); +} + +void connmgr_fini(void) +{ +        struct list_head * p = NULL; +        struct list_head * n = NULL; + +        pthread_mutex_lock(&connmgr.aes_lock); + +        list_for_each_safe(p, n, &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_mutex_destroy(&connmgr.aes_lock); +} + +struct ae * connmgr_ae_create(struct conn_info info) +{ +        struct ae * ae; + +        ae = malloc(sizeof(*ae)); +        if (ae == NULL) +                return NULL; + +        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_cond_init(&ae->conn_cond, NULL)) { +                pthread_mutex_destroy(&ae->conn_lock); +                free(ae); +                return NULL; +        } + +        pthread_mutex_lock(&connmgr.aes_lock); +        list_add(&ae->next, &connmgr.aes); +        pthread_mutex_unlock(&connmgr.aes_lock); + +        return ae; +} + +void connmgr_ae_destroy(struct ae * ae) +{ +        assert(ae); + +        pthread_mutex_lock(&connmgr.aes_lock); + +        list_del(&ae->next); + +        destroy_ae(ae); + +        pthread_mutex_unlock(&connmgr.aes_lock); +} + +int connmgr_alloc(struct ae *   ae, +                  char *        dst_name, +                  qosspec_t *   qs, +                  struct conn * conn) +{ +        assert(ae); +        assert(dst_name); +        assert(conn); + +        memset(&conn->conn_info, 0, sizeof(conn->conn_info)); + +        conn->flow_info.fd = flow_alloc(dst_name, qs); +        if (conn->flow_info.fd < 0) { +                log_err("Failed to allocate flow to %s.", dst_name); +                return -1; +        } + +        if (qs != NULL) +                conn->flow_info.qs = *qs; +        else +                memset(&conn->flow_info.qs, 0, sizeof(conn->flow_info.qs)); + +        if (flow_alloc_res(conn->flow_info.fd)) { +                log_err("Flow allocation to %s failed.", dst_name); +                flow_dealloc(conn->flow_info.fd); +                return -1; +        } + +        if (cacep_snd(conn->flow_info.fd, &ae->info)) { +                log_err("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."); +                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) { +                flow_dealloc(conn->flow_info.fd); +                return -1; +        } + +        return 0; +} + +int connmgr_wait(struct ae *   ae, +                 struct conn * conn) +{ +        struct ae_conn * ae_conn; + +        assert(ae); +        assert(conn); + +        pthread_mutex_lock(&ae->conn_lock); + +        pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock, +                             (void *) &ae->conn_lock); + +        while (list_is_empty(&ae->conn_list)) +                pthread_cond_wait(&ae->conn_cond, &ae->conn_lock); + +        ae_conn = list_first_entry((&ae->conn_list), struct ae_conn, next); +        if (ae_conn == NULL) { +                pthread_mutex_unlock(&ae->conn_lock); +                return -1; +        } + +        *conn = ae_conn->conn; + +        list_del(&ae_conn->next); +        free(ae_conn); + +        pthread_cleanup_pop(true); + +        return 0; +} diff --git a/src/ipcpd/normal/connmgr.h b/src/ipcpd/normal/connmgr.h new file mode 100644 index 00000000..c0356f6d --- /dev/null +++ b/src/ipcpd/normal/connmgr.h @@ -0,0 +1,57 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Handles the different AP connections + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_CONNMGR_H +#define OUROBOROS_IPCPD_NORMAL_CONNMGR_H + +#include <ouroboros/cacep.h> +#include <ouroboros/qos.h> + +struct conn { +        struct conn_info conn_info; +        struct flow_info { +                int              fd; +                qosspec_t        qs; +        } flow_info; +}; + +int         connmgr_init(void); + +void        connmgr_fini(void); + +int         connmgr_start(void); + +void        connmgr_stop(void); + +struct ae * connmgr_ae_create(struct conn_info info); + +void        connmgr_ae_destroy(struct ae * ae); + +int         connmgr_alloc(struct ae *   ae, +                          char *        dst_name, +                          qosspec_t *   qs, +                          struct conn * conn); + +int         connmgr_wait(struct ae *   ae, +                         struct conn * conn); + +#endif /* OUROBOROS_IPCPD_NORMAL_CONNMGR_H */ diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index 55d6e3f6..ae9793c6 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -3,8 +3,8 @@   *   * DIF directory   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 diff --git a/src/ipcpd/normal/dir.h b/src/ipcpd/normal/dir.h index 925fc823..04e722f3 100644 --- a/src/ipcpd/normal/dir.h +++ b/src/ipcpd/normal/dir.h @@ -3,7 +3,8 @@   *   * DIF directory   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 diff --git a/src/ipcpd/normal/dt_const.h b/src/ipcpd/normal/dt_const.h index c94e9395..327f51b8 100644 --- a/src/ipcpd/normal/dt_const.h +++ b/src/ipcpd/normal/dt_const.h @@ -3,8 +3,8 @@   *   * Data Transfer Constants for the IPCP   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index bc5d2a20..7e15be11 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -3,7 +3,8 @@   *   * Enrollment Task   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> + *    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 @@ -22,27 +23,37 @@  #include <ouroboros/config.h>  #include <ouroboros/endian.h> -#include <ouroboros/time_utils.h> +#include <ouroboros/errno.h>  #include <ouroboros/cdap.h> +#include <ouroboros/time_utils.h>  #include <ouroboros/dev.h>  #include <ouroboros/logs.h>  #include <ouroboros/rib.h> +#include <ouroboros/errno.h>  #include "ae.h" +#include "connmgr.h"  #include "ribconfig.h"  #include <assert.h>  #include <stdlib.h>  #include <string.h> +#include <pthread.h>  /* Symbolic, will return current time */  #define TIME_NAME               "localtime"  #define TIME_PATH               DLR TIME_NAME  #define ENROLL_WARN_TIME_OFFSET 20 -int enroll_handle(int fd) +struct { +        struct ae * ae; +        pthread_t   listener; +} enroll; + +static void * enroll_handle(void * o)  { -        struct cdap *    ci; +        struct cdap *    cdap; +        struct conn      conn;          cdap_key_t       key;          enum cdap_opcode oc;          char *           name; @@ -59,103 +70,105 @@ int enroll_handle(int fd)          char * members_ro = MEMBERS_PATH;          char * dif_ro     = DIF_PATH; -        if (flow_alloc_resp(fd, 0) < 0) { -                flow_dealloc(fd); -                log_err("Could not respond to request."); -                return -1; -        } - -        ci = cdap_create(fd); -        if (ci == NULL) { -                flow_dealloc(fd); -                log_err("Failed to create CDAP instance."); -                return -1; -        } - -        while (!(boot_r && members_r && dif_name_r)) { -                key = cdap_request_wait(ci, &oc, &name, &data, -                                        (size_t *) &len , &flags); -                assert(key >= 0); -                assert(name); +        (void) o; -                if (data != NULL) { -                        free(data); -                        log_warn("Received data with enrollment request."); +        while (true) { +                cdap = cdap_create(); +                if (cdap == NULL) { +                        log_err("Failed to instantiate CDAP."); +                        continue;                  } -                if (oc != CDAP_READ) { -                        log_warn("Invalid request."); -                        cdap_reply_send(ci, key, -1, NULL, 0); -                        cdap_destroy(ci); -                        flow_dealloc(fd); -                        free(name); -                        return -1; +                if (connmgr_wait(enroll.ae, &conn)) { +                        log_err("Failed to get next connection."); +                        cdap_destroy(cdap); +                        continue;                  } -                if (strcmp(name, boot_ro) == 0) { -                        boot_r = true; -                } else if (strcmp(name, members_ro) == 0) { -                        members_r = true; -                } else if (strcmp(name, dif_ro) == 0) { -                        dif_name_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(ci, key, 0, buf, sizeof(buf)); -                        free(name); +                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);                          continue; -                } else { -                        log_warn("Illegal read: %s.", name); -                        cdap_reply_send(ci, key, -1, NULL, 0); -                        cdap_destroy(ci); -                        flow_dealloc(fd); -                        free(name); -                        return -1;                  } -                len = rib_pack(name, &buf, PACK_HASH_ROOT); -                if (len < 0) { -                        log_err("Failed to pack %s.", name); -                        cdap_reply_send(ci, key, -1, NULL, 0); -                        cdap_destroy(ci); -                        flow_dealloc(fd); -                        free(name); -                        return -1; -                } +                while (!(boot_r && members_r && dif_name_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, dif_ro) == 0) { +                                dif_name_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); -                log_dbg("Packed %s (%zu bytes).", name, len); +                        free(name); -                free(name); +                        if (cdap_reply_send(cdap, key, 0, buf, len)) { +                                log_err("Failed to send CDAP reply."); +                                free(buf); +                                continue; +                        } -                if (cdap_reply_send(ci, key, 0, buf, len)) { -                        log_err("Failed to send CDAP reply."); -                        cdap_destroy(ci); -                        flow_dealloc(fd); -                        return -1; +                        free(buf);                  } -                free(buf); -        } +                log_dbg("Sent boot info to new member."); -        log_dbg("Sent boot info to new member."); - -        cdap_destroy(ci); - -        flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd); +        }          return 0;  }  int enroll_boot(char * dst_name)  { -        struct cdap * ci; -        cdap_key_t    key; +        struct cdap * cdap; +        cdap_key_t *  key;          uint8_t *     data;          size_t        len; -        int           fd; +        struct conn   conn;          struct timespec t0;          struct timespec rtt; @@ -166,22 +179,22 @@ int enroll_boot(char * dst_name)          char * members_ro = MEMBERS_PATH;          char * dif_ro     = DIF_PATH; -        fd = flow_alloc(dst_name, ENROLL_AE, NULL); -        if (fd < 0) { -                log_err("Failed to allocate flow."); +        cdap = cdap_create(); +        if (cdap == NULL) { +                log_err("Failed to instantiate CDAP.");                  return -1;          } -        if (flow_alloc_res(fd)) { -                log_err("Flow allocation failed."); -                flow_dealloc(fd); +        if (connmgr_alloc(enroll.ae, dst_name, NULL, &conn)) { +                log_err("Failed to get connection."); +                cdap_destroy(cdap);                  return -1;          } -        ci = cdap_create(fd); -        if (ci == NULL) { -                log_err("Failed to create CDAP instance."); -                flow_dealloc(fd); +        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;          } @@ -189,26 +202,29 @@ int enroll_boot(char * dst_name)          clock_gettime(CLOCK_REALTIME, &t0); -        key = cdap_request_send(ci, CDAP_READ, TIME_PATH, NULL, 0, 0); -        if (key < 0) { +        key = cdap_request_send(cdap, CDAP_READ, TIME_PATH, NULL, 0, 0); +        if (key == NULL) {                  log_err("Failed to send CDAP request."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } -        if (cdap_reply_wait(ci, key, &data, &len)) { +        if (cdap_reply_wait(cdap, key[0], &data, &len)) {                  log_err("Failed to get CDAP reply."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                free(key); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } +        free(key); +          clock_gettime(CLOCK_REALTIME, &rtt);          delta_t = ts_diff_ms(&t0, &rtt); -        assert (len == 2 * sizeof (uint64_t)); +        assert(len == 2 * sizeof (uint64_t));          rtt.tv_sec  = ntoh64(((uint64_t *) data)[0]);          rtt.tv_nsec = ntoh64(((uint64_t *) data)[1]); @@ -218,93 +234,138 @@ int enroll_boot(char * dst_name)          free(data); -        key = cdap_request_send(ci, CDAP_READ, boot_ro, NULL, 0, 0); -        if (key < 0) { +        key = cdap_request_send(cdap, CDAP_READ, boot_ro, NULL, 0, 0); +        if (key == NULL) {                  log_err("Failed to send CDAP request."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } -        if (cdap_reply_wait(ci, key, &data, &len)) { +        if (cdap_reply_wait(cdap, key[0], &data, &len)) {                  log_err("Failed to get CDAP reply."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                free(key); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } +        free(key); +          log_dbg("Packed information received (%zu bytes).", len);          if (rib_unpack(data, len, UNPACK_CREATE)) {                  log_warn("Error unpacking RIB data.");                  rib_del(boot_ro);                  free(data); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          }          log_dbg("Packed information inserted into RIB."); -        key = cdap_request_send(ci, CDAP_READ, members_ro, NULL, 0, 0); -        if (key < 0) { +        key = cdap_request_send(cdap, CDAP_READ, members_ro, NULL, 0, 0); +        if (key == NULL) {                  log_err("Failed to send CDAP request."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } -        if (cdap_reply_wait(ci, key, &data, &len)) { +        if (cdap_reply_wait(cdap, key[0], &data, &len)) {                  log_err("Failed to get CDAP reply."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                free(key); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } +        free(key); +          log_dbg("Packed information received (%zu bytes).", len);          if (rib_unpack(data, len, UNPACK_CREATE)) {                  log_warn("Error unpacking RIB data.");                  rib_del(boot_ro);                  free(data); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          }          log_dbg("Packed information inserted into RIB."); -        key = cdap_request_send(ci, CDAP_READ, dif_ro, NULL, 0, 0); -        if (key < 0) { +        key = cdap_request_send(cdap, CDAP_READ, dif_ro, NULL, 0, 0); +        if (key == NULL) {                  log_err("Failed to send CDAP request."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } -        if (cdap_reply_wait(ci, key, &data, &len)) { +        if (cdap_reply_wait(cdap, key[0], &data, &len)) {                  log_err("Failed to get CDAP reply."); -                cdap_destroy(ci); -                flow_dealloc(fd); +                free(key); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          } +        free(key); +          log_dbg("Packed information received (%zu bytes).", len);          if (rib_unpack(data, len, UNPACK_CREATE)) {                  log_warn("Error unpacking RIB data.");                  rib_del(boot_ro);                  free(data); -                cdap_destroy(ci); -                flow_dealloc(fd); +                cdap_destroy(cdap); +                flow_dealloc(conn.flow_info.fd);                  return -1;          }          log_dbg("Packed information inserted into RIB."); -        cdap_destroy(ci); +        cdap_destroy(cdap); +        flow_dealloc(conn.flow_info.fd); + +        return 0; +} + +int enroll_init(void) +{ +        struct conn_info info; + +        memset(&info, 0, sizeof(info)); + +        strcpy(info.ae_name, ENROLL_AE); +        strcpy(info.protocol, CDAP_PROTO); +        info.pref_version = 1; +        info.pref_syntax  = PROTO_GPB; + +        enroll.ae = connmgr_ae_create(info); +        if (enroll.ae == NULL) +                return -1; + +        return 0; +} -        flow_dealloc(fd); +void enroll_fini(void) +{ +        connmgr_ae_destroy(enroll.ae); +} + +int enroll_start(void) +{ +        if (pthread_create(&enroll.listener, NULL, enroll_handle, NULL)) +                return -1;          return 0;  } + +void enroll_stop(void) +{ +        pthread_cancel(enroll.listener); +        pthread_join(enroll.listener, NULL); +} diff --git a/src/ipcpd/normal/enroll.h b/src/ipcpd/normal/enroll.h index 2980c380..05f950ba 100644 --- a/src/ipcpd/normal/enroll.h +++ b/src/ipcpd/normal/enroll.h @@ -3,7 +3,8 @@   *   * Enrollment Task   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> + *    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 @@ -22,8 +23,14 @@  #ifndef OUROBOROS_IPCPD_NORMAL_ENROLL_H  #define OUROBOROS_IPCPD_NORMAL_ENROLL_H -int enroll_handle(int fd); +int  enroll_init(void); -int enroll_boot(char * dst_name); +void enroll_fini(void); + +int  enroll_start(void); + +void enroll_stop(void); + +int  enroll_boot(char * dst_name);  #endif /* OUROBOROS_IPCPD_NORMAL_ENROLL_H */ diff --git a/src/ipcpd/normal/flow_alloc.proto b/src/ipcpd/normal/flow_alloc.proto index 16e8be2c..3b08f047 100644 --- a/src/ipcpd/normal/flow_alloc.proto +++ b/src/ipcpd/normal/flow_alloc.proto @@ -31,7 +31,6 @@ enum flow_alloc_code {  message flow_alloc_msg {          required flow_alloc_code code  = 1;          optional string dst_name       = 2; -        optional string src_ae_name    = 3; -        optional uint32 qoscube        = 4; -        optional sint32 response       = 5; +        optional uint32 qoscube        = 3; +        optional sint32 response       = 4;  }; diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index c2b53abf..790b34dd 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -3,7 +3,8 @@   *   * Flow manager of the IPC Process   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -31,12 +32,16 @@  #include <ouroboros/cacep.h>  #include <ouroboros/rib.h> +#include "connmgr.h"  #include "fmgr.h"  #include "frct.h"  #include "ipcp.h"  #include "shm_pci.h" -#include "gam.h"  #include "ribconfig.h" +#include "pff.h" +#include "neighbors.h" +#include "gam.h" +#include "routing.h"  #include <stdlib.h>  #include <stdbool.h> @@ -48,19 +53,7 @@ typedef FlowAllocMsg flow_alloc_msg_t;  #define FD_UPDATE_TIMEOUT 100000 /* nanoseconds */ -struct nm1_flow { -        struct list_head    next; -        int                 fd; -        qosspec_t           qs; -        struct cacep_info * info; -}; -  struct { -        flow_set_t *       nm1_set[QOS_CUBE_MAX]; -        fqueue_t *         nm1_fqs[QOS_CUBE_MAX]; -        struct list_head   nm1_flows; -        pthread_rwlock_t   nm1_flows_lock; -          flow_set_t *       np1_set[QOS_CUBE_MAX];          fqueue_t *         np1_fqs[QOS_CUBE_MAX];          pthread_rwlock_t   np1_flows_lock; @@ -69,15 +62,45 @@ struct {          int                np1_cep_id_to_fd[IPCPD_MAX_CONNS];          pthread_t          np1_sdu_reader; + +        flow_set_t *       nm1_set[QOS_CUBE_MAX]; +        fqueue_t *         nm1_fqs[QOS_CUBE_MAX];          pthread_t          nm1_sdu_reader; -        pthread_t          nm1_flow_wait; -        /* FIXME: Replace with PFF */ -        int fd; +        struct pff *       pff[QOS_CUBE_MAX]; +        struct routing_i * routing[QOS_CUBE_MAX];          struct gam *       gam; +        struct nbs *       nbs; +        struct ae *        ae; + +        struct nb_notifier nb_notifier;  } fmgr; +static int fmgr_neighbor_event(enum nb_event event, +                               struct conn   conn) +{ +        qoscube_t cube; + +        /* We are only interested in neighbors being added and removed. */ +        switch (event) { +        case NEIGHBOR_ADDED: +                ipcp_flow_get_qoscube(conn.flow_info.fd, &cube); +                flow_set_add(fmgr.nm1_set[cube], conn.flow_info.fd); +                log_dbg("Added fd %d to flow set.", conn.flow_info.fd); +                break; +        case NEIGHBOR_REMOVED: +                ipcp_flow_get_qoscube(conn.flow_info.fd, &cube); +                flow_set_del(fmgr.nm1_set[cube], conn.flow_info.fd); +                log_dbg("Removed fd %d from flow set.", conn.flow_info.fd); +                break; +        default: +                break; +        } + +        return 0; +} +  static void * fmgr_np1_sdu_reader(void * o)  {          struct shm_du_buff * sdb; @@ -162,7 +185,7 @@ void * fmgr_nm1_sdu_reader(void * o)                          shm_pci_des(sdb, &pci); -                        if (pci.dst_addr != ipcpi.address) { +                        if (pci.dst_addr != ipcpi.dt_addr) {                                  log_dbg("PDU needs to be forwarded.");                                  if (pci.ttl == 0) { @@ -171,12 +194,20 @@ void * fmgr_nm1_sdu_reader(void * o)                                          continue;                                  } -                                /* -                                 * FIXME: Dropping for now, since -                                 * we don't have a PFF yet -                                 */ -                                ipcp_flow_del(sdb); -                                continue; +                                fd = pff_nhop(fmgr.pff[i], pci.dst_addr); +                                if (fd < 0) { +                                        log_err("No next hop for %lu", +                                                pci.dst_addr); +                                        ipcp_flow_del(sdb); +                                        continue; +                                } + +                                if (ipcp_flow_write(fd, sdb)) { +                                        log_err("Failed to write SDU to fd %d.", +                                                fd); +                                        ipcp_flow_del(sdb); +                                        continue; +                                }                          }                          shm_pci_shrink(sdb); @@ -192,49 +223,6 @@ void * fmgr_nm1_sdu_reader(void * o)          return (void *) 0;  } -static void * fmgr_nm1_flow_wait(void * o) -{ -        qoscube_t           cube; -        struct cacep_info * info; -        int                 fd; -        qosspec_t           qs; -        struct nm1_flow *   flow; - -        (void) o; - -        while (true) { -                if (gam_flow_wait(fmgr.gam, &fd, &info, &qs)) { -                        log_err("Failed to get next flow descriptor."); -                        continue; -                } - -                ipcp_flow_get_qoscube(fd, &cube); -                flow_set_add(fmgr.nm1_set[cube], fd); - -                /* FIXME: Temporary, until we have a PFF */ -                fmgr.fd = fd; - -                pthread_rwlock_wrlock(&fmgr.nm1_flows_lock); -                flow = malloc(sizeof(*flow)); -                if (flow == NULL) { -                        free(info); -                        pthread_rwlock_unlock(&fmgr.nm1_flows_lock); -                        continue; -                } - -                flow->info = info; -                flow->fd = fd; -                flow->qs = qs; - -                list_head_init(&flow->next); -                list_add(&flow->next, &fmgr.nm1_flows); - -                pthread_rwlock_unlock(&fmgr.nm1_flows_lock); -        } - -        return (void *) 0; -} -  static void fmgr_destroy_flows(void)  {          int i; @@ -247,13 +235,28 @@ static void fmgr_destroy_flows(void)          }  } -int fmgr_init(void) +static void fmgr_destroy_routing(void)  { -        enum pol_cacep     pc; -        enum pol_gam       pg; +        int i; +        for (i = 0; i < QOS_CUBE_MAX; ++i) +                routing_i_destroy(fmgr.routing[i]); +} + +static void fmgr_destroy_pff(void) +{          int i; +        for (i = 0; i < QOS_CUBE_MAX; ++i) +                pff_destroy(fmgr.pff[i]); +} + +int fmgr_init(void) +{ +        int              i; +        int              j; +        struct conn_info info; +          for (i = 0; i < AP_MAX_FLOWS; ++i)                  fmgr.np1_fd_to_cep_id[i] = INVALID_CEP_ID; @@ -286,81 +289,139 @@ int fmgr_init(void)                  }          } -        if (rib_read(BOOT_PATH "/dt/gam/type", &pg, sizeof(pg)) -            != sizeof(pg)) { -                log_err("Failed to read policy for ribmgr gam."); +        strcpy(info.ae_name, DT_AE); +        strcpy(info.protocol, FRCT_PROTO); +        info.pref_version = 1; +        info.pref_syntax = PROTO_FIXED; +        info.addr = ipcpi.dt_addr; + +        fmgr.ae = connmgr_ae_create(info); +        if (fmgr.ae == NULL) { +                log_err("Failed to create AE struct."); +                fmgr_destroy_flows();                  return -1;          } -        if (rib_read(BOOT_PATH "/dt/gam/cacep", &pc, sizeof(pc)) -            != sizeof(pc)) { -                log_err("Failed to read CACEP policy for ribmgr gam."); +        fmgr.nbs = nbs_create(); +        if (fmgr.nbs == NULL) { +                log_err("Failed to create neighbors struct."); +                fmgr_destroy_flows(); +                connmgr_ae_destroy(fmgr.ae);                  return -1;          } -        /* FIXME: Implement cacep policies */ -        (void) pc; +        fmgr.nb_notifier.notify_call = fmgr_neighbor_event; +        if (nbs_reg_notifier(fmgr.nbs, &fmgr.nb_notifier)) { +                log_err("Failed to register notifier."); +                nbs_destroy(fmgr.nbs); +                fmgr_destroy_flows(); +                connmgr_ae_destroy(fmgr.ae); +                return -1; +        } -        fmgr.gam = gam_create(pg, DT_AE); -        if (fmgr.gam == NULL) { -                log_err("Failed to create graph adjacency manager."); +        if (routing_init(fmgr.nbs)) { +                log_err("Failed to init routing."); +                nbs_unreg_notifier(fmgr.nbs, &fmgr.nb_notifier); +                nbs_destroy(fmgr.nbs);                  fmgr_destroy_flows(); +                connmgr_ae_destroy(fmgr.ae);                  return -1;          } -        list_head_init(&fmgr.nm1_flows); +        if (pthread_rwlock_init(&fmgr.np1_flows_lock, NULL)) { +                routing_fini(); +                nbs_unreg_notifier(fmgr.nbs, &fmgr.nb_notifier); +                nbs_destroy(fmgr.nbs); +                fmgr_destroy_flows(); +                connmgr_ae_destroy(fmgr.ae); +                return -1; +        } -        pthread_rwlock_init(&fmgr.nm1_flows_lock, NULL); -        pthread_rwlock_init(&fmgr.np1_flows_lock, NULL); +        for (i = 0; i < QOS_CUBE_MAX; ++i) { +                fmgr.pff[i] = pff_create(); +                if (fmgr.pff[i] == NULL) { +                        for (j = 0; j < i; ++j) +                                pff_destroy(fmgr.pff[j]); +                        pthread_rwlock_destroy(&fmgr.np1_flows_lock); +                        routing_fini(); +                        nbs_unreg_notifier(fmgr.nbs, &fmgr.nb_notifier); +                        nbs_destroy(fmgr.nbs); +                        fmgr_destroy_flows(); +                        connmgr_ae_destroy(fmgr.ae); +                        return -1; +                } -        pthread_create(&fmgr.np1_sdu_reader, NULL, fmgr_np1_sdu_reader, NULL); -        pthread_create(&fmgr.nm1_sdu_reader, NULL, fmgr_nm1_sdu_reader, NULL); -        pthread_create(&fmgr.nm1_flow_wait, NULL, fmgr_nm1_flow_wait, NULL); +                fmgr.routing[i] = routing_i_create(fmgr.pff[i]); +                if (fmgr.routing[i] == NULL) { +                        for (j = 0; j < i; ++j) +                                routing_i_destroy(fmgr.routing[j]); +                        fmgr_destroy_pff(); +                        pthread_rwlock_destroy(&fmgr.np1_flows_lock); +                        routing_fini(); +                        nbs_unreg_notifier(fmgr.nbs, &fmgr.nb_notifier); +                        nbs_destroy(fmgr.nbs); +                        fmgr_destroy_flows(); +                        connmgr_ae_destroy(fmgr.ae); +                        return -1; +                } +        }          return 0;  }  void fmgr_fini()  { -        struct list_head * pos = NULL; -        struct list_head * n = NULL; -        qoscube_t          cube; +        nbs_unreg_notifier(fmgr.nbs, &fmgr.nb_notifier); -        pthread_cancel(fmgr.np1_sdu_reader); -        pthread_cancel(fmgr.nm1_sdu_reader); -        pthread_cancel(fmgr.nm1_flow_wait); +        fmgr_destroy_routing(); -        pthread_join(fmgr.np1_sdu_reader, NULL); -        pthread_join(fmgr.nm1_sdu_reader, NULL); -        pthread_join(fmgr.nm1_flow_wait, NULL); +        fmgr_destroy_pff(); -        gam_destroy(fmgr.gam); +        routing_fini(); + +        fmgr_destroy_flows(); + +        connmgr_ae_destroy(fmgr.ae); + +        nbs_destroy(fmgr.nbs); +} + +int fmgr_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; +        } -        pthread_rwlock_wrlock(&fmgr.nm1_flows_lock); - -        list_for_each_safe(pos, n, &fmgr.nm1_flows) { -                struct nm1_flow * flow = -                        list_entry(pos, struct nm1_flow, next); -                list_del(&flow->next); -                flow_dealloc(flow->fd); -                ipcp_flow_get_qoscube(flow->fd, &cube); -                flow_set_del(fmgr.nm1_set[cube], flow->fd); -                free(flow->info->name); -                free(flow->info); -                free(flow); +        fmgr.gam = gam_create(pg, fmgr.nbs, fmgr.ae); +        if (fmgr.gam == NULL) { +                log_err("Failed to init dt graph adjacency manager."); +                nbs_unreg_notifier(fmgr.nbs, &fmgr.nb_notifier); +                return -1;          } -        pthread_rwlock_unlock(&fmgr.nm1_flows_lock); +        pthread_create(&fmgr.np1_sdu_reader, NULL, fmgr_np1_sdu_reader, NULL); +        pthread_create(&fmgr.nm1_sdu_reader, NULL, fmgr_nm1_sdu_reader, NULL); -        pthread_rwlock_destroy(&fmgr.nm1_flows_lock); -        pthread_rwlock_destroy(&fmgr.np1_flows_lock); +        return 0; +} -        fmgr_destroy_flows(); +void fmgr_stop(void) +{ +        pthread_cancel(fmgr.np1_sdu_reader); +        pthread_cancel(fmgr.nm1_sdu_reader); + +        pthread_join(fmgr.np1_sdu_reader, NULL); +        pthread_join(fmgr.nm1_sdu_reader, NULL); + +        gam_destroy(fmgr.gam);  }  int fmgr_np1_alloc(int       fd,                     char *    dst_ap_name, -                   char *    src_ae_name,                     qoscube_t cube)  {          cep_id_t         cep_id; @@ -406,7 +467,6 @@ int fmgr_np1_alloc(int       fd,          msg.code = FLOW_ALLOC_CODE__FLOW_REQ;          msg.dst_name = dst_ap_name; -        msg.src_ae_name = src_ae_name;          msg.has_qoscube = true;          msg.qoscube = cube; @@ -546,7 +606,6 @@ int fmgr_np1_post_buf(cep_id_t   cep_id,          case FLOW_ALLOC_CODE__FLOW_REQ:                  fd = ipcp_flow_req_arr(getpid(),                                         msg->dst_name, -                                       msg->src_ae_name,                                         msg->qoscube);                  if (fd < 0) {                          flow_alloc_msg__free_unpacked(msg, NULL); @@ -615,24 +674,20 @@ int fmgr_np1_post_sdu(cep_id_t             cep_id,          return 0;  } -int fmgr_nm1_flow_arr(int       fd, -                      qosspec_t qs) -{ -        assert(fmgr.gam); - -        if (gam_flow_arr(fmgr.gam, fd, qs)) { -                log_err("Failed to hand to graph adjacency manager."); -                return -1; -        } - -        return 0; -} -  int fmgr_nm1_write_sdu(struct pci *         pci,                         struct shm_du_buff * sdb)  { +        int fd; +          if (pci == NULL || sdb == NULL) +                return -EINVAL; + +        fd = pff_nhop(fmgr.pff[pci->qos_id], pci->dst_addr); +        if (fd < 0) { +                log_err("Could not get nhop for address %lu", pci->dst_addr); +                ipcp_flow_del(sdb);                  return -1; +        }          if (shm_pci_ser(sdb, pci)) {                  log_err("Failed to serialize PDU."); @@ -640,8 +695,8 @@ int fmgr_nm1_write_sdu(struct pci *         pci,                  return -1;          } -        if (ipcp_flow_write(fmgr.fd, sdb)) { -                log_err("Failed to write SDU to fd %d.", fmgr.fd); +        if (ipcp_flow_write(fd, sdb)) { +                log_err("Failed to write SDU to fd %d.", fd);                  ipcp_flow_del(sdb);                  return -1;          } @@ -653,9 +708,17 @@ int fmgr_nm1_write_buf(struct pci * pci,                         buffer_t *   buf)  {          buffer_t * buffer; +        int        fd;          if (pci == NULL || buf == NULL || buf->data == NULL) +                return -EINVAL; + +        fd = pff_nhop(fmgr.pff[pci->qos_id], pci->dst_addr); +        if (fd < 0) { +                log_err("Could not get nhop for address %lu", pci->dst_addr); +                free(buf->data);                  return -1; +        }          buffer = shm_pci_ser_buf(buf, pci);          if (buffer == NULL) { @@ -664,7 +727,7 @@ int fmgr_nm1_write_buf(struct pci * pci,                  return -1;          } -        if (flow_write(fmgr.fd, buffer->data, buffer->len) == -1) { +        if (flow_write(fd, buffer->data, buffer->len) == -1) {                  log_err("Failed to write buffer to fd.");                  free(buffer);                  return -1; diff --git a/src/ipcpd/normal/fmgr.h b/src/ipcpd/normal/fmgr.h index 3c61f55a..b4d0b65a 100644 --- a/src/ipcpd/normal/fmgr.h +++ b/src/ipcpd/normal/fmgr.h @@ -3,7 +3,8 @@   *   * Flow manager of the IPC Process   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -32,9 +33,12 @@ int  fmgr_init(void);  void fmgr_fini(void); +int  fmgr_start(void); + +void fmgr_stop(void); +  int  fmgr_np1_alloc(int       fd,                      char *    dst_ap_name, -                    char *    src_ae_name,                      qoscube_t qos);  int  fmgr_np1_alloc_resp(int fd, @@ -54,8 +58,4 @@ int  fmgr_nm1_write_sdu(struct pci *         pci,  int  fmgr_nm1_write_buf(struct pci * pci,                          buffer_t *   buf); -int  fmgr_nm1_flow_arr(int       fd, -                       qosspec_t qs); - -  #endif /* OUROBOROS_IPCPD_NORMAL_FMGR_H */ diff --git a/src/ipcpd/normal/frct.c b/src/ipcpd/normal/frct.c index 915feaf8..62cbf9f7 100644 --- a/src/ipcpd/normal/frct.c +++ b/src/ipcpd/normal/frct.c @@ -3,7 +3,8 @@   *   * The Flow and Retransmission control component   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -198,12 +199,12 @@ int frct_fini()          return 0;  } -int frct_nm1_post_sdu(struct pci * pci, +int frct_nm1_post_sdu(struct pci *         pci,                        struct shm_du_buff * sdb)  {          struct frct_i * instance; -        buffer_t buf; -        cep_id_t id; +        buffer_t        buf; +        cep_id_t        id;          if (pci == NULL || sdb == NULL)                  return -1; @@ -267,8 +268,8 @@ cep_id_t frct_i_create(uint64_t   address,                         qoscube_t  cube)  {          struct frct_i * instance; -        struct pci pci; -        cep_id_t id; +        struct pci      pci; +        cep_id_t        id;          if (buf == NULL || buf->data == NULL)                  return INVALID_CEP_ID; @@ -285,7 +286,7 @@ cep_id_t frct_i_create(uint64_t   address,          pci.pdu_type = PDU_TYPE_MGMT;          pci.dst_addr = address; -        pci.src_addr = ipcpi.address; +        pci.src_addr = ipcpi.dt_addr;          pci.dst_cep_id = 0;          pci.src_cep_id = id;          pci.seqno = 0; @@ -304,7 +305,7 @@ int frct_i_accept(cep_id_t   id,                    buffer_t * buf,                    qoscube_t  cube)  { -        struct pci pci; +        struct pci      pci;          struct frct_i * instance;          if (buf == NULL || buf->data == NULL) @@ -330,7 +331,7 @@ int frct_i_accept(cep_id_t   id,          pci.pdu_type = PDU_TYPE_MGMT;          pci.dst_addr = instance->r_address; -        pci.src_addr = ipcpi.address; +        pci.src_addr = ipcpi.dt_addr;          pci.dst_cep_id = instance->r_cep_id;          pci.src_cep_id = instance->cep_id;          pci.seqno = 0; @@ -347,7 +348,7 @@ int frct_i_accept(cep_id_t   id,  int frct_i_destroy(cep_id_t   id,                     buffer_t * buf)  { -        struct pci pci; +        struct pci      pci;          struct frct_i * instance;          pthread_mutex_lock(&frct.instances_lock); @@ -367,7 +368,7 @@ int frct_i_destroy(cep_id_t   id,          pci.pdu_type = PDU_TYPE_MGMT;          pci.dst_addr = instance->r_address; -        pci.src_addr = ipcpi.address; +        pci.src_addr = ipcpi.dt_addr;          pci.dst_cep_id = instance->r_cep_id;          pci.src_cep_id = instance->cep_id;          pci.seqno = 0; @@ -390,7 +391,7 @@ int frct_i_destroy(cep_id_t   id,  int frct_i_write_sdu(cep_id_t             id,                       struct shm_du_buff * sdb)  { -        struct pci pci; +        struct pci      pci;          struct frct_i * instance;          if (sdb == NULL) @@ -413,7 +414,7 @@ int frct_i_write_sdu(cep_id_t             id,          pci.pdu_type = PDU_TYPE_DTP;          pci.dst_addr = instance->r_address; -        pci.src_addr = ipcpi.address; +        pci.src_addr = ipcpi.dt_addr;          pci.dst_cep_id = instance->r_cep_id;          pci.src_cep_id = instance->cep_id;          pci.seqno = (instance->seqno)++; diff --git a/src/ipcpd/normal/frct.h b/src/ipcpd/normal/frct.h index 462b8cc3..a1dcb151 100644 --- a/src/ipcpd/normal/frct.h +++ b/src/ipcpd/normal/frct.h @@ -3,7 +3,8 @@   *   * The Flow and Retransmission control component   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -27,6 +28,8 @@  #include "shm_pci.h" +#define FRCT_PROTO "FRCT" +  struct frct_i;  int         frct_init(void); diff --git a/src/ipcpd/normal/fso.proto b/src/ipcpd/normal/fso.proto new file mode 100644 index 00000000..32b281d6 --- /dev/null +++ b/src/ipcpd/normal/fso.proto @@ -0,0 +1,29 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Flow State Object message + * + *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +syntax = "proto2"; + +message fso { +        required uint64 s_addr = 1; +        required uint64 d_addr = 2; +        /* Add QoS parameters of link here */ +}; diff --git a/src/ipcpd/normal/gam.c b/src/ipcpd/normal/gam.c index 9ee55261..643d83b0 100644 --- a/src/ipcpd/normal/gam.c +++ b/src/ipcpd/normal/gam.c @@ -1,10 +1,10 @@  /*   * Ouroboros - Copyright (C) 2016 - 2017   * - * Graph adjacency manager for IPC Process components + *  Data transfer graph adjacency manager   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 @@ -20,9 +20,10 @@   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ -#define OUROBOROS_PREFIX "graph-adjacency-manager" +#define OUROBOROS_PREFIX "dt-gam"  #include <ouroboros/config.h> +#include <ouroboros/cdap.h>  #include <ouroboros/dev.h>  #include <ouroboros/logs.h>  #include <ouroboros/list.h> @@ -39,271 +40,43 @@  #include <pthread.h>  #include <string.h> -struct ga { -        struct list_head    next; - -        qosspec_t           qs; -        int                 fd; -        struct cacep_info * info; -}; -  struct gam { -        struct list_head     gas; -        pthread_mutex_t      gas_lock; -        pthread_cond_t       gas_cond; - -        char *               ae_name; -          struct pol_gam_ops * ops;          void *               ops_o;  };  struct gam * gam_create(enum pol_gam gam_type, -                        const char * ae_name) +                        struct nbs * nbs, +                        struct ae *  ae)  { -        struct gam * tmp; +        struct gam * gam; -        tmp = malloc(sizeof(*tmp)); -        if (tmp == NULL) +        gam = malloc(sizeof(*gam)); +        if (gam == NULL)                  return NULL;          switch (gam_type) {          case COMPLETE: -                tmp->ops = &complete_ops; +                gam->ops = &complete_ops;                  break;          default:                  log_err("Unknown gam policy: %d.", gam_type); -                free(tmp); -                return NULL; -        } - -        list_head_init(&tmp->gas); - -        tmp->ae_name = strdup(ae_name); -        if (tmp->ae_name == NULL) { -                free(tmp); -                return NULL; -        } - -        if (pthread_mutex_init(&tmp->gas_lock, NULL)) { -                free(tmp->ae_name); -                free(tmp); -                return NULL; -        } - -        if (pthread_cond_init(&tmp->gas_cond, NULL)) { -                pthread_mutex_destroy(&tmp->gas_lock); -                free(tmp->ae_name); -                free(tmp);                  return NULL;          } -        tmp->ops_o = tmp->ops->create(tmp); -        if (tmp->ops_o == NULL) { -                pthread_cond_destroy(&tmp->gas_cond); -                pthread_mutex_destroy(&tmp->gas_lock); -                free(tmp->ae_name); -                free(tmp); +        gam->ops_o = gam->ops->create(nbs, ae); +        if (gam->ops_o == NULL) { +                free(gam);                  return NULL;          } -        if (tmp->ops->start(tmp->ops_o)) { -                pthread_cond_destroy(&tmp->gas_cond); -                pthread_mutex_destroy(&tmp->gas_lock); -                free(tmp->ae_name); -                free(tmp); -                return NULL; -        } - -        return tmp; -} - -void gam_destroy(struct gam * instance) -{ -        struct list_head * p = NULL; -        struct list_head * n = NULL; - -        assert(instance); - -        instance->ops->stop(instance->ops_o); - -        pthread_mutex_lock(&instance->gas_lock); - -        list_for_each_safe(p, n, &instance->gas) { -                struct ga * e = list_entry(p, struct ga, next); -                list_del(&e->next); -                free(e->info->name); -                free(e->info); -                free(e); -        } - -        pthread_mutex_unlock(&instance->gas_lock); - -        pthread_mutex_destroy(&instance->gas_lock); -        pthread_cond_destroy(&instance->gas_cond); - -        free(instance->ae_name); -        instance->ops->destroy(instance->ops_o); -        free(instance); -} - -static int add_ga(struct gam *        instance, -                  int                 fd, -                  qosspec_t           qs, -                  struct cacep_info * info) -{ -        struct ga * ga; - -        ga = malloc(sizeof(*ga)); -        if (ga == NULL) -                return -ENOMEM; - -        ga->fd = fd; -        ga->info = info; -        ga->qs = qs; - -        list_head_init(&ga->next); - -        pthread_mutex_lock(&instance->gas_lock); -        list_add(&ga->next, &instance->gas); -        pthread_cond_signal(&instance->gas_cond); -        pthread_mutex_unlock(&instance->gas_lock); - -        log_info("Added %s flow to %s.", instance->ae_name, info->name); - -        return 0; +        return gam;  } -int gam_flow_arr(struct gam * instance, -                 int          fd, -                 qosspec_t    qs) +void gam_destroy(struct gam * gam)  { -        struct cacep *      cacep; -        struct cacep_info * info; - -        if (flow_alloc_resp(fd, instance->ops->accept_new_flow(instance->ops_o)) -            < 0) { -                log_err("Could not respond to new flow."); -                return -1; -        } - -        cacep = cacep_create(fd, ipcpi.name, ipcpi.address); -        if (cacep == NULL) { -                log_err("Failed to create CACEP instance."); -                return -1; -        } - -        info = cacep_auth_wait(cacep); -        if (info == NULL) { -                log_err("Other side failed to authenticate."); -                cacep_destroy(cacep); -                return -1; -        } - -        cacep_destroy(cacep); - -        if (instance->ops->accept_flow(instance->ops_o, qs, info)) { -                flow_dealloc(fd); -                free(info->name); -                free(info); -                return 0; -        } - -        if (add_ga(instance, fd, qs, info)) { -                log_err("Failed to add ga to graph adjacency manager list."); -                free(info->name); -                free(info); -                return -1; -        } - -        return 0; -} - -int gam_flow_alloc(struct gam * instance, -                   char *       dst_name, -                   qosspec_t    qs) -{ -        struct cacep *      cacep; -        struct cacep_info * info; -        int                 fd; - -        fd = flow_alloc(dst_name, instance->ae_name, NULL); -        if (fd < 0) { -                log_err("Failed to allocate flow to %s.", dst_name); -                return -1; -        } - -        if (flow_alloc_res(fd)) { -                log_err("Flow allocation to %s failed.", dst_name); -                flow_dealloc(fd); -                return -1; -        } - -        cacep = cacep_create(fd, ipcpi.name, ipcpi.address); -        if (cacep == NULL) { -                log_err("Failed to create CACEP instance."); -                return -1; -        } - -        info = cacep_auth(cacep); -        if (info == NULL) { -                log_err("Failed to authenticate."); -                cacep_destroy(cacep); -                return -1; -        } - -        cacep_destroy(cacep); - -        if (instance->ops->accept_flow(instance->ops_o, qs, info)) { -                flow_dealloc(fd); -                free(info->name); -                free(info); -                return 0; -        } - -        if (add_ga(instance, fd, qs, info)) { -                log_err("Failed to add GA to graph adjacency manager list."); -                free(info->name); -                free(info); -                return -1; -        } - -        return 0; -} - -int gam_flow_wait(struct gam *         instance, -                  int *                fd, -                  struct cacep_info ** info, -                  qosspec_t *          qs) -{ -        struct ga * ga; - -        assert(fd); -        assert(info); -        assert(qs); - -        pthread_mutex_lock(&instance->gas_lock); - -        pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock, -                             (void *) &instance->gas_lock); - -        while (list_is_empty(&instance->gas)) -                pthread_cond_wait(&instance->gas_cond, &instance->gas_lock); - -        ga = list_first_entry((&instance->gas), struct ga, next); -        if (ga == NULL) { -                pthread_mutex_unlock(&instance->gas_lock); -                return -1; -        } - -        *fd   = ga->fd; -        *info = ga->info; -        *qs   = ga->qs; - -        list_del(&ga->next); -        free(ga); - -        pthread_cleanup_pop(true); +        assert(gam); -        return 0; +        gam->ops->destroy(gam->ops_o); +        free(gam);  } diff --git a/src/ipcpd/normal/gam.h b/src/ipcpd/normal/gam.h index 50f83df9..4ae0b1b3 100644 --- a/src/ipcpd/normal/gam.h +++ b/src/ipcpd/normal/gam.h @@ -1,10 +1,10 @@  /*   * Ouroboros - Copyright (C) 2016 - 2017   * - * Graph adjacency manager for IPC Process components + * Data transfer graph adjacency manager   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 @@ -26,22 +26,12 @@  #include <ouroboros/cacep.h>  #include <ouroboros/irm_config.h> -struct gam * gam_create(enum pol_gam gam_type, -                        const char * ae_name); - -void         gam_destroy(struct gam * instance); +#include "neighbors.h" -int          gam_flow_arr(struct gam * instance, -                          int          fd, -                          qosspec_t    qs); - -int          gam_flow_alloc(struct gam * instance, -                            char *       dst_name, -                            qosspec_t    qs); +struct gam * gam_create(enum pol_gam gam_type, +                        struct nbs * nbs, +                        struct ae *  ae); -int          gam_flow_wait(struct gam *         instance, -                           int *                fd, -                           struct cacep_info ** info, -                           qosspec_t *          qs); +void         gam_destroy(struct gam * gam);  #endif /* OUROBOROS_IPCPD_NORMAL_GAM_H */ diff --git a/src/ipcpd/normal/graph.c b/src/ipcpd/normal/graph.c new file mode 100644 index 00000000..85bb3fe2 --- /dev/null +++ b/src/ipcpd/normal/graph.c @@ -0,0 +1,277 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Graph structure + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define OUROBOROS_PREFIX "graph" + +#include <ouroboros/config.h> +#include <ouroboros/logs.h> +#include <ouroboros/errno.h> +#include <ouroboros/list.h> + +#include "graph.h" + +#include <assert.h> +#include <pthread.h> +#include <stdlib.h> + +static struct edge * find_edge_by_addr(struct vertex * vertex, +                                       uint64_t        dst_addr) +{ +        struct list_head * p = NULL; + +        list_for_each(p, &vertex->edges) { +                struct edge * e = list_entry(p, struct edge, next); +                if (e->dst_addr == dst_addr) +                        return e; +        } + +        return NULL; +} + +static struct vertex * find_vertex_by_addr(struct graph * graph, +                                           uint64_t       addr) +{ +        struct list_head * p = NULL; + +        list_for_each(p, &graph->vertices) { +                struct vertex * e = list_entry(p, struct vertex, next); +                if (e->addr == addr) +                        return e; +        } + +        return NULL; +} + +static int add_edge(struct vertex * vertex, +                    uint64_t        dst_addr, +                    qosspec_t       qs) +{ +        struct edge * edge; + +        edge = malloc(sizeof(*edge)); +        if (edge == NULL) +                return -ENOMEM; + +        list_head_init(&edge->next); +        edge->dst_addr = dst_addr; +        edge->qs = qs; + +        list_add(&edge->next, &vertex->edges); + +        return 0; +} + +static void del_edge(struct edge * edge) +{ +       list_del(&edge->next); +       free(edge); +} + +static int add_vertex(struct graph * graph, +                      uint64_t       addr) +{ +        struct vertex *    vertex; +        struct list_head * p; + +        vertex = malloc(sizeof(*vertex)); +        if (vertex == NULL) +                return -1; + +        list_head_init(&vertex->next); +        list_head_init(&vertex->edges); +        vertex->addr = addr; + +        list_for_each(p, &graph->vertices) { +                struct vertex * v = list_entry(p, struct vertex, next); +                if (v->addr > addr) +                        break; +        } + +        list_add_tail(&vertex->next, p); + +        graph->nr_vertices++; + +        return 0; +} + +static void del_vertex(struct graph * graph, +                       struct vertex * vertex) +{ +        struct list_head * p = NULL; +        struct list_head * n = NULL; + +        list_del(&vertex->next); + +        list_for_each_safe(p, n, &vertex->edges) { +                struct edge * e = list_entry(p, struct edge, next); +                del_edge(e); +        } + +        free(vertex); + +        graph->nr_vertices--; +} + +struct graph * graph_create(void) +{ +        struct graph * graph; + +        graph = malloc(sizeof(*graph)); +        if (graph == NULL) +                return NULL; + +        if (pthread_mutex_init(&graph->lock, NULL)) { +                free(graph); +                return NULL; +        } + +        graph->nr_vertices = 0; +        list_head_init(&graph->vertices); + +        return graph; +} + +void graph_destroy(struct graph * graph) +{ +        struct list_head * p = NULL; +        struct list_head * n = NULL; + +        assert(graph); + +        pthread_mutex_lock(&graph->lock); + +        list_for_each_safe(p, n, &graph->vertices) { +                struct vertex * e = list_entry(p, struct vertex, next); +                del_vertex(graph, e); +        } + +        pthread_mutex_unlock(&graph->lock); + +        pthread_mutex_destroy(&graph->lock); +} + +int graph_add_edge(struct graph * graph, +                   uint64_t       s_addr, +                   uint64_t       d_addr, +                   qosspec_t      qs) +{ +        struct vertex * v; +        struct edge * e; + +        assert(graph); + +        pthread_mutex_lock(&graph->lock); + +        v = find_vertex_by_addr(graph, s_addr); +        if (v == NULL) { +                if (add_vertex(graph, s_addr)) { +                        pthread_mutex_unlock(&graph->lock); +                        return -ENOMEM; +                } +        } + +        e = find_edge_by_addr(v, d_addr); +        if (e != NULL) { +                pthread_mutex_unlock(&graph->lock); +                log_err("Edge already exists."); +                return -1; +        } + +        if (add_edge(v, d_addr, qs)) { +                pthread_mutex_unlock(&graph->lock); +                log_err("Failed to add edge."); +                return -1; +        } + +        pthread_mutex_unlock(&graph->lock); + +        return 0; +} + +int graph_update_edge(struct graph * graph, +                      uint64_t       s_addr, +                      uint64_t       d_addr, +                      qosspec_t      qs) +{ +        struct vertex * v; +        struct edge * e; + +        assert(graph); + +        pthread_mutex_lock(&graph->lock); + +        v = find_vertex_by_addr(graph, s_addr); +        if (v == NULL) { +                pthread_mutex_unlock(&graph->lock); +                log_err("No such vertex."); +                return -1; +        } + +        e = find_edge_by_addr(v, d_addr); +        if (e == NULL) { +                pthread_mutex_unlock(&graph->lock); +                log_err("No such edge."); +                return -1; +        } + +        e->qs = qs; + +        pthread_mutex_unlock(&graph->lock); + +        return 0; +} + +int graph_del_edge(struct graph * graph, +                   uint64_t       s_addr, +                   uint64_t       d_addr) +{ +        struct vertex * v; +        struct edge * e; + +        assert(graph); + +        pthread_mutex_lock(&graph->lock); + +        v = find_vertex_by_addr(graph, s_addr); +        if (v == NULL) { +                pthread_mutex_unlock(&graph->lock); +                log_err("No such vertex."); +                return -1; +        } + +        e = find_edge_by_addr(v, d_addr); +        if (e == NULL) { +                pthread_mutex_unlock(&graph->lock); +                log_err("No such edge."); +                return -1; +        } + +        del_edge(e); + +        /* Removing vertex if it was the last edge */ +        if (list_is_empty(&v->edges)) +               del_vertex(graph, v); + +        pthread_mutex_unlock(&graph->lock); + +        return 0; +} diff --git a/src/ipcpd/normal/graph.h b/src/ipcpd/normal/graph.h new file mode 100644 index 00000000..9653efd7 --- /dev/null +++ b/src/ipcpd/normal/graph.h @@ -0,0 +1,67 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Graph structure + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_GRAPH_H +#define OUROBOROS_IPCPD_NORMAL_GRAPH_H + +#include <ouroboros/list.h> +#include <ouroboros/qos.h> + +#include <inttypes.h> + +struct edge { +        struct list_head next; +        uint64_t         dst_addr; +        qosspec_t        qs; +}; + +struct vertex { +        struct list_head next; +        uint64_t         addr; +        struct list_head edges; +}; + +struct graph { +        size_t           nr_vertices; +        struct list_head vertices; +        pthread_mutex_t  lock; +}; + +struct graph * graph_create(void); + +void           graph_destroy(struct graph * graph); + +int            graph_add_edge(struct graph * graph, +                              uint64_t       s_addr, +                              uint64_t       d_addr, +                              qosspec_t      qs); + +int            graph_update_edge(struct graph * graph, +                                 uint64_t       s_addr, +                                 uint64_t       d_addr, +                                 qosspec_t      qs); + +int            graph_del_edge(struct graph * graph, +                              uint64_t       s_addr, +                              uint64_t       d_addr); + +#endif /* OUROBOROS_IPCPD_NORMAL_GRAPH_H */ diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index c41b6187..7acf3046 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -3,8 +3,8 @@   *   * Normal IPC Process   * - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> + *    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 @@ -24,7 +24,6 @@  #include <ouroboros/config.h>  #include <ouroboros/logs.h> -#include <ouroboros/dev.h>  #include <ouroboros/ipcp-dev.h>  #include <ouroboros/time_utils.h>  #include <ouroboros/irm.h> @@ -33,11 +32,10 @@  #include <ouroboros/errno.h>  #include "addr_auth.h" -#include "ae.h" +#include "connmgr.h"  #include "dir.h"  #include "enroll.h"  #include "fmgr.h" -#include "frct.h"  #include "ipcp.h"  #include "ribconfig.h"  #include "ribmgr.h" @@ -45,17 +43,11 @@  #include <stdbool.h>  #include <signal.h>  #include <stdlib.h> -#include <pthread.h>  #include <string.h>  #include <assert.h>  #include <inttypes.h> -#define THIS_TYPE    IPCP_NORMAL - -struct { -        pthread_t acceptor; -        struct addr_auth * auth; -} normal; +#define THIS_TYPE IPCP_NORMAL  void ipcp_sig_handler(int         sig,                        siginfo_t * info, @@ -83,54 +75,6 @@ void ipcp_sig_handler(int         sig,          }  } -static void * flow_acceptor(void * o) -{ -        int       fd; -        char *    ae_name; -        qosspec_t qs; - -        (void) o; - -        while (true) { -                pthread_rwlock_rdlock(&ipcpi.state_lock); - -                if (ipcp_get_state() != IPCP_OPERATIONAL) { -                        pthread_rwlock_unlock(&ipcpi.state_lock); -                        log_info("Shutting down flow acceptor."); -                        return 0; -                } - -                pthread_rwlock_unlock(&ipcpi.state_lock); - -                fd = flow_accept(&ae_name, &qs); -                if (fd < 0) { -                        if (fd != -EIRMD) -                                log_warn("Flow accept failed: %d", fd); -                        continue; -                } - -                log_dbg("New flow allocation request for AE %s.", ae_name); - -                if (strcmp(ae_name, ENROLL_AE) == 0) { -                        enroll_handle(fd); -                } else if (strcmp(ae_name, MGMT_AE) == 0) { -                        ribmgr_flow_arr(fd, qs); -                } else if (strcmp(ae_name, DT_AE) == 0) { -                        fmgr_nm1_flow_arr(fd, qs); -                } else { -                        log_dbg("Flow allocation request for unknown AE %s.", -                                ae_name); -                        if (flow_alloc_resp(fd, -1)) -                                log_warn("Failed to reply to flow allocation."); -                        flow_dealloc(fd); -                } - -                free(ae_name); -        } - -        return (void *) 0; -} -  /*   * Boots the IPCP off information in the rib.   * Common function after bootstrap or enroll. @@ -155,7 +99,7 @@ static int boot_components(void)          }          if (rib_add(MEMBERS_PATH, ipcpi.name)) { -                log_warn("Failed to add name to " MEMBERS_PATH); +                log_err("Failed to add name to " MEMBERS_PATH);                  return -1;          } @@ -164,67 +108,80 @@ static int boot_components(void)          if (rib_read(BOOT_PATH "/addr_auth/type", &pa, sizeof(pa))              != sizeof(pa)) {                  log_err("Failed to read policy for address authority."); +                connmgr_fini();                  return -1;          } -        normal.auth = addr_auth_create(pa); -        if (normal.auth == NULL) { +        if (addr_auth_init(pa)) {                  log_err("Failed to init address authority.");                  return -1;          } -        ipcpi.address = normal.auth->address(); -        if (ipcpi.address == 0) { +        ipcpi.dt_addr = addr_auth_address(); +        if (ipcpi.dt_addr == 0) {                  log_err("Failed to get a valid address."); -                addr_auth_destroy(normal.auth); +                addr_auth_fini();                  return -1;          } -        log_dbg("IPCP got address %" PRIu64 ".", ipcpi.address); +        log_dbg("IPCP got address %" PRIu64 ".", ipcpi.dt_addr);          log_dbg("Starting ribmgr.");          if (ribmgr_init()) {                  log_err("Failed to initialize RIB manager."); -                addr_auth_destroy(normal.auth); +                addr_auth_fini();                  return -1;          }          if (dir_init()) {                  log_err("Failed to initialize directory.");                  ribmgr_fini(); -                addr_auth_destroy(normal.auth); +                addr_auth_fini();                  return -1;          }          log_dbg("Ribmgr started."); -        if (fmgr_init()) { +        if (frct_init()) { +                dir_fini(); +                ribmgr_fini(); +                addr_auth_fini(); +                log_err("Failed to initialize FRCT."); +                return -1; +        } + +        if (fmgr_start()) { +                frct_fini();                  dir_fini();                  ribmgr_fini(); -                addr_auth_destroy(normal.auth); +                addr_auth_fini();                  log_err("Failed to start flow manager.");                  return -1;          } -        if (frct_init()) { -                fmgr_fini(); + +        if (enroll_start()) { +                fmgr_stop(); +                frct_fini();                  dir_fini();                  ribmgr_fini(); -                addr_auth_destroy(normal.auth); -                log_err("Failed to initialize FRCT."); +                addr_auth_fini(); +                log_err("Failed to start enroll.");                  return -1;          }          ipcp_set_state(IPCP_OPERATIONAL); -        if (pthread_create(&normal.acceptor, NULL, flow_acceptor, NULL)) { +        if (connmgr_start()) {                  ipcp_set_state(IPCP_INIT); -                fmgr_fini(); +                enroll_stop(); +                fmgr_stop(); +                frct_fini();                  dir_fini();                  ribmgr_fini(); -                addr_auth_destroy(normal.auth); -                log_err("Failed to create acceptor thread."); +                addr_auth_fini(); +                log_err("Failed to start AP connection manager.");                  return -1;          } @@ -233,18 +190,19 @@ static int boot_components(void)  void shutdown_components(void)  { -        pthread_cancel(normal.acceptor); -        pthread_join(normal.acceptor, NULL); +        connmgr_stop(); + +        enroll_stop();          frct_fini(); -        fmgr_fini(); +        fmgr_stop();          dir_fini();          ribmgr_fini(); -        addr_auth_destroy(normal.auth); +        addr_auth_fini();  }  static int normal_ipcp_enroll(char * dst_name) @@ -339,11 +297,6 @@ int normal_rib_init(void)  static int normal_ipcp_bootstrap(struct dif_config * conf)  { -        /* FIXME: get CACEP policies from conf */ -        enum pol_cacep pol = NO_AUTH; - -        (void) pol; -          assert(conf);          assert(conf->type == THIS_TYPE); @@ -391,12 +344,6 @@ static int normal_ipcp_bootstrap(struct dif_config * conf)              rib_write(BOOT_PATH "/rm/gam/type",                        &conf->rm_gam_type,                        sizeof(conf->rm_gam_type)) || -            rib_write(BOOT_PATH "/rm/gam/cacep", -                      &pol, -                      sizeof(pol)) || -            rib_write(BOOT_PATH "/dt/gam/cacep", -                      &pol, -                      sizeof(pol)) ||              rib_write(BOOT_PATH "/addr_auth/type",                        &conf->addr_auth_type,                        sizeof(conf->addr_auth_type))) { @@ -424,9 +371,9 @@ static struct ipcp_ops normal_ops = {          .ipcp_name_reg        = dir_name_reg,          .ipcp_name_unreg      = dir_name_unreg,          .ipcp_name_query      = dir_name_query, -        .ipcp_flow_alloc      = NULL, /* fmgr_np1_alloc, */ -        .ipcp_flow_alloc_resp = NULL, /* fmgr_np1_alloc_resp, */ -        .ipcp_flow_dealloc    = NULL, /* fmgr_np1_dealloc */ +        .ipcp_flow_alloc      = fmgr_np1_alloc, +        .ipcp_flow_alloc_resp = fmgr_np1_alloc_resp, +        .ipcp_flow_dealloc    = fmgr_np1_dealloc  };  int main(int    argc, @@ -473,11 +420,44 @@ int main(int    argc,                  exit(EXIT_FAILURE);          } +        if (connmgr_init()) { +                log_err("Failed to initialize connection manager."); +                ipcp_create_r(getpid(), -1); +                rib_fini(); +                irm_unbind_api(getpid(), ipcpi.name); +                ipcp_fini(); +                exit(EXIT_FAILURE); +        } + +        if (enroll_init()) { +                log_err("Failed to initialize enroll component."); +                ipcp_create_r(getpid(), -1); +                connmgr_fini(); +                rib_fini(); +                irm_unbind_api(getpid(), ipcpi.name); +                ipcp_fini(); +                exit(EXIT_FAILURE); +        } + +        if (fmgr_init()) { +                log_err("Failed to initialize flow manager component."); +                ipcp_create_r(getpid(), -1); +                enroll_fini(); +                connmgr_fini(); +                rib_fini(); +                irm_unbind_api(getpid(), ipcpi.name); +                ipcp_fini(); +                exit(EXIT_FAILURE); +        } +          pthread_sigmask(SIG_BLOCK, &sigset, NULL);          if (ipcp_boot() < 0) {                  log_err("Failed to boot IPCP.");                  ipcp_create_r(getpid(), -1); +                fmgr_fini(); +                enroll_fini(); +                connmgr_fini();                  rib_fini();                  irm_unbind_api(getpid(), ipcpi.name);                  ipcp_fini(); @@ -490,6 +470,9 @@ int main(int    argc,                  log_err("Failed to notify IRMd we are initialized.");                  ipcp_set_state(IPCP_NULL);                  ipcp_shutdown(); +                fmgr_fini(); +                enroll_fini(); +                connmgr_fini();                  rib_fini();                  irm_unbind_api(getpid(), ipcpi.name);                  ipcp_fini(); @@ -501,6 +484,12 @@ int main(int    argc,          if (ipcp_get_state() == IPCP_SHUTDOWN)                  shutdown_components(); +        fmgr_fini(); + +        enroll_fini(); + +        connmgr_fini(); +          rib_fini();          irm_unbind_api(getpid(), ipcpi.name); diff --git a/src/ipcpd/normal/neighbors.c b/src/ipcpd/normal/neighbors.c new file mode 100644 index 00000000..66da0462 --- /dev/null +++ b/src/ipcpd/normal/neighbors.c @@ -0,0 +1,213 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Data transfer neighbors + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define OUROBOROS_PREFIX "neighbors" + +#include <ouroboros/config.h> +#include <ouroboros/shared.h> +#include <ouroboros/ipcp-dev.h> +#include <ouroboros/errno.h> +#include <ouroboros/logs.h> + +#include "neighbors.h" + +#include <stdlib.h> +#include <assert.h> +#include <inttypes.h> + +static void notify_listeners(enum nb_event event, +                             struct nb *   nb, +                             struct nbs *  nbs) +{ +        struct list_head * p = NULL; + +        list_for_each(p, &nbs->notifiers) { +                struct nb_notifier * e = +                        list_entry(p, struct nb_notifier, next); +                if (e->notify_call(event, nb->conn)) +                        log_err("Listener reported an error."); +        } +} + +struct nbs * nbs_create(void) +{ +        struct nbs * nbs; + +        nbs = malloc(sizeof(*nbs)); +        if (nbs == NULL) +                return NULL; + +        list_head_init(&nbs->list); +        list_head_init(&nbs->notifiers); + +        if (pthread_mutex_init(&nbs->list_lock, NULL)) +                return NULL; + +        if (pthread_mutex_init(&nbs->notifiers_lock, NULL)) { +                pthread_mutex_destroy(&nbs->list_lock); +                return NULL; +        } + +        return nbs; +} + +void nbs_destroy(struct nbs * nbs) +{ +        struct list_head * p = NULL; +        struct list_head * n = NULL; + +        assert(nbs); + +        pthread_mutex_lock(&nbs->list_lock); + +        list_for_each_safe(p, n, &nbs->list) { +                struct nb * e = list_entry(p, struct nb, next); +                list_del(&e->next); +                free(e); +        } + +        pthread_mutex_unlock(&nbs->list_lock); + +        pthread_mutex_destroy(&nbs->list_lock); +        pthread_mutex_destroy(&nbs->notifiers_lock); +} + +int nbs_add(struct nbs * nbs, +            struct conn  conn) +{ +        struct nb * nb; + +        assert(nbs); + +        nb = malloc(sizeof(*nb)); +        if (nb == NULL) +                return -ENOMEM; + +        nb->conn = conn; + +        list_head_init(&nb->next); + +        pthread_mutex_lock(&nbs->list_lock); + +        list_add(&nb->next, &nbs->list); + +        notify_listeners(NEIGHBOR_ADDED, nb, nbs); + +        pthread_mutex_unlock(&nbs->list_lock); + +        log_info("Added neighbor with fd %d and address %" PRIu64 " to list.", +                 conn.flow_info.fd, conn.conn_info.addr); + +        return 0; +} + +int nbs_update_qos(struct nbs * nbs, +                   int          fd, +                   qosspec_t    qs) +{ +        struct list_head * p = NULL; + +        assert(nbs); + +        pthread_mutex_lock(&nbs->list_lock); + +        list_for_each(p, &nbs->list) { +                struct nb * e = list_entry(p, struct nb, next); +                if (e->conn.flow_info.fd == fd) { +                        e->conn.flow_info.qs = qs; + +                        notify_listeners(NEIGHBOR_QOS_CHANGE, e, nbs); + +                        pthread_mutex_unlock(&nbs->list_lock); +                        return 0; +                } +        } + +        pthread_mutex_unlock(&nbs->list_lock); + +        return -1; +} + +int nbs_del(struct nbs * nbs, +            int          fd) +{ +        struct list_head * p = NULL; +        struct list_head * n = NULL; + +        assert(nbs); + +        pthread_mutex_lock(&nbs->list_lock); + +        list_for_each_safe(p, n, &nbs->list) { +                struct nb * e = list_entry(p, struct nb, next); +                if (e->conn.flow_info.fd == fd) { +                        notify_listeners(NEIGHBOR_REMOVED, e, nbs); +                        list_del(&e->next); +                        free(e); +                        pthread_mutex_unlock(&nbs->list_lock); +                        return 0; +                } +        } + +        pthread_mutex_unlock(&nbs->list_lock); + +        return -1; +} + +int nbs_reg_notifier(struct nbs *         nbs, +                     struct nb_notifier * notify) +{ +        assert(nbs); +        assert(notify); + +        pthread_mutex_lock(&nbs->notifiers_lock); + +        list_head_init(¬ify->next); +        list_add(¬ify->next, &nbs->notifiers); + +        pthread_mutex_unlock(&nbs->notifiers_lock); + +        return 0; +} + +int nbs_unreg_notifier(struct nbs *         nbs, +                       struct nb_notifier * notify) +{ +        struct list_head * p = NULL; +        struct list_head * n = NULL; + +        pthread_mutex_lock(&nbs->notifiers_lock); + +        list_for_each_safe(p, n, &nbs->notifiers) { +                struct nb_notifier * e = +                        list_entry(p, struct nb_notifier, next); +                if (e == notify) { +                        list_del(&e->next); +                        pthread_mutex_unlock(&nbs->notifiers_lock); +                        return 0; +                } +        } + +        pthread_mutex_unlock(&nbs->notifiers_lock); + +        return -1; +} diff --git a/src/ipcpd/normal/neighbors.h b/src/ipcpd/normal/neighbors.h new file mode 100644 index 00000000..8714a9aa --- /dev/null +++ b/src/ipcpd/normal/neighbors.h @@ -0,0 +1,81 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Data transfer neighbors + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_NEIGHBORS_H +#define OUROBOROS_IPCPD_NORMAL_NEIGHBORS_H + +#include <ouroboros/irm_config.h> +#include <ouroboros/list.h> +#include <ouroboros/qos.h> +#include <ouroboros/fqueue.h> +#include <ouroboros/cacep.h> + +#include "connmgr.h" + +enum nb_event { +        NEIGHBOR_ADDED, +        NEIGHBOR_REMOVED, +        NEIGHBOR_QOS_CHANGE +}; + +typedef int (* nb_notify_t)(enum nb_event event, +                            struct conn   conn); + +struct nb_notifier { +        struct list_head next; +        nb_notify_t      notify_call; +}; + +struct nb { +        struct list_head next; +        struct conn      conn; +}; + +struct nbs { +        struct list_head notifiers; +        pthread_mutex_t  notifiers_lock; + +        struct list_head list; +        pthread_mutex_t  list_lock; +}; + +struct nbs * nbs_create(void); + +void         nbs_destroy(struct nbs * nbs); + +int          nbs_add(struct nbs * nbs, +                     struct conn  conn); + +int          nbs_update_qos(struct nbs * nbs, +                            int          fd, +                            qosspec_t    qs); + +int          nbs_del(struct nbs * nbs, +                     int          fd); + +int          nbs_reg_notifier(struct nbs *         nbs, +                              struct nb_notifier * notify); + +int          nbs_unreg_notifier(struct nbs *         nbs, +                                struct nb_notifier * notify); + +#endif diff --git a/src/ipcpd/normal/pff.c b/src/ipcpd/normal/pff.c index 2f7d554b..8cab7936 100644 --- a/src/ipcpd/normal/pff.c +++ b/src/ipcpd/normal/pff.c @@ -3,7 +3,8 @@   *   * PDU Forwarding Function   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -55,15 +56,16 @@ struct pff * pff_create(void)          return tmp;  } -int pff_destroy(struct pff * instance) +void pff_destroy(struct pff * instance)  {          assert(instance); +        pthread_mutex_lock(&instance->lock);          htable_destroy(instance->table); +        pthread_mutex_unlock(&instance->lock); +          pthread_mutex_destroy(&instance->lock);          free(instance); - -        return 0;  }  int pff_add(struct pff * instance, uint64_t addr, int fd) diff --git a/src/ipcpd/normal/pff.h b/src/ipcpd/normal/pff.h index b4a1400b..667c341e 100644 --- a/src/ipcpd/normal/pff.h +++ b/src/ipcpd/normal/pff.h @@ -3,8 +3,8 @@   *   * PDU Forwarding Function   * - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> + *    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 @@ -25,8 +25,6 @@  #include <stdint.h> -struct pff; -  /*   * PFF will take a type in the future,   * to allow different policies. @@ -34,7 +32,7 @@ struct pff;   */  struct pff * pff_create(void); -int          pff_destroy(struct pff * instance); +void         pff_destroy(struct pff * instance);  int          pff_add(struct pff * instance,                       uint64_t     addr, diff --git a/src/ipcpd/normal/pol-addr-auth-ops.h b/src/ipcpd/normal/pol-addr-auth-ops.h new file mode 100644 index 00000000..f0f473ef --- /dev/null +++ b/src/ipcpd/normal/pol-addr-auth-ops.h @@ -0,0 +1,34 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Address authority policy ops + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_POL_ADDR_AUTH_OPS_H +#define OUROBOROS_IPCPD_NORMAL_POL_ADDR_AUTH_OPS_H + +struct pol_addr_auth_ops { +        int      (* init)(void); + +        int      (* fini)(void); + +        uint64_t (* address)(void); +}; + +#endif /* OUROBOROS_IPCPD_NORMAL_POL_ADDR_AUTH_OPS_H */ diff --git a/src/ipcpd/normal/pol-gam-ops.h b/src/ipcpd/normal/pol-gam-ops.h index 0721136c..cfe9cbc3 100644 --- a/src/ipcpd/normal/pol-gam-ops.h +++ b/src/ipcpd/normal/pol-gam-ops.h @@ -3,8 +3,8 @@   *   * Graph adjacency manager policy ops   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 @@ -24,21 +24,13 @@  #define OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H  #include <ouroboros/cacep.h> +#include <ouroboros/qos.h>  struct pol_gam_ops { -        void * (* create)(struct gam * instance); +        void * (* create)(struct nbs * nbs, +                          struct ae *  ae);          void   (* destroy)(void * o); - -        int    (* start)(void * o); - -        int    (* stop)(void * o); - -        int    (* accept_new_flow)(void * o); - -        int    (* accept_flow)(void *                    o, -                               qosspec_t                 qs, -                               const struct cacep_info * info);  };  #endif /* OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H */ diff --git a/src/ipcpd/normal/pol/complete.c b/src/ipcpd/normal/pol/complete.c index 5faa1ae8..1f3f6031 100644 --- a/src/ipcpd/normal/pol/complete.c +++ b/src/ipcpd/normal/pol/complete.c @@ -1,10 +1,10 @@  /*   * Ouroboros - Copyright (C) 2016 - 2017   * - * Graph adjacency manager for IPC Process components + * Sets up a complete graph   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 @@ -20,35 +20,54 @@   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ -#define OUROBOROS_PREFIX "complete-graph-adjacency-manager" +#define OUROBOROS_PREFIX "complete"  #include <ouroboros/config.h> -#include <ouroboros/logs.h> -#include <ouroboros/list.h> -#include <ouroboros/qos.h> +#include <ouroboros/shared.h>  #include <ouroboros/rib.h> +#include <ouroboros/dev.h> +#include <ouroboros/logs.h> +#include <ouroboros/errno.h> +#include <ouroboros/cacep.h> -#include "ipcp.h" -#include "gam.h" +#include "neighbors.h" +#include "frct.h"  #include "ribconfig.h" +#include "ipcp.h" +#include "ae.h"  #include <string.h>  #include <stdlib.h>  #include <assert.h> -struct neighbor { -        struct list_head next; -        char *           neighbor; +struct complete { +        struct nbs * nbs; +        struct ae *  ae; +        pthread_t    allocator; +        pthread_t    listener;  }; -struct complete { -        struct list_head neighbors; -        pthread_mutex_t  neighbors_lock; +static void * listener(void * o) +{ +        struct complete * complete; +        struct conn       conn; -        pthread_t        allocator; +        complete = (struct complete *) o; -        struct gam *     gam; -}; +        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 * allocator(void * o)  { @@ -56,19 +75,37 @@ static void * allocator(void * o)          ssize_t           len;          char **           children;          ssize_t           i; -        struct complete * complete = (struct complete *) o; +        struct complete * complete; +        struct conn       conn; -        assert(complete); -        assert(complete->gam); +        complete = (struct complete *) o;          qs.delay = 0;          qs.jitter = 0; +        /* FIXME: implement QoS specs */ +        qs.cube = QOS_CUBE_BE; +          /* FIXME: subscribe to members to keep the graph complete. */          len = rib_children("/" MEMBERS_NAME, &children);          for (i = 0; i < len; ++i) { -                if (strcmp(children[i], ipcpi.name) < 0) -                        gam_flow_alloc(complete->gam, children[i], qs); +                if (strcmp(children[i], ipcpi.name) < 0) { +                        if (connmgr_alloc(complete->ae, +                                          children[i], +                                          &qs, +                                          &conn)) { +                                log_warn("Failed to get a 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]);          } @@ -78,123 +115,41 @@ static void * allocator(void * o)          return (void *) 0;  } -void * complete_create(struct gam * gam) +void * complete_create(struct nbs * nbs, +                       struct ae *  ae)  {          struct complete * complete; -        assert(gam); -          complete = malloc(sizeof(*complete));          if (complete == NULL)                  return NULL; -        list_head_init(&complete->neighbors); -        complete->gam = gam; - -        if (pthread_mutex_init(&complete->neighbors_lock, NULL)) { -                free(complete); -                return NULL; -        } - -        return (void *) complete; -} - -int complete_start(void * o) -{ -        struct complete * complete = (struct complete *) o; - -        assert(complete); -        assert(complete->gam); +        complete->nbs = nbs; +        complete->ae = ae;          if (pthread_create(&complete->allocator, NULL, -                           allocator, (void *) complete)) { -                pthread_mutex_destroy(&complete->neighbors_lock); -                free(complete); -                return -1; -        } +                           allocator, (void *) complete)) +                return NULL; -        /* FIXME: Handle flooding of the flow allocator before detaching.*/ -        pthread_join(complete->allocator, NULL); +        if (pthread_create(&complete->listener, NULL, +                           listener, (void *) complete)) +                return NULL; -        return 0; +        return complete;  } -int complete_stop(void * o) +void complete_destroy(void * ops_o)  { -        (void) o; +        struct complete * complete; -        return 0; -} +        assert(ops_o); -void complete_destroy(void * o) -{ -        struct list_head * p = NULL; -        struct list_head * n = NULL; -        struct complete * complete = (struct complete *) o; - -        list_for_each_safe(p, n, &complete->neighbors) { -                struct neighbor * e = list_entry(p, struct neighbor, next); -                list_del(&e->next); -                free(e->neighbor); -                free(e); -        } +        complete = (struct complete *) ops_o; -        pthread_mutex_destroy(&complete->neighbors_lock); +        pthread_cancel(complete->allocator); +        pthread_cancel(complete->listener); +        pthread_join(complete->allocator, NULL); +        pthread_join(complete->listener, NULL);          free(complete);  } - -int complete_accept_new_flow(void * o) -{ -        (void) o; - -        return 0; -} - -int complete_accept_flow(void *                    o, -                         qosspec_t                 qs, -                         const struct cacep_info * info) -{ -        struct list_head * pos = NULL; -        struct neighbor * n; -        struct complete * complete = (struct complete *) o; - -        (void) qs; - -        assert(complete); - -        pthread_mutex_lock(&complete->neighbors_lock); - -        list_for_each(pos, &complete->neighbors) { -                struct neighbor * e = list_entry(pos, struct neighbor, next); -                if (strcmp(e->neighbor, info->name) == 0) { -                        pthread_mutex_unlock(&complete->neighbors_lock); -                        return -1; -                } - -                assert(complete); -                assert(&complete->neighbors_lock); -                assert(pos->nxt); -        } - -        n = malloc(sizeof(*n)); -        if (n == NULL) { -                pthread_mutex_unlock(&complete->neighbors_lock); -                return -1; -        } - -        list_head_init(&n->next); - -        n->neighbor = strdup(info->name); -        if (n->neighbor == NULL) { -                pthread_mutex_unlock(&complete->neighbors_lock); -                free(n); -                return -1; -        } - -        list_add(&n->next, &complete->neighbors); - -        pthread_mutex_unlock(&complete->neighbors_lock); - -        return 0; -} diff --git a/src/ipcpd/normal/pol/complete.h b/src/ipcpd/normal/pol/complete.h index 3f08c2e5..46a535c2 100644 --- a/src/ipcpd/normal/pol/complete.h +++ b/src/ipcpd/normal/pol/complete.h @@ -1,10 +1,10 @@  /*   * Ouroboros - Copyright (C) 2016 - 2017   * - * Graph adjacency manager for IPC Process components + * Sets up a complete graph   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 @@ -23,30 +23,19 @@  #ifndef OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H  #define OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H -#include "gam.h" -#include "pol-gam-ops.h" - -void * complete_create(struct gam * instance); - -void   complete_destroy(void * o); +#include <ouroboros/irm_config.h> +#include <ouroboros/qos.h> -int    complete_start(void * o); - -int    complete_stop(void * o); +#include "pol-gam-ops.h" -int    complete_accept_new_flow(void * o); +void * complete_create(struct nbs * nbs, +                       struct ae *  ae); -int    complete_accept_flow(void *                    o, -                            qosspec_t                 qs, -                            const struct cacep_info * info); +void   complete_destroy(void * ops_o);  struct pol_gam_ops complete_ops = { -        .create          = complete_create, -        .destroy         = complete_destroy, -        .start           = complete_start, -        .stop            = complete_stop, -        .accept_new_flow = complete_accept_new_flow, -        .accept_flow     = complete_accept_flow +        .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 d982f5ac..e709da7c 100644 --- a/src/ipcpd/normal/pol/flat.c +++ b/src/ipcpd/normal/pol/flat.c @@ -3,8 +3,8 @@   *   * Policy for flat addresses in a distributed way   * - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> + *    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 @@ -80,6 +80,16 @@ static int addr_taken(char *  name,  #define INVALID_ADDRESS 0 +int flat_init(void) +{ +        return 0; +} + +int flat_fini(void) +{ +        return 0; +} +  uint64_t flat_address(void)  {          struct timespec t; diff --git a/src/ipcpd/normal/pol/flat.h b/src/ipcpd/normal/pol/flat.h index 73d7de8b..d45a89cd 100644 --- a/src/ipcpd/normal/pol/flat.h +++ b/src/ipcpd/normal/pol/flat.h @@ -3,7 +3,8 @@   *   * Policy for flat addresses in a distributed way   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -22,8 +23,16 @@  #ifndef OUROBOROS_IPCPD_NORMAL_FLAT_H  #define OUROBOROS_IPCPD_NORMAL_FLAT_H +#include "pol-addr-auth-ops.h" +  int      flat_init(void);  int      flat_fini(void);  uint64_t flat_address(void); +struct pol_addr_auth_ops flat_ops = { +        .init    = flat_init, +        .fini    = flat_fini, +        .address = flat_address +}; +  #endif /* OUROBOROS_IPCPD_NORMAL_FLAT_H */ diff --git a/src/ipcpd/normal/ribconfig.h b/src/ipcpd/normal/ribconfig.h index 15b65ce2..5ecdaab3 100644 --- a/src/ipcpd/normal/ribconfig.h +++ b/src/ipcpd/normal/ribconfig.h @@ -31,9 +31,11 @@  #define MEMBERS_NAME     "members"  #define DIF_NAME         "dif_name"  #define DIR_NAME         "directory" +#define ROUTING_NAME     "fsdb"  #define DIF_PATH         DLR DIF_NAME  #define DIR_PATH         DLR DIR_NAME  #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 f254bd50..ec465c6b 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -3,8 +3,8 @@   *   * RIB manager of the IPC Process   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 @@ -45,35 +45,70 @@  #include <assert.h>  struct { -        flow_set_t *   fs; -        fqueue_t *     fq; -        struct gam *   gam; +        flow_set_t *       fs; +        fqueue_t *         fq; + +        struct gam *       gam; +        struct nbs *       nbs; +        struct ae *        ae; + +        struct nb_notifier nb_notifier;  } ribmgr; +static int ribmgr_neighbor_event(enum nb_event event, +                                 struct conn   conn) +{ +        /* We are only interested in neighbors being added and removed. */ +        switch (event) { +        case NEIGHBOR_ADDED: +                flow_set_add(ribmgr.fs, conn.flow_info.fd); +                break; +        case NEIGHBOR_REMOVED: +                flow_set_del(ribmgr.fs, conn.flow_info.fd); +                break; +        default: +                break; +        } + +        return 0; +}  int ribmgr_init(void)  { -        enum pol_cacep pc; -        enum pol_gam   pg; +        enum pol_gam     pg; +        struct conn_info info; -        if (rib_read(BOOT_PATH "/rm/gam/type", &pg, sizeof(pg)) -            != sizeof(pg)) { -                log_err("Failed to read policy for ribmgr gam."); +        strcpy(info.ae_name, MGMT_AE); +        strcpy(info.protocol, CDAP_PROTO); +        info.pref_version = 1; +        info.pref_syntax = PROTO_GPB; + +        ribmgr.nbs = nbs_create(); +        if (ribmgr.nbs == NULL) { +                log_err("Failed to create neighbors.");                  return -1;          } -        if (rib_read(BOOT_PATH "/rm/gam/cacep", &pc, sizeof(pc)) -            != sizeof(pc)) { -                log_err("Failed to read CACEP policy for ribmgr gam."); +        ribmgr.ae = connmgr_ae_create(info); +        if (ribmgr.ae == NULL) { +                log_err("Failed to create AE struct."); +                nbs_destroy(ribmgr.nbs);                  return -1;          } -        /* FIXME: Implement cacep policies */ -        (void) pc; +        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; +        } -        ribmgr.gam = gam_create(pg, MGMT_AE); +        ribmgr.gam = gam_create(pg, ribmgr.nbs, ribmgr.ae);          if (ribmgr.gam == NULL) {                  log_err("Failed to create gam."); +                connmgr_ae_destroy(ribmgr.ae); +                nbs_destroy(ribmgr.nbs);                  return -1;          } @@ -81,6 +116,8 @@ int ribmgr_init(void)          if (ribmgr.fs == NULL) {                  log_err("Failed to create flow set.");                  gam_destroy(ribmgr.gam); +                connmgr_ae_destroy(ribmgr.ae); +                nbs_destroy(ribmgr.nbs);                  return -1;          } @@ -89,6 +126,19 @@ int ribmgr_init(void)                  log_err("Failed to create fq.");                  flow_set_destroy(ribmgr.fs);                  gam_destroy(ribmgr.gam); +                connmgr_ae_destroy(ribmgr.ae); +                nbs_destroy(ribmgr.nbs); +                return -1; +        } + +        ribmgr.nb_notifier.notify_call = ribmgr_neighbor_event; +        if (nbs_reg_notifier(ribmgr.nbs, &ribmgr.nb_notifier)) { +                log_err("Failed to register notifier."); +                fqueue_destroy(ribmgr.fq); +                flow_set_destroy(ribmgr.fs); +                gam_destroy(ribmgr.gam); +                connmgr_ae_destroy(ribmgr.ae); +                nbs_destroy(ribmgr.nbs);                  return -1;          } @@ -97,20 +147,12 @@ int ribmgr_init(void)  void ribmgr_fini(void)  { +        nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier);          flow_set_destroy(ribmgr.fs);          fqueue_destroy(ribmgr.fq);          gam_destroy(ribmgr.gam); -} - -int ribmgr_flow_arr(int       fd, -                    qosspec_t qs) -{ -        assert(ribmgr.gam); - -        if (gam_flow_arr(ribmgr.gam, fd, qs)) -                return -1; - -        return 0; +        connmgr_ae_destroy(ribmgr.ae); +        nbs_destroy(ribmgr.nbs);  }  int ribmgr_disseminate(char *           path, diff --git a/src/ipcpd/normal/ribmgr.h b/src/ipcpd/normal/ribmgr.h index 12f407ab..8922688a 100644 --- a/src/ipcpd/normal/ribmgr.h +++ b/src/ipcpd/normal/ribmgr.h @@ -3,7 +3,8 @@   *   * RIB manager of the IPC Process   * - *    Sander Vrijders <sander.vrijders@intec.ugent.be> + *    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 @@ -41,9 +42,6 @@ int  ribmgr_init(void);  void ribmgr_fini(void); -int  ribmgr_flow_arr(int       fd, -                     qosspec_t qs); -  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 new file mode 100644 index 00000000..0b82b70d --- /dev/null +++ b/src/ipcpd/normal/routing.c @@ -0,0 +1,302 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Routing component of the IPCP + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define OUROBOROS_PREFIX "routing" + +#include <ouroboros/config.h> +#include <ouroboros/errno.h> +#include <ouroboros/list.h> +#include <ouroboros/logs.h> +#include <ouroboros/rib.h> +#include <ouroboros/rqueue.h> + +#include "routing.h" +#include "ribmgr.h" +#include "ribconfig.h" +#include "ipcp.h" +#include "graph.h" + +#include <assert.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> + +#include "fso.pb-c.h" +typedef Fso fso_t; + +#define BUF_SIZE 256 + +struct routing_table_entry { +        struct list_head next; +        uint64_t         dst; +        uint64_t         nhop; +}; + +struct routing_i { +        struct pff * pff; +}; + +struct { +        struct nbs *       nbs; +        struct nb_notifier nb_notifier; + +        struct graph *     graph; + +        ro_set_t *         set; +        rqueue_t *         queue; +        pthread_t          rib_listener; +} routing; + +struct routing_i * routing_i_create(struct pff * pff) +{ +        struct routing_i * tmp; + +        assert(pff); + +        tmp = malloc(sizeof(*tmp)); +        if (tmp == NULL) +                return NULL; + +        tmp->pff = pff; + +        return tmp; +} + +void routing_i_destroy(struct routing_i * instance) +{ +        assert(instance); + +        free(instance); +} + +static int routing_neighbor_event(enum nb_event event, +                                  struct conn   conn) +{ +        char      path[RIB_MAX_PATH_LEN + 1]; +        char      fso_name[RIB_MAX_PATH_LEN + 1]; +        fso_t     fso = FSO__INIT; +        size_t    len; +        uint8_t * data; + +        sprintf(fso_name, "%" PRIx64 "-%" PRIx64, +                ipcpi.dt_addr, conn.conn_info.addr); +        rib_path_append(rib_path_append(path, ROUTING_PATH), fso_name); + +        switch (event) { +        case NEIGHBOR_ADDED: +                fso.s_addr = ipcpi.dt_addr; +                fso.d_addr = conn.conn_info.addr; + +                len = fso__get_packed_size(&fso); +                if (len == 0) +                        return -1; + +                data = malloc(len); +                if (data == NULL) +                        return -1; + +                fso__pack(&fso, data); + +                if (rib_add(ROUTING_PATH, fso_name)) { +                        log_err("Failed to add FSO."); +                        free(data); +                        return -1; +                } + +                if (rib_put(path, data, len)) { +                        log_err("Failed to put FSO in RIB."); +                        rib_del(path); +                        free(data); +                        return -1; +                } + +                log_dbg("Added %s to RIB.", path); + +                break; +        case NEIGHBOR_REMOVED: +                if (rib_del(path)) { +                        log_err("Failed to remove FSO."); +                        return -1; +                } + +                log_dbg("Removed %s from RIB.", path); + +                break; +        case NEIGHBOR_QOS_CHANGE: +                log_info("Not currently supported."); +                break; +        default: +                log_info("Unsupported event for routing."); +                break; +        } + +        return 0; +} + +static int read_fso(char *  path, +                    int32_t flag) +{ +        ssize_t   len; +        uint8_t   ro[BUF_SIZE]; +        fso_t *   fso; +        qosspec_t qs; + +        len = rib_read(path, ro, BUF_SIZE); +        if (len < 0) { +                log_err("Failed to read FSO."); +                return -1; +        } + +        fso = fso__unpack(NULL, len, ro); +        if (fso == NULL) { +                log_err("Failed to unpack."); +                return -1; +        } + +        if (flag & RO_CREATE) { +                if (graph_add_edge(routing.graph, +                                   fso->s_addr, fso->d_addr, qs)) { +                        log_err("Failed to add edge to graph."); +                        fso__free_unpacked(fso, NULL); +                        return -1; +                } +        } else if (flag & RO_MODIFY) { +                if (graph_update_edge(routing.graph, +                                      fso->s_addr, fso->d_addr, qs)) { +                        log_err("Failed to update edge of graph."); +                        fso__free_unpacked(fso, NULL); +                        return -1; +                } +        } else if (flag & RO_DELETE) { +                if (graph_del_edge(routing.graph, fso->s_addr, fso->d_addr)) { +                        log_err("Failed to del edge of graph."); +                        fso__free_unpacked(fso, NULL); +                        return -1; +                } +        } + +        fso__free_unpacked(fso, NULL); + +        return 0; +} + +static void * rib_listener(void * o) +{ +        int32_t flag; +        char    path[RIB_MAX_PATH_LEN + 1]; +        char ** children; +        ssize_t len; +        int     i; + +        (void) o; + +        if (ro_set_add(routing.set, ROUTING_PATH, +                       RO_MODIFY | RO_CREATE | RO_DELETE)) { +                log_err("Failed to add to RO set"); +                return (void * ) -1; +        } + +        len = rib_children(ROUTING_PATH, &children); +        if (len < 0) { +                log_err("Failed to retrieve children."); +                return (void *) -1; +        } + +        for (i = 0; i < len; i++) { +                if (read_fso(children[i], RO_CREATE)) { +                        log_err("Failed to parse FSO."); +                        continue; +                } +        } + +        while (rib_event_wait(routing.set, routing.queue, NULL)) { +                flag = rqueue_next(routing.queue, path); +                if (flag < 0) +                        continue; + +                if (read_fso(children[i], flag)) { +                        log_err("Failed to parse FSO."); +                        continue; +                } +        } + +        return (void *) 0; +} + +int routing_init(struct nbs * nbs) +{ +        routing.graph = graph_create(); +        if (routing.graph == NULL) +                return -1; + +        if (rib_add(RIB_ROOT, ROUTING_NAME)) { +                graph_destroy(routing.graph); +                return -1; +        } + +        routing.nbs = nbs; + +        routing.nb_notifier.notify_call = routing_neighbor_event; +        if (nbs_reg_notifier(routing.nbs, &routing.nb_notifier)) { +                graph_destroy(routing.graph); +                rib_del(ROUTING_PATH); +                return -1; +        } + +        routing.set = ro_set_create(); +        if (routing.set == NULL) { +                nbs_unreg_notifier(routing.nbs, &routing.nb_notifier); +                graph_destroy(routing.graph); +                rib_del(ROUTING_PATH); +                return -1; +        } + +        routing.queue = rqueue_create(); +        if (routing.queue == NULL) { +                ro_set_destroy(routing.set); +                nbs_unreg_notifier(routing.nbs, &routing.nb_notifier); +                graph_destroy(routing.graph); +                rib_del(ROUTING_PATH); +                return -1; +        } + +        pthread_create(&routing.rib_listener, NULL, rib_listener, NULL); + +        return 0; +} + +void routing_fini(void) +{ +        pthread_cancel(routing.rib_listener); + +        pthread_join(routing.rib_listener, NULL); + +        rqueue_destroy(routing.queue); + +        ro_set_destroy(routing.set); + +        graph_destroy(routing.graph); + +        rib_del(ROUTING_PATH); + +        nbs_unreg_notifier(routing.nbs, &routing.nb_notifier); +} diff --git a/src/ipcpd/normal/routing.h b/src/ipcpd/normal/routing.h new file mode 100644 index 00000000..0794ef28 --- /dev/null +++ b/src/ipcpd/normal/routing.h @@ -0,0 +1,45 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Routing component of the IPCP + * + *    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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_ROUTING_H +#define OUROBOROS_IPCPD_NORMAL_ROUTING_H + +#include <ouroboros/qos.h> + +#include "pff.h" +#include "neighbors.h" + +#include <stdint.h> + +/* + * Routing will take a type in the future, + * to allow different policies. + */ +int                routing_init(struct nbs * nbs); + +void               routing_fini(void); + +struct routing_i * routing_i_create(struct pff * pff); + +void               routing_i_destroy(struct routing_i * instance); + +#endif /* OUROBOROS_IPCPD_NORMAL_ROUTING_H */ diff --git a/src/ipcpd/normal/shm_pci.c b/src/ipcpd/normal/shm_pci.c index 0807a24f..1170adff 100644 --- a/src/ipcpd/normal/shm_pci.c +++ b/src/ipcpd/normal/shm_pci.c @@ -3,8 +3,8 @@   *   * Protocol Control Information in Shared Memory Map   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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 diff --git a/src/ipcpd/normal/shm_pci.h b/src/ipcpd/normal/shm_pci.h index 17ce5cdd..0c54c883 100644 --- a/src/ipcpd/normal/shm_pci.h +++ b/src/ipcpd/normal/shm_pci.h @@ -3,8 +3,8 @@   *   * Protocol Control Information in Shared Memory Map   * - *    Dimitri Staessens <dimitri.staessens@intec.ugent.be> - *    Sander Vrijders   <sander.vrijders@intec.ugent.be> + *    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  | 
