From 27b36b690a4b048721f0a568ef0aff03bf8e9855 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Thu, 7 Jul 2016 19:01:00 +0200 Subject: 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. --- src/irmd/main.c | 128 ++++++++++++++++++++++++++++++++++------------------ src/irmd/registry.c | 57 +++++++++++++++++++++++ src/irmd/registry.h | 18 +++++++- 3 files changed, 158 insertions(+), 45 deletions(-) (limited to 'src') 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 #include #include +#include #include +#include #include #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, -- cgit v1.2.3