summaryrefslogtreecommitdiff
path: root/src/irmd
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@intec.ugent.be>2016-10-13 15:47:55 +0200
committerdimitri staessens <dimitri.staessens@intec.ugent.be>2016-10-13 15:47:55 +0200
commit20921b8300d1699d8b0133b3f5fc360fdd99fc0d (patch)
tree5192d254611ec919edf4596152ed5c041463acf2 /src/irmd
parent550e7892e47cf8daf351eb773ef3900b33ecabae (diff)
downloadouroboros-20921b8300d1699d8b0133b3f5fc360fdd99fc0d.tar.gz
ouroboros-20921b8300d1699d8b0133b3f5fc360fdd99fc0d.zip
lib: Fix flow deallocation logic
Both the N and N-1 entity must now call flow_dealloc for the port_id to be released.
Diffstat (limited to 'src/irmd')
-rw-r--r--src/irmd/irm_flow.c2
-rw-r--r--src/irmd/irm_flow.h3
-rw-r--r--src/irmd/main.c39
3 files changed, 28 insertions, 16 deletions
diff --git a/src/irmd/irm_flow.c b/src/irmd/irm_flow.c
index b99c6f97..df1302b4 100644
--- a/src/irmd/irm_flow.c
+++ b/src/irmd/irm_flow.c
@@ -63,7 +63,7 @@ void irm_flow_destroy(struct irm_flow * f)
return;
}
- if (f->state == FLOW_PENDING)
+ if (f->state == FLOW_ALLOC_PENDING)
f->state = FLOW_DESTROY;
else
f->state = FLOW_NULL;
diff --git a/src/irmd/irm_flow.h b/src/irmd/irm_flow.h
index db6598bf..5ec6d90e 100644
--- a/src/irmd/irm_flow.h
+++ b/src/irmd/irm_flow.h
@@ -31,8 +31,9 @@
enum flow_state {
FLOW_NULL = 0,
- FLOW_PENDING,
+ FLOW_ALLOC_PENDING,
FLOW_ALLOCATED,
+ FLOW_DEALLOC_PENDING,
FLOW_DESTROY
};
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 24a49c49..157fd8eb 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -38,7 +38,6 @@
#include <ouroboros/logs.h>
-
#include "utils.h"
#include "registry.h"
#include "irm_flow.h"
@@ -1144,7 +1143,7 @@ static struct irm_flow * flow_alloc(pid_t api,
}
f->n_api = api;
- f->state = FLOW_PENDING;
+ f->state = FLOW_ALLOC_PENDING;
if (clock_gettime(CLOCK_MONOTONIC, &f->t0) < 0)
LOG_WARN("Failed to set timestamp.");
@@ -1239,30 +1238,42 @@ static int flow_dealloc(pid_t api, int port_id)
f = get_irm_flow(port_id);
if (f == NULL) {
- bmp_release(irmd->port_ids, port_id);
pthread_rwlock_unlock(&irmd->flows_lock);
pthread_rwlock_unlock(&irmd->state_lock);
+ LOG_DBG("Deallocate called for unknown port.");
return 0;
}
if (api == f->n_api) {
- bmp_release(irmd->port_ids, port_id);
- n_1_api = f->n_1_api;
+ f->n_api = -1;
+ n_1_api = f->n_1_api;
+ } else if (api == f->n_1_api) {
+ f->n_1_api = -1;
+ } else {
+ pthread_rwlock_unlock(&irmd->flows_lock);
+ pthread_rwlock_unlock(&irmd->state_lock);
+ LOG_DBG("Dealloc called by wrong AP-I.");
+ return -EPERM;
}
- list_del(&f->next);
+ if (irm_flow_get_state(f) == FLOW_DEALLOC_PENDING) {
+ list_del(&f->next);
+ irm_flow_destroy(f);
+ bmp_release(irmd->port_ids, port_id);
+ LOG_INFO("Completed deallocation of port_id %d by AP-I %d.",
+ port_id, api);
+ } else {
+ irm_flow_set_state(f, FLOW_DEALLOC_PENDING);
+ LOG_DBG("Partial deallocation of port_id %d by AP-I %d.",
+ port_id, api);
+ }
pthread_rwlock_unlock(&irmd->flows_lock);
+ pthread_rwlock_unlock(&irmd->state_lock);
if (n_1_api != -1)
ret = ipcp_flow_dealloc(n_1_api, port_id);
- pthread_rwlock_unlock(&irmd->state_lock);
-
- irm_flow_destroy(f);
-
- LOG_INFO("Deallocated flow with port_id %d.", port_id);
-
return ret;
}
@@ -1322,7 +1333,7 @@ static struct irm_flow * flow_req_arr(pid_t api,
return NULL;
}
- f->state = FLOW_PENDING;
+ f->state = FLOW_ALLOC_PENDING;
f->n_1_api = api;
if (clock_gettime(CLOCK_MONOTONIC, &f->t0) < 0)
LOG_WARN("Failed to set timestamp.");
@@ -1672,7 +1683,7 @@ void * irm_sanitize()
struct irm_flow * f =
list_entry(p, struct irm_flow, next);
- if (irm_flow_get_state(f) == FLOW_PENDING
+ if (irm_flow_get_state(f) == FLOW_ALLOC_PENDING
&& ts_diff_ms(&f->t0, &now) > IRMD_FLOW_TIMEOUT) {
LOG_INFO("Pending port_id %d timed out.",
f->port_id);