diff options
| -rw-r--r-- | src/ipcpd/normal/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/ipcpd/normal/fso.proto | 29 | ||||
| -rw-r--r-- | src/ipcpd/normal/routing.c | 184 | 
3 files changed, 182 insertions, 34 deletions
| diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index 39ced7bc..06292c50 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -15,6 +15,7 @@ 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(FSO_SRCS FSO_HDRS fso.proto)  set(SOURCE_FILES    # Add source files here @@ -38,7 +39,7 @@ set(SOURCE_FILES    )  add_executable(ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES} -  ${FLOW_ALLOC_SRCS}) +  ${FLOW_ALLOC_SRCS} ${FSO_SRCS})  target_link_libraries(ipcpd-normal LINK_PUBLIC ouroboros)  include(AddCompileFlags) 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/routing.c b/src/ipcpd/normal/routing.c index 46c2be08..745d1812 100644 --- a/src/ipcpd/normal/routing.c +++ b/src/ipcpd/normal/routing.c @@ -27,6 +27,7 @@  #include <ouroboros/list.h>  #include <ouroboros/logs.h>  #include <ouroboros/rib.h> +#include <ouroboros/rqueue.h>  #include "routing.h"  #include "ribmgr.h" @@ -39,7 +40,10 @@  #include <inttypes.h>  #include <string.h> -#define ADDR_SIZE 30 +#include "fso.pb-c.h" +typedef Fso fso_t; + +#define BUF_SIZE 256  struct routing_table_entry {          struct list_head next; @@ -48,17 +52,18 @@ struct routing_table_entry {  };  struct routing_i { -        struct pff *     pff; -        struct list_head routing_table; +        struct pff * pff;  };  struct {          struct nbs *       nbs;          struct nb_notifier nb_notifier; -        char               fso_path[RIB_MAX_PATH_LEN + 1]; -          struct graph *     graph; + +        ro_set_t *         set; +        rqueue_t *         queue; +        pthread_t          rib_listener;  } routing;  struct routing_i * routing_i_create(struct pff * pff) @@ -73,8 +78,6 @@ struct routing_i * routing_i_create(struct pff * pff)          tmp->pff = pff; -        list_head_init(&tmp->routing_table); -          return tmp;  } @@ -88,24 +91,41 @@ void routing_i_destroy(struct routing_i * instance)  static int routing_neighbor_event(enum nb_event event,                                    struct conn   conn)  { -        char addr[ADDR_SIZE]; -        char path[RIB_MAX_PATH_LEN + 1]; +        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; -        strcpy(path, routing.fso_path); -        snprintf(addr, ADDR_SIZE, "%" PRIx64, conn.conn_info.addr); -        rib_path_append(path, addr); +        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: -                if (rib_add(routing.fso_path, addr)) { +                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_write(path, &conn.flow_info.qs, -                              sizeof(conn.flow_info.qs))) { -                        log_err("Failed to write qosspec to FSO."); +                if (rib_put(path, data, len)) { +                        log_err("Failed to put FSO in RIB.");                          rib_del(path); +                        free(data);                          return -1;                  } @@ -118,12 +138,7 @@ static int routing_neighbor_event(enum nb_event event,                  break;          case NEIGHBOR_QOS_CHANGE: -                if (rib_write(path, &conn.flow_info.qs, -                              sizeof(conn.flow_info.qs))) { -                        log_err("Failed to write qosspec to FSO."); -                        return -1; -                } - +                log_info("Not currently supported.");                  break;          default:                  log_info("Unsupported event for routing."); @@ -133,10 +148,98 @@ static int routing_neighbor_event(enum nb_event event,          return 0;  } -int routing_init(struct nbs * nbs) +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)  { -        char addr[ADDR_SIZE]; +        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; @@ -146,32 +249,47 @@ int routing_init(struct nbs * nbs)                  return -1;          } -        rib_path_append(routing.fso_path, ROUTING_NAME); - -        snprintf(addr, ADDR_SIZE, "%" PRIx64, ipcpi.dt_addr); +        routing.nbs = nbs; -        if (rib_add(routing.fso_path, addr)) { +        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;          } -        rib_path_append(routing.fso_path, addr); - -        routing.nbs = nbs; +        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.nb_notifier.notify_call = routing_neighbor_event; -        if (nbs_reg_notifier(routing.nbs, &routing.nb_notifier)) { +        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); | 
