summaryrefslogtreecommitdiff
path: root/src/irmd
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@intec.ugent.be>2016-07-07 19:01:00 +0200
committerdimitri staessens <dimitri.staessens@intec.ugent.be>2016-07-07 20:54:06 +0200
commit27b36b690a4b048721f0a568ef0aff03bf8e9855 (patch)
tree36936ba283d5567c4c2533c1e56675290ff5fc67 /src/irmd
parentb3870ef695a256be4a4ed28a991c39aab37bd6f3 (diff)
downloadouroboros-27b36b690a4b048721f0a568ef0aff03bf8e9855.tar.gz
ouroboros-27b36b690a4b048721f0a568ef0aff03bf8e9855.zip
irmd: Prioritize local ipcp for local flows
For locally registered processes, the IRMd will first look for the local, then the normal, then the shim-udp. It will look for a normal, a shim-eth-llc and ultimately a shim-udp for non-local destinations. It does not yet check if a remote destination is actually known in a DIF. Fixes #18.
Diffstat (limited to 'src/irmd')
-rw-r--r--src/irmd/main.c128
-rw-r--r--src/irmd/registry.c57
-rw-r--r--src/irmd/registry.h18
3 files changed, 158 insertions, 45 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 19bc5b9b..c05a99f6 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -60,6 +60,7 @@ struct ipcp_entry {
struct list_head next;
char * name;
pid_t api;
+ enum ipcp_type type;
char * dif_name;
};
@@ -240,27 +241,53 @@ static struct ipcp_entry * get_ipcp_entry_by_api(pid_t api)
return NULL;
}
-/*
- * FIXME: this just returns the first IPCP that
- * matches the requested DIF name for now
- */
-static pid_t get_ipcp_by_dst_name(char * dst_name,
- char * dif_name)
+
+/* FIXME: Check if the name exists anywhere in a DIF. */
+static pid_t get_ipcp_by_dst_name(char * dst_name)
{
struct list_head * pos = NULL;
+ struct reg_entry * re =
+ registry_get_entry_by_name(&instance->registry, dst_name);
+
+ if (re != NULL) {
+ list_for_each(pos, &instance->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(pos, struct ipcp_entry, next);
+ if (e->dif_name == NULL)
+ continue;
+
+ if (e->type == IPCP_LOCAL)
+ return e->api;
+ }
+ }
list_for_each(pos, &instance->ipcps) {
struct ipcp_entry * e =
list_entry(pos, struct ipcp_entry, next);
+ if (e->dif_name != NULL && e->type == IPCP_NORMAL) {
+ if (re != NULL &&
+ !reg_entry_is_local_in_dif(re, e->dif_name))
+ continue;
+ return e->api;
+ }
+ }
- if (e->dif_name == NULL)
- continue;
-
- if (dif_name != NULL) {
- if (wildcard_match(dif_name, e->dif_name) == 0) {
+ if (re == NULL) {
+ list_for_each(pos, &instance->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(pos, struct ipcp_entry, next);
+ if (e->dif_name != NULL && e->type == IPCP_SHIM_ETH_LLC)
return e->api;
- }
- } else {
+ }
+ }
+
+ list_for_each(pos, &instance->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(pos, struct ipcp_entry, next);
+ if (e->dif_name != NULL && e->type == IPCP_SHIM_UDP) {
+ if (re != NULL &&
+ !reg_entry_is_local_in_dif(re, e->dif_name))
+ continue;
return e->api;
}
}
@@ -274,6 +301,8 @@ static pid_t create_ipcp(char * name,
struct spawned_api * api;
struct ipcp_entry * tmp = NULL;
+ struct list_head * pos;
+
api = malloc(sizeof(*api));
if (api == NULL)
return -ENOMEM;
@@ -309,9 +338,17 @@ static pid_t create_ipcp(char * name,
}
tmp->dif_name = NULL;
+ tmp->type = ipcp_type;
pthread_rwlock_wrlock(&instance->reg_lock);
+ list_for_each(pos, &instance->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(pos, struct ipcp_entry, next);
+ if (e->type < ipcp_type)
+ break;
+ }
+
list_add(&tmp->next, &instance->ipcps);
list_add(&api->next, &instance->spawned_apis);
@@ -647,16 +684,17 @@ static int ap_reg(char * name,
continue;
for (i = 0; i < len; ++i) {
- if (wildcard_match(difs[i], e->dif_name) == 0) {
- if (ipcp_name_reg(e->api, name)) {
- LOG_ERR("Could not register "
- "%s in DIF %s.",
- name, e->dif_name);
- } else {
- LOG_INFO("Registered %s in %s",
- name, e->dif_name);
- ++ret;
- }
+ if (wildcard_match(difs[i], e->dif_name))
+ continue;
+
+ if (ipcp_name_reg(e->api, name) ||
+ reg_entry_add_local_in_dif(reg, e->dif_name)) {
+ LOG_ERR("Could not register %s in DIF %s.",
+ name, e->dif_name);
+ } else {
+ LOG_INFO("Registered %s in %s",
+ name, e->dif_name);
+ ++ret;
}
}
}
@@ -679,7 +717,7 @@ static int ap_unreg(char * name,
{
int i;
int ret = 0;
- struct reg_entry * rne = NULL;
+ struct reg_entry * re = NULL;
struct list_head * pos = NULL;
if (name == NULL || len == 0 || difs == NULL || difs[0] == NULL)
@@ -694,6 +732,14 @@ static int ap_unreg(char * name,
pthread_rwlock_wrlock(&instance->reg_lock);
+ re = registry_get_entry_by_name(&instance->registry, name);
+ if (re == NULL) {
+ pthread_rwlock_unlock(&instance->reg_lock);
+ pthread_rwlock_unlock(&instance->state_lock);
+ LOG_ERR("Tried to unregister a name that is not bound.");
+ return -1;
+ }
+
list_for_each(pos, &instance->ipcps) {
struct ipcp_entry * e =
list_entry(pos, struct ipcp_entry, next);
@@ -702,17 +748,17 @@ static int ap_unreg(char * name,
continue;
for (i = 0; i < len; ++i) {
- if (wildcard_match(difs[i], e->dif_name) == 0) {
- if (ipcp_name_unreg(e->api,
- rne->name)) {
- LOG_ERR("Could not unregister "
- "%s in DIF %s.",
- rne->name, e->dif_name);
- --ret;
- } else {
- LOG_INFO("Unregistered %s from %s.",
- rne->name, e->dif_name);
- }
+ if (wildcard_match(difs[i], e->dif_name))
+ continue;
+
+ if (ipcp_name_unreg(e->api, re->name)) {
+ LOG_ERR("Could not unregister %s in DIF %s.",
+ re->name, e->dif_name);
+ --ret;
+ } else {
+ reg_entry_del_local_from_dif(re, e->dif_name);
+ LOG_INFO("Unregistered %s from %s.",
+ re->name, e->dif_name);
}
}
}
@@ -872,7 +918,6 @@ static struct port_map_entry * flow_alloc(pid_t api,
{
struct port_map_entry * pme;
pid_t ipcp;
- char * dif_name = NULL;
/* FIXME: Map qos_spec to qos_cube */
@@ -897,14 +942,11 @@ static struct port_map_entry * flow_alloc(pid_t api,
pthread_rwlock_rdlock(&instance->reg_lock);
- if (qos != NULL)
- dif_name = qos->dif_name;
-
- ipcp = get_ipcp_by_dst_name(dst_name, dif_name);
- if (ipcp == 0) {
+ ipcp = get_ipcp_by_dst_name(dst_name);
+ if (ipcp == -1) {
pthread_rwlock_unlock(&instance->reg_lock);
pthread_rwlock_unlock(&instance->state_lock);
- LOG_ERR("Unknown DIF name.");
+ LOG_INFO("Destination unreachable.");
return NULL;
}
@@ -1723,8 +1765,6 @@ static struct irm * irm_create()
free(instance);
return NULL;
}
-
- lockfile_close(lf);
}
if (pthread_rwlock_init(&instance->state_lock, NULL)) {
diff --git a/src/irmd/registry.c b/src/irmd/registry.c
index c5f81d77..e9927b7e 100644
--- a/src/irmd/registry.c
+++ b/src/irmd/registry.c
@@ -143,6 +143,7 @@ struct reg_entry * reg_entry_init(struct reg_entry * e,
INIT_LIST_HEAD(&e->ap_names);
INIT_LIST_HEAD(&e->auto_ap_info);
INIT_LIST_HEAD(&e->ap_instances);
+ INIT_LIST_HEAD(&e->difs);
e->name = name;
e->flags = flags;
@@ -228,9 +229,65 @@ void reg_entry_destroy(struct reg_entry * e)
free(n);
}
+ list_for_each_safe(pos, n, &e->difs) {
+ struct reg_dif_name * d =
+ list_entry(pos, struct reg_dif_name, next);
+ free(d->dif_name);
+ free(d);
+ }
+
free(e);
}
+bool reg_entry_is_local_in_dif(struct reg_entry * e,
+ char * dif_name)
+{
+ struct list_head * pos = NULL;
+
+ list_for_each(pos, &e->difs) {
+ struct reg_dif_name * d =
+ list_entry(pos, struct reg_dif_name, next);
+
+ if (!strcmp(dif_name, d->dif_name))
+ return true;
+ }
+
+ return false;
+}
+
+int reg_entry_add_local_in_dif(struct reg_entry * e,
+ char * dif_name)
+{
+ if (!reg_entry_is_local_in_dif(e, dif_name)) {
+ struct reg_dif_name * rdn = malloc(sizeof(*rdn));
+ rdn->dif_name = strdup(dif_name);
+ if (rdn->dif_name == NULL)
+ return -1;
+ list_add(&rdn->next, &e->difs);
+ return 0;
+ }
+
+ return 0; /* already registered. Is ok */
+}
+
+void reg_entry_del_local_from_dif(struct reg_entry * e,
+ char * dif_name)
+{
+ struct list_head * pos = NULL;
+ struct list_head * n = NULL;
+
+ list_for_each_safe(pos, n, &e->difs) {
+ struct reg_dif_name * d =
+ list_entry(pos, struct reg_dif_name, next);
+
+ if (!strcmp(dif_name, d->dif_name)) {
+ list_del(&d->next);
+ free(d);
+ }
+ }
+}
+
+
struct reg_ap_name * reg_entry_get_ap_name(struct reg_entry * e,
char * ap_name)
{
diff --git a/src/irmd/registry.h b/src/irmd/registry.h
index 83b9d393..927b2364 100644
--- a/src/irmd/registry.h
+++ b/src/irmd/registry.h
@@ -23,10 +23,13 @@
#ifndef OUROBOROS_IRMD_REGISTRY_H
#define OUROBOROS_IRMD_REGISTRY_H
+#include <ouroboros/config.h>
#include <ouroboros/list.h>
#include <stdint.h>
+#include <stdbool.h>
#include <pthread.h>
+#include <string.h>
#include <sys/types.h>
#define reg_entry_has_api(e, id) (reg_entry_get_reg_instance(e, id) != NULL)
@@ -78,6 +81,9 @@ struct reg_entry {
/* known instances */
struct list_head ap_instances;
+ /* difs in which this name is registered */
+ struct list_head difs;
+
char * req_ae_name;
int response;
@@ -96,6 +102,11 @@ struct reg_ap_name {
char * ap_name;
};
+struct reg_dif_name {
+ struct list_head next;
+ char * dif_name;
+};
+
struct reg_instance * reg_instance_create(pid_t api);
void reg_instance_destroy(struct reg_instance * i);
@@ -118,7 +129,12 @@ struct reg_auto * reg_entry_get_reg_auto(struct reg_entry * e,
char * ap_name);
pid_t reg_entry_resolve_api(struct reg_entry * e);
char ** reg_entry_resolve_auto(struct reg_entry * e);
-
+bool reg_entry_is_local_in_dif(struct reg_entry * e,
+ char * dif_name);
+int reg_entry_add_local_in_dif(struct reg_entry * e,
+ char * dif_name);
+void reg_entry_del_local_from_dif(struct reg_entry * e,
+ char * dif_name);
int registry_add_entry(struct list_head * registry,
char * name,
char * ap_name,