summaryrefslogtreecommitdiff
path: root/src/ipcpd
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd')
-rw-r--r--src/ipcpd/ipcp.c17
-rw-r--r--src/ipcpd/ipcp.h3
-rw-r--r--src/ipcpd/local/main.c8
-rw-r--r--src/ipcpd/normal/CMakeLists.txt2
-rw-r--r--src/ipcpd/normal/fmgr.c197
-rw-r--r--src/ipcpd/normal/fmgr.h10
-rw-r--r--src/ipcpd/normal/gam.c285
-rw-r--r--src/ipcpd/normal/gam.h46
-rw-r--r--src/ipcpd/normal/main.c27
-rw-r--r--src/ipcpd/normal/pol-gam-ops.h40
-rw-r--r--src/ipcpd/normal/pol/complete.c208
-rw-r--r--src/ipcpd/normal/pol/complete.h46
-rw-r--r--src/ipcpd/normal/ribmgr.c19
-rw-r--r--src/ipcpd/normal/ribmgr.h2
-rw-r--r--src/ipcpd/normal/static_info.proto19
-rw-r--r--src/ipcpd/shim-eth-llc/main.c8
-rw-r--r--src/ipcpd/shim-udp/main.c8
17 files changed, 813 insertions, 132 deletions
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index 2e4c3fca..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;
@@ -440,22 +441,26 @@ int ipcp_parse_arg(int argc, char * argv[])
if (atoi(argv[1]) == 0)
return -1;
- if (argv[2] == NULL)
+ ipcpi.irmd_api = atoi(argv[1]);
+
+ /* argument 2: IPCP name */
+ ipcpi.name = argv[2];
+
+ /* argument 3: logfile name (if any) */
+ if (argv[3] == NULL)
return 0;
len += strlen(INSTALL_PREFIX);
len += strlen(LOG_DIR);
- len += strlen(argv[2]);
+ len += strlen(argv[3]);
log_file = malloc(len + 1);
- if (log_file == NULL) {
- LOG_ERR("Failed to malloc");
+ if (log_file == NULL)
return -1;
- }
strcpy(log_file, INSTALL_PREFIX);
strcat(log_file, LOG_DIR);
- strcat(log_file, argv[2]);
+ strcat(log_file, argv[3]);
log_file[len] = '\0';
if (set_logfile(log_file))
diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h
index ae5a56da..a75186ba 100644
--- a/src/ipcpd/ipcp.h
+++ b/src/ipcpd/ipcp.h
@@ -38,6 +38,9 @@ enum ipcp_state {
};
struct ipcp {
+ int irmd_api;
+ char * name;
+
struct ipcp_data * data;
struct ipcp_ops * ops;
int irmd_fd;
diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c
index 58949aea..5117f59d 100644
--- a/src/ipcpd/local/main.c
+++ b/src/ipcpd/local/main.c
@@ -41,9 +41,6 @@
#define EVENT_WAIT_TIMEOUT 100 /* us */
#define THIS_TYPE IPCP_LOCAL
-/* global for trapping signal */
-int irmd_api;
-
struct {
int in_out[IRMD_MAX_FLOWS];
flow_set_t * flows;
@@ -127,7 +124,7 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c)
case SIGTERM:
case SIGHUP:
case SIGQUIT:
- if (info->si_pid == irmd_api) {
+ if (info->si_pid == ipcpi.irmd_api) {
pthread_rwlock_wrlock(&ipcpi.state_lock);
if (ipcp_get_state() == IPCP_INIT)
@@ -349,9 +346,6 @@ int main(int argc, char * argv[])
exit(EXIT_FAILURE);
}
- /* store the process id of the irmd */
- irmd_api = atoi(argv[1]);
-
/* init sig_act */
memset(&sig_act, 0, sizeof(sig_act));
diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt
index bdcb78ae..157baa9e 100644
--- a/src/ipcpd/normal/CMakeLists.txt
+++ b/src/ipcpd/normal/CMakeLists.txt
@@ -29,12 +29,14 @@ set(SOURCE_FILES
dir.c
fmgr.c
frct.c
+ gam.c
main.c
pathname.c
pff.c
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 a419e9f5..6fe6fb60 100644
--- a/src/ipcpd/normal/fmgr.c
+++ b/src/ipcpd/normal/fmgr.c
@@ -28,6 +28,7 @@
#include <ouroboros/ipcp-dev.h>
#include <ouroboros/fqueue.h>
#include <ouroboros/errno.h>
+#include <ouroboros/cacep.h>
#include <stdlib.h>
#include <stdbool.h>
@@ -42,15 +43,24 @@
#include "dir.h"
#include "pathname.h"
#include "ro.h"
+#include "gam.h"
#include "flow_alloc.pb-c.h"
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];
@@ -60,21 +70,23 @@ struct {
cep_id_t np1_fd_to_cep_id[AP_MAX_FLOWS];
int np1_cep_id_to_fd[IPCPD_MAX_CONNS];
- pthread_t nm1_sdu_reader;
pthread_t np1_sdu_reader;
+ pthread_t nm1_sdu_reader;
+ pthread_t nm1_flow_wait;
/* FIXME: Replace with PFF */
int fd;
+
+ struct gam * gam;
} fmgr;
static void * fmgr_np1_sdu_reader(void * o)
{
struct shm_du_buff * sdb;
- struct timespec timeout = {0, FD_UPDATE_TIMEOUT};
- int fd;
-
- int i = 0;
- int ret;
+ struct timespec timeout = {0, FD_UPDATE_TIMEOUT};
+ int fd;
+ int i = 0;
+ int ret;
(void) o;
@@ -118,12 +130,12 @@ static void * fmgr_np1_sdu_reader(void * o)
void * fmgr_nm1_sdu_reader(void * o)
{
- struct timespec timeout = {0, FD_UPDATE_TIMEOUT};
+ struct timespec timeout = {0, FD_UPDATE_TIMEOUT};
struct shm_du_buff * sdb;
- struct pci * pci;
- int fd;
- int i = 0;
- int ret;
+ struct pci * pci;
+ int fd;
+ int i = 0;
+ int ret;
(void) o;
@@ -202,6 +214,49 @@ 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;
@@ -224,9 +279,6 @@ int fmgr_init()
for (i = 0; i < IPCPD_MAX_CONNS; ++i)
fmgr.np1_cep_id_to_fd[i] = -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.np1_set[i] = flow_set_create();
if (fmgr.np1_set[i] == NULL) {
@@ -253,29 +305,55 @@ int fmgr_init()
}
}
+ fmgr.gam = gam_create(ribmgr_dt_gam(), DT_AE);
+ if (fmgr.gam == NULL) {
+ LOG_ERR("Failed to create graph adjacency manager.");
+ fmgr_destroy_flows();
+ return -1;
+ }
+
+ list_head_init(&fmgr.nm1_flows);
+
+ pthread_rwlock_init(&fmgr.nm1_flows_lock, NULL);
+ pthread_rwlock_init(&fmgr.np1_flows_lock, NULL);
+
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);
return 0;
}
int fmgr_fini()
{
- int i;
- int j;
+ struct list_head * pos = NULL;
+ struct list_head * n = NULL;
+ qoscube_t cube;
pthread_cancel(fmgr.np1_sdu_reader);
pthread_cancel(fmgr.nm1_sdu_reader);
+ pthread_cancel(fmgr.nm1_flow_wait);
pthread_join(fmgr.np1_sdu_reader, NULL);
pthread_join(fmgr.nm1_sdu_reader, NULL);
+ pthread_join(fmgr.nm1_flow_wait, NULL);
- for (i = 0; i < AP_MAX_FLOWS; ++i)
- for (j = 0; j < QOS_CUBE_MAX; ++j)
- if (flow_set_has(fmgr.nm1_set[j], i)) {
- flow_dealloc(i);
- flow_set_del(fmgr.nm1_set[j], i);
- }
+ gam_destroy(fmgr.gam);
+
+ 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);
+ free(flow);
+ }
+
+ pthread_rwlock_unlock(&fmgr.nm1_flows_lock);
pthread_rwlock_destroy(&fmgr.nm1_flows_lock);
pthread_rwlock_destroy(&fmgr.np1_flows_lock);
@@ -290,12 +368,12 @@ int fmgr_np1_alloc(int fd,
char * src_ae_name,
qoscube_t cube)
{
- cep_id_t cep_id;
- buffer_t buf;
+ cep_id_t cep_id;
+ buffer_t buf;
flow_alloc_msg_t msg = FLOW_ALLOC_MSG__INIT;
- char * path;
- uint8_t * ro_data;
- uint64_t addr;
+ char * path;
+ uint8_t * ro_data;
+ uint64_t addr;
path = pathname_create(RO_DIR);
if (path == NULL)
@@ -359,9 +437,9 @@ int fmgr_np1_alloc(int fd,
static int np1_flow_dealloc(int fd)
{
flow_alloc_msg_t msg = FLOW_ALLOC_MSG__INIT;
- buffer_t buf;
- int ret;
- qoscube_t cube;
+ buffer_t buf;
+ int ret;
+ qoscube_t cube;
ipcp_flow_get_qoscube(fd, &cube);
flow_set_del(fmgr.np1_set[cube], fd);
@@ -388,10 +466,11 @@ static int np1_flow_dealloc(int fd)
return ret;
}
-int fmgr_np1_alloc_resp(int fd, int response)
+int fmgr_np1_alloc_resp(int fd,
+ int response)
{
flow_alloc_msg_t msg = FLOW_ALLOC_MSG__INIT;
- buffer_t buf;
+ buffer_t buf;
msg.code = FLOW_ALLOC_CODE__FLOW_REPLY;
msg.response = response;
@@ -443,7 +522,8 @@ int fmgr_np1_dealloc(int fd)
return ret;
}
-int fmgr_np1_post_buf(cep_id_t cep_id, buffer_t * buf)
+int fmgr_np1_post_buf(cep_id_t cep_id,
+ buffer_t * buf)
{
int ret = 0;
int fd;
@@ -512,7 +592,8 @@ int fmgr_np1_post_buf(cep_id_t cep_id, buffer_t * buf)
return ret;
}
-int fmgr_np1_post_sdu(cep_id_t cep_id, struct shm_du_buff * sdb)
+int fmgr_np1_post_sdu(cep_id_t cep_id,
+ struct shm_du_buff * sdb)
{
int fd;
@@ -530,52 +611,21 @@ int fmgr_np1_post_sdu(cep_id_t cep_id, struct shm_du_buff * sdb)
return 0;
}
-/* FIXME: do this in a topologymanager instance */
-int fmgr_nm1_add_flow(int fd)
+int fmgr_nm1_flow_arr(int fd,
+ qosspec_t qs)
{
- qoscube_t qos;
+ assert(fmgr.gam);
- if (flow_alloc_resp(fd, 0) < 0) {
- LOG_ERR("Could not respond to new flow.");
+ if (gam_flow_arr(fmgr.gam, fd, qs)) {
+ LOG_ERR("Failed to hand to graph adjacency manager.");
return -1;
}
- ipcp_flow_get_qoscube(fd, &qos);
- flow_set_add(fmgr.nm1_set[qos], fd);
-
- /* FIXME: Temporary, until we have a PFF */
- fmgr.fd = fd;
-
- return 0;
-}
-
-int fmgr_nm1_dt_flow(char * dst_name, qoscube_t qos)
-{
- int fd;
- int result;
-
- /* FIXME: Map qos cube on correct QoS. */
- fd = flow_alloc(dst_name, DT_AE, NULL);
- if (fd < 0) {
- LOG_ERR("Failed to allocate flow to %s.", dst_name);
- return -1;
- }
-
- result = flow_alloc_res(fd);
- if (result < 0) {
- LOG_ERR("Allocate flow to %s result %d.", dst_name, result);
- return -1;
- }
-
- flow_set_add(fmgr.nm1_set[qos], fd);
-
- /* FIXME: Temporary, until we have a PFF */
- fmgr.fd = fd;
-
return 0;
}
-int fmgr_nm1_write_sdu(struct pci * pci, struct shm_du_buff * sdb)
+int fmgr_nm1_write_sdu(struct pci * pci,
+ struct shm_du_buff * sdb)
{
if (pci == NULL || sdb == NULL)
return -1;
@@ -595,7 +645,8 @@ int fmgr_nm1_write_sdu(struct pci * pci, struct shm_du_buff * sdb)
return 0;
}
-int fmgr_nm1_write_buf(struct pci * pci, buffer_t * buf)
+int fmgr_nm1_write_buf(struct pci * pci,
+ buffer_t * buf)
{
buffer_t * buffer;
diff --git a/src/ipcpd/normal/fmgr.h b/src/ipcpd/normal/fmgr.h
index 85731081..ae5c8ea8 100644
--- a/src/ipcpd/normal/fmgr.h
+++ b/src/ipcpd/normal/fmgr.h
@@ -23,6 +23,7 @@
#define OUROBOROS_IPCPD_NORMAL_FMGR_H
#include <ouroboros/shared.h>
+#include <ouroboros/qos.h>
#include "ae.h"
#include "frct.h"
@@ -47,15 +48,14 @@ int fmgr_np1_post_buf(cep_id_t id,
int fmgr_np1_post_sdu(cep_id_t id,
struct shm_du_buff * sdb);
-int fmgr_nm1_add_flow(int fd);
-
-int fmgr_nm1_dt_flow(char * dst_name,
- qoscube_t qos);
-
int fmgr_nm1_write_sdu(struct pci * pci,
struct shm_du_buff * sdb);
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/gam.c b/src/ipcpd/normal/gam.c
new file mode 100644
index 00000000..0e626115
--- /dev/null
+++ b/src/ipcpd/normal/gam.c
@@ -0,0 +1,285 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2017
+ *
+ * Graph adjacency manager for IPC Process components
+ *
+ * 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.
+ */
+
+#define OUROBOROS_PREFIX "graph-adjacency-manager"
+
+#include <ouroboros/config.h>
+#include <ouroboros/dev.h>
+#include <ouroboros/logs.h>
+#include <ouroboros/list.h>
+#include <ouroboros/errno.h>
+
+#include "ribmgr.h"
+#include "ipcp.h"
+#include "gam.h"
+#include "pol-gam-ops.h"
+#include "pol/complete.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#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 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);
+ 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);
+ return NULL;
+ }
+
+ return tmp;
+}
+
+void gam_destroy(struct gam * instance)
+{
+ struct list_head * p = NULL;
+ struct list_head * n = NULL;
+
+ assert(instance);
+
+ instance->ops->destroy(instance->ops_o);
+
+ pthread_mutex_destroy(&instance->gas_lock);
+ pthread_cond_destroy(&instance->gas_cond);
+
+ list_for_each_safe(p, n, &instance->gas) {
+ struct ga * e = list_entry(p, struct ga, next);
+ list_del(&e->next);
+ free(e->info);
+ free(e);
+ }
+
+ free(instance->ae_name);
+ 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);
+
+ return 0;
+}
+
+int gam_flow_arr(struct gam * instance,
+ int fd,
+ qosspec_t qs)
+{
+ 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, ribmgr_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);
+ return 0;
+ }
+
+ if (add_ga(instance, fd, qs, info)) {
+ LOG_ERR("Failed to add ga to graph adjacency manager list.");
+ 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, ribmgr_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);
+ return 0;
+ }
+
+ if (add_ga(instance, fd, qs, info)) {
+ LOG_ERR("Failed to add GA to graph adjacency manager list.");
+ 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);
+
+ 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_mutex_unlock(&instance->gas_lock);
+
+ return 0;
+}
diff --git a/src/ipcpd/normal/gam.h b/src/ipcpd/normal/gam.h
new file mode 100644
index 00000000..e858114c
--- /dev/null
+++ b/src/ipcpd/normal/gam.h
@@ -0,0 +1,46 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2017
+ *
+ * Graph adjacency manager for IPC Process components
+ *
+ * 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.
+ */
+
+#ifndef OUROBOROS_IPCPD_NORMAL_GAM_H
+#define OUROBOROS_IPCPD_NORMAL_GAM_H
+
+#include <ouroboros/cacep.h>
+
+struct gam * gam_create(enum pol_gam gam_type,
+ const char * ae_name);
+
+void gam_destroy(struct gam * instance);
+
+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);
+
+int gam_flow_wait(struct gam * instance,
+ int * fd,
+ struct cacep_info ** info,
+ qosspec_t * qs);
+
+#endif /* OUROBOROS_IPCPD_NORMAL_GAM_H */
diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c
index 8db754aa..85f56ab0 100644
--- a/src/ipcpd/normal/main.c
+++ b/src/ipcpd/normal/main.c
@@ -26,6 +26,7 @@
#include <ouroboros/dev.h>
#include <ouroboros/ipcp-dev.h>
#include <ouroboros/time_utils.h>
+#include <ouroboros/irm.h>
#include "fmgr.h"
#include "ribmgr.h"
@@ -47,7 +48,9 @@ int irmd_api;
pthread_t acceptor;
-void ipcp_sig_handler(int sig, siginfo_t * info, void * c)
+void ipcp_sig_handler(int sig,
+ siginfo_t * info,
+ void * c)
{
(void) c;
@@ -55,7 +58,7 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c)
case SIGINT:
case SIGTERM:
case SIGHUP:
- if (info->si_pid == irmd_api) {
+ if (info->si_pid == ipcpi.irmd_api) {
pthread_rwlock_wrlock(&ipcpi.state_lock);
if (ipcp_get_state() == IPCP_INIT)
@@ -101,7 +104,7 @@ static void * flow_acceptor(void * o)
if (strcmp(ae_name, MGMT_AE) == 0) {
ribmgr_add_nm1_flow(fd);
} else if (strcmp(ae_name, DT_AE) == 0) {
- fmgr_nm1_add_flow(fd);
+ fmgr_nm1_flow_arr(fd, qs);
} else {
LOG_DBG("Flow allocation request for unknown AE %s.",
ae_name);
@@ -195,12 +198,6 @@ static int normal_ipcp_enroll(char * dst_name)
pthread_rwlock_unlock(&ipcpi.state_lock);
- /* FIXME: Remove once we obtain neighbors during enrollment */
- if (fmgr_nm1_dt_flow(dst_name, QOS_CUBE_BE)) {
- LOG_ERR("Failed to establish data transfer flow.");
- return -1;
- }
-
LOG_DBG("Enrolled with %s.", dst_name);
return 0;
@@ -296,10 +293,11 @@ static struct ipcp_ops normal_ops = {
.ipcp_flow_dealloc = fmgr_np1_dealloc
};
-int main(int argc, char * argv[])
+int main(int argc,
+ char * argv[])
{
struct sigaction sig_act;
- sigset_t sigset;
+ sigset_t sigset;
if (ap_init(argv[0])) {
LOG_ERR("Failed to init AP");
@@ -317,8 +315,11 @@ int main(int argc, char * argv[])
exit(EXIT_FAILURE);
}
- /* store the process id of the irmd */
- irmd_api = atoi(argv[1]);
+ if (irm_bind_api(getpid(), ipcpi.name)) {
+ LOG_ERR("Failed to bind AP name.");
+ close_logfile();
+ exit(EXIT_FAILURE);
+ }
/* init sig_act */
memset(&sig_act, 0, sizeof(sig_act));
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 <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.
+ */
+
+#ifndef OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H
+#define OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H
+
+#include <ouroboros/cacep.h>
+
+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 <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.
+ */
+
+#define OUROBOROS_PREFIX "complete-graph-adjacency-manager"
+
+#include <ouroboros/config.h>
+#include <ouroboros/logs.h>
+#include <ouroboros/list.h>
+#include <ouroboros/qos.h>
+
+#include "pathname.h"
+#include "ro.h"
+#include "ipcp.h"
+#include "gam.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#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 <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.
+ */
+
+#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 6356d48c..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;
@@ -1577,8 +1586,8 @@ ssize_t ro_children(const char * name, char *** children)
}
child = node->child;
- **children = malloc(len);
- if (**children == NULL) {
+ *children = malloc(len);
+ if (*children == NULL) {
pthread_mutex_unlock(&rib.ro_lock);
return -1;
}
@@ -1590,7 +1599,7 @@ ssize_t ro_children(const char * name, char *** children)
free((*children)[i]);
i--;
}
- free(**children);
+ free(*children);
pthread_mutex_unlock(&rib.ro_lock);
return -1;
}
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
diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c
index 0ff8007b..da496b07 100644
--- a/src/ipcpd/shim-eth-llc/main.c
+++ b/src/ipcpd/shim-eth-llc/main.c
@@ -77,9 +77,6 @@ typedef ShimEthLlcMsg shim_eth_llc_msg_t;
#define EVENT_WAIT_TIMEOUT 100 /* us */
#define NAME_QUERY_TIMEOUT 100000000 /* ns */
-/* global for trapping signal */
-int irmd_api;
-
struct eth_llc_frame {
uint8_t dst_hwaddr[MAC_SIZE];
uint8_t src_hwaddr[MAC_SIZE];
@@ -675,7 +672,7 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c)
case SIGINT:
case SIGTERM:
case SIGHUP:
- if (info->si_pid == irmd_api) {
+ if (info->si_pid == ipcpi.irmd_api) {
pthread_rwlock_wrlock(&ipcpi.state_lock);
if (ipcp_get_state() == IPCP_INIT)
@@ -1123,9 +1120,6 @@ int main(int argc, char * argv[])
exit(EXIT_FAILURE);
}
- /* store the process id of the irmd */
- irmd_api = atoi(argv[1]);
-
/* init sig_act */
memset(&sig_act, 0, sizeof(sig_act));
diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c
index 8c0c0aac..99aac40e 100644
--- a/src/ipcpd/shim-udp/main.c
+++ b/src/ipcpd/shim-udp/main.c
@@ -60,9 +60,6 @@ typedef ShimUdpMsg shim_udp_msg_t;
#define UDP_MAX_PORTS 0xFFFF
-/* global for trapping signal */
-int irmd_api;
-
struct uf {
int udp;
int skfd;
@@ -529,7 +526,7 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c)
case SIGINT:
case SIGTERM:
case SIGHUP:
- if (info->si_pid == irmd_api) {
+ if (info->si_pid == ipcpi.irmd_api) {
pthread_rwlock_wrlock(&ipcpi.state_lock);
if (ipcp_get_state() == IPCP_INIT)
@@ -1191,9 +1188,6 @@ int main(int argc, char * argv[])
exit(EXIT_FAILURE);
}
- /* store the process id of the irmd */
- irmd_api = atoi(argv[1]);
-
/* init sig_act */
memset(&sig_act, 0, sizeof(sig_act));