From 15e9b779385c71d366776b83540e19e0735c4e66 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 11 Jan 2017 18:59:11 +0100 Subject: ipcpd: normal: Create policies for GAM This allows the selection of a policy for the graph adjacency manager. Currently we only support constructing a complete graph. --- src/ipcpd/ipcp.c | 1 + src/ipcpd/normal/CMakeLists.txt | 1 + src/ipcpd/normal/fmgr.c | 4 +- src/ipcpd/normal/gam.c | 136 ++++++++---------------- src/ipcpd/normal/gam.h | 8 +- src/ipcpd/normal/pol-gam-ops.h | 40 +++++++ src/ipcpd/normal/pol/complete.c | 208 +++++++++++++++++++++++++++++++++++++ src/ipcpd/normal/pol/complete.h | 46 ++++++++ src/ipcpd/normal/ribmgr.c | 13 ++- src/ipcpd/normal/ribmgr.h | 2 + src/ipcpd/normal/static_info.proto | 19 ++-- 11 files changed, 367 insertions(+), 111 deletions(-) create mode 100644 src/ipcpd/normal/pol-gam-ops.h create mode 100644 src/ipcpd/normal/pol/complete.c create mode 100644 src/ipcpd/normal/pol/complete.h (limited to 'src/ipcpd') diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 96f00dc0..a94e268d 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -128,6 +128,7 @@ static void * ipcp_main_loop(void * o) conf.min_pdu_size = conf_msg->min_pdu_size; conf.max_pdu_size = conf_msg->max_pdu_size; conf.addr_auth_type = conf_msg->addr_auth_type; + conf.dt_gam_type = conf_msg->dt_gam_type; } if (conf_msg->ipcp_type == IPCP_SHIM_UDP) { conf.ip_addr = conf_msg->ip_addr; diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index 43059c3e..157baa9e 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -36,6 +36,7 @@ set(SOURCE_FILES ribmgr.c shm_pci.c # Add policies last + pol/complete.c pol/flat.c ) diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 33ac83c9..6fe6fb60 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -305,7 +305,7 @@ int fmgr_init() } } - fmgr.gam = gam_create(DT_AE); + fmgr.gam = gam_create(ribmgr_dt_gam(), DT_AE); if (fmgr.gam == NULL) { LOG_ERR("Failed to create graph adjacency manager."); fmgr_destroy_flows(); @@ -617,7 +617,7 @@ int fmgr_nm1_flow_arr(int fd, assert(fmgr.gam); if (gam_flow_arr(fmgr.gam, fd, qs)) { - LOG_ERR("Failed to hand to connectivy manager."); + LOG_ERR("Failed to hand to graph adjacency manager."); return -1; } diff --git a/src/ipcpd/normal/gam.c b/src/ipcpd/normal/gam.c index 34db87e3..0e626115 100644 --- a/src/ipcpd/normal/gam.c +++ b/src/ipcpd/normal/gam.c @@ -3,7 +3,7 @@ * * Graph adjacency manager for IPC Process components * - * Dimitri Staeesens + * Dimitri Staessens * Sander Vrijders * * This program is free software; you can redistribute it and/or modify @@ -25,23 +25,20 @@ #include #include #include -#include #include #include #include "ribmgr.h" #include "ipcp.h" -#include "ro.h" -#include "pathname.h" #include "gam.h" +#include "pol-gam-ops.h" +#include "pol/complete.h" #include #include #include #include -#define RO_DIR "neighbors" - struct ga { struct list_head next; @@ -51,59 +48,34 @@ struct ga { }; struct gam { - struct list_head gas; - pthread_mutex_t gas_lock; - pthread_cond_t gas_cond; - - char * ae_name; + struct list_head gas; + pthread_mutex_t gas_lock; + pthread_cond_t gas_cond; - /* FIXME: Keep a list of known members */ + char * ae_name; - pthread_t allocator; + struct pol_gam_ops * ops; + void * ops_o; }; -static void * allocator(void * o) +struct gam * gam_create(enum pol_gam gam_type, + const char * ae_name) { - qosspec_t qs; - ssize_t len; - char ** children; - struct gam * instance; - int i; - char * ro_name; - - instance = (struct gam *) o; - - qs.delay = 0; - qs.jitter = 0; - - ro_name = pathname_create(RO_DIR); - if (ro_name == NULL) - return (void *) -1; - - len = ro_children(ro_name, &children); - if (len > 0) { - for (i = 0; i < len; i++) { - if (strcmp(children[i], ipcpi.name) == 0) - continue; - gam_flow_alloc(instance, children[i], qs); - } - } - - pathname_destroy(ro_name); - - return (void *) 0; -} - -struct gam * gam_create(char * ae_name) -{ - struct gam * tmp; - struct ro_attr attr; - char * ro_name; + struct gam * tmp; tmp = malloc(sizeof(*tmp)); if (tmp == NULL) return NULL; + switch (gam_type) { + case COMPLETE: + tmp->ops = &complete_ops; + break; + default: + free(tmp); + return NULL; + } + list_head_init(&tmp->gas); tmp->ae_name = strdup(ae_name); @@ -125,47 +97,8 @@ struct gam * gam_create(char * ae_name) return NULL; } - ro_attr_init(&attr); - attr.enrol_sync = true; - attr.recv_set = ALL_MEMBERS; - - ro_name = pathname_create(RO_DIR); - if (ro_name == NULL) { - pthread_mutex_destroy(&tmp->gas_lock); - free(tmp->ae_name); - free(tmp); - return NULL; - } - - if (!ro_exists(RO_DIR)) { - if (ro_create(ro_name, &attr, NULL, 0)) { - pathname_destroy(ro_name); - pthread_mutex_destroy(&tmp->gas_lock); - free(tmp->ae_name); - free(tmp); - return NULL; - } - } - - ro_name = pathname_append(ro_name, ipcpi.name); - if (ro_name == NULL) { - pathname_destroy(ro_name); - pthread_mutex_destroy(&tmp->gas_lock); - free(tmp->ae_name); - free(tmp); - return NULL; - } - - if (ro_create(ro_name, &attr, NULL, 0)) { - pathname_destroy(ro_name); - pthread_mutex_destroy(&tmp->gas_lock); - free(tmp->ae_name); - free(tmp); - return NULL; - } - pathname_destroy(ro_name); - - if (pthread_create(&tmp->allocator, NULL, allocator, (void *) tmp)) { + 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); @@ -183,8 +116,7 @@ void gam_destroy(struct gam * instance) assert(instance); - pthread_cancel(instance->allocator); - pthread_join(instance->allocator, NULL); + instance->ops->destroy(instance->ops_o); pthread_mutex_destroy(&instance->gas_lock); pthread_cond_destroy(&instance->gas_cond); @@ -232,7 +164,8 @@ int gam_flow_arr(struct gam * instance, struct cacep * cacep; struct cacep_info * info; - if (flow_alloc_resp(fd, 0) < 0) { + if (flow_alloc_resp(fd, instance->ops->accept_new_flow(instance->ops_o)) + < 0) { LOG_ERR("Could not respond to new flow."); return -1; } @@ -249,8 +182,15 @@ int gam_flow_arr(struct gam * instance, cacep_destroy(cacep); return -1; } + cacep_destroy(cacep); + if (instance->ops->accept_flow(instance->ops_o, qs, info)) { + flow_dealloc(fd); + free(info); + return 0; + } + if (add_ga(instance, fd, qs, info)) { LOG_ERR("Failed to add ga to graph adjacency manager list."); free(info); @@ -292,10 +232,17 @@ int gam_flow_alloc(struct gam * instance, cacep_destroy(cacep); return -1; } + cacep_destroy(cacep); + if (instance->ops->accept_flow(instance->ops_o, qs, info)) { + flow_dealloc(fd); + free(info); + return 0; + } + if (add_ga(instance, fd, qs, info)) { - LOG_ERR("Failed to add ga to graph adjacency manager list."); + LOG_ERR("Failed to add GA to graph adjacency manager list."); free(info); return -1; } @@ -322,7 +269,6 @@ int gam_flow_wait(struct gam * instance, ga = list_first_entry((&instance->gas), struct ga, next); if (ga == NULL) { pthread_mutex_unlock(&instance->gas_lock); - LOG_ERR("Ga was NULL."); return -1; } diff --git a/src/ipcpd/normal/gam.h b/src/ipcpd/normal/gam.h index 309cb46d..e858114c 100644 --- a/src/ipcpd/normal/gam.h +++ b/src/ipcpd/normal/gam.h @@ -23,8 +23,10 @@ #ifndef OUROBOROS_IPCPD_NORMAL_GAM_H #define OUROBOROS_IPCPD_NORMAL_GAM_H -/* FIXME: Will take a policy */ -struct gam * gam_create(char * ae_name); +#include + +struct gam * gam_create(enum pol_gam gam_type, + const char * ae_name); void gam_destroy(struct gam * instance); @@ -41,4 +43,4 @@ int gam_flow_wait(struct gam * instance, struct cacep_info ** info, qosspec_t * qs); -#endif +#endif /* OUROBOROS_IPCPD_NORMAL_GAM_H */ diff --git a/src/ipcpd/normal/pol-gam-ops.h b/src/ipcpd/normal/pol-gam-ops.h new file mode 100644 index 00000000..eeece8d9 --- /dev/null +++ b/src/ipcpd/normal/pol-gam-ops.h @@ -0,0 +1,40 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Graph adjacency manager policy ops + * + * Dimitri Staessens + * Sander Vrijders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H +#define OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H + +#include + +struct pol_gam_ops { + void * (* create)(struct gam * instance); + + void (* destroy)(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 new file mode 100644 index 00000000..89e1b91f --- /dev/null +++ b/src/ipcpd/normal/pol/complete.c @@ -0,0 +1,208 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Graph adjacency manager for IPC Process components + * + * Dimitri Staessens + * Sander Vrijders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define OUROBOROS_PREFIX "complete-graph-adjacency-manager" + +#include +#include +#include +#include + +#include "pathname.h" +#include "ro.h" +#include "ipcp.h" +#include "gam.h" + +#include +#include + +#define RO_DIR "neighbors" + +struct neighbor { + struct list_head next; + char * neighbor; +}; + +struct complete { + struct list_head neighbors; + pthread_mutex_t neighbors_lock; + + pthread_t allocator; + + struct gam * gam; +}; + +static void * allocator(void * o) +{ + qosspec_t qs; + ssize_t len; + char ** children; + int i; + char * ro_name; + struct complete * complete = (struct complete *) o; + + qs.delay = 0; + qs.jitter = 0; + + ro_name = pathname_create(RO_DIR); + if (ro_name == NULL) + return (void *) -1; + + len = ro_children(ro_name, &children); + if (len > 0) { + for (i = 0; i < len; i++) { + if (strcmp(children[i], ipcpi.name) == 0) + continue; + gam_flow_alloc(complete->gam, children[i], qs); + } + } + + pathname_destroy(ro_name); + + return (void *) 0; +} + +void * complete_create(struct gam * gam) +{ + struct ro_attr attr; + char * ro_name; + struct complete * complete; + + ro_attr_init(&attr); + attr.enrol_sync = true; + attr.recv_set = ALL_MEMBERS; + + complete = malloc(sizeof(*complete)); + if (complete == NULL) + return NULL; + + ro_name = pathname_create(RO_DIR); + if (ro_name == NULL) { + free(complete); + return NULL; + } + + if (!ro_exists(RO_DIR)) { + if (ro_create(ro_name, &attr, NULL, 0)) { + free(complete); + pathname_destroy(ro_name); + return NULL; + } + } + + ro_name = pathname_append(ro_name, ipcpi.name); + if (ro_name == NULL) { + free(complete); + pathname_destroy(ro_name); + return NULL; + } + + if (ro_create(ro_name, &attr, NULL, 0)) { + free(complete); + pathname_destroy(ro_name); + return NULL; + } + pathname_destroy(ro_name); + + list_head_init(&complete->neighbors); + complete->gam = gam; + + if (pthread_mutex_init(&complete->neighbors_lock, NULL)) { + free(complete); + return NULL; + } + + if (pthread_create(&complete->allocator, NULL, + allocator, (void *) complete)) { + free(complete); + pthread_mutex_destroy(&complete->neighbors_lock); + return NULL; + } + + return (void *) complete; +} + +void complete_destroy(void * o) +{ + struct list_head * p = NULL; + struct list_head * n = NULL; + struct complete * complete = (struct complete *) o; + + pthread_cancel(complete->allocator); + pthread_join(complete->allocator, NULL); + + 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); + } +} + +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; + + 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; + } + } + + 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 new file mode 100644 index 00000000..8fcc87ba --- /dev/null +++ b/src/ipcpd/normal/pol/complete.h @@ -0,0 +1,46 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Graph adjacency manager for IPC Process components + * + * Dimitri Staessens + * Sander Vrijders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#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); + +int complete_accept_new_flow(void * o); + +int complete_accept_flow(void * o, + qosspec_t qs, + const struct cacep_info * info); + +struct pol_gam_ops complete_ops = { + .create = complete_create, + .destroy = complete_destroy, + .accept_new_flow = complete_accept_new_flow, + .accept_flow = complete_accept_flow +}; + +#endif /* OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H */ diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index c780bf50..993fe62a 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -139,6 +139,8 @@ struct { struct addr_auth * addr_auth; enum pol_addr_auth addr_auth_type; + enum pol_gam dt_gam_type; + enum ribmgr_state state; pthread_cond_t state_cond; pthread_mutex_t state_lock; @@ -168,6 +170,7 @@ void ribmgr_ro_created(const char * name, rib.dtc.min_pdu_size = stat_msg->min_pdu_size; rib.dtc.max_pdu_size = stat_msg->max_pdu_size; rib.addr_auth_type = stat_msg->addr_auth_type; + rib.dt_gam_type = stat_msg->dt_gam_type; static_info_msg__free_unpacked(stat_msg, NULL); } @@ -1262,6 +1265,7 @@ int ribmgr_bootstrap(struct dif_config * conf) stat_info.min_pdu_size = rib.dtc.min_pdu_size = conf->min_pdu_size; stat_info.max_pdu_size = rib.dtc.max_pdu_size = conf->max_pdu_size; stat_info.addr_auth_type = rib.addr_auth_type = conf->addr_auth_type; + stat_info.dt_gam_type = rib.dt_gam_type = conf->dt_gam_type; len = static_info_msg__get_packed_size(&stat_info); if (len == 0) { @@ -1354,16 +1358,21 @@ int ribmgr_start_policies(void) return 0; } -struct dt_const * ribmgr_dt_const() +struct dt_const * ribmgr_dt_const(void) { return &(rib.dtc); } -uint64_t ribmgr_address() +uint64_t ribmgr_address(void) { return rib.address; } +enum pol_gam ribmgr_dt_gam(void) +{ + return rib.dt_gam_type; +} + static int send_neighbors_ro(char * name, ro_msg_t * msg, enum cdap_opcode code) { struct list_head * p = NULL; diff --git a/src/ipcpd/normal/ribmgr.h b/src/ipcpd/normal/ribmgr.h index ddc98e6e..22212de9 100644 --- a/src/ipcpd/normal/ribmgr.h +++ b/src/ipcpd/normal/ribmgr.h @@ -45,4 +45,6 @@ struct dt_const * ribmgr_dt_const(void); uint64_t ribmgr_address(void); +enum pol_gam ribmgr_dt_gam(void); + #endif /* OUROBOROS_IPCPD_NORMAL_RIBMGR_H */ diff --git a/src/ipcpd/normal/static_info.proto b/src/ipcpd/normal/static_info.proto index 18f02e36..bb6f8c4e 100644 --- a/src/ipcpd/normal/static_info.proto +++ b/src/ipcpd/normal/static_info.proto @@ -23,13 +23,14 @@ syntax = "proto2"; message static_info_msg { - required uint32 addr_size = 1; - required uint32 cep_id_size = 2; - required uint32 pdu_length_size = 3; - required uint32 seqno_size = 4; - required bool has_ttl = 5; - required bool has_chk = 6; - required uint32 min_pdu_size = 7; - required uint32 max_pdu_size = 8; - required uint32 addr_auth_type = 9; + required uint32 addr_size = 1; + required uint32 cep_id_size = 2; + required uint32 pdu_length_size = 3; + required uint32 seqno_size = 4; + required bool has_ttl = 5; + required bool has_chk = 6; + required uint32 min_pdu_size = 7; + required uint32 max_pdu_size = 8; + required uint32 addr_auth_type = 9; + required uint32 dt_gam_type = 10; } \ No newline at end of file -- cgit v1.2.3