From 20921b8300d1699d8b0133b3f5fc360fdd99fc0d Mon Sep 17 00:00:00 2001
From: dimitri staessens <dimitri.staessens@intec.ugent.be>
Date: Thu, 13 Oct 2016 15:47:55 +0200
Subject: lib: Fix flow deallocation logic

Both the N and N-1 entity must now call flow_dealloc for the port_id
to be released.
---
 src/ipcpd/local/main.c        |  2 ++
 src/ipcpd/shim-eth-llc/main.c |  2 ++
 src/ipcpd/shim-udp/main.c     |  2 ++
 src/irmd/irm_flow.c           |  2 +-
 src/irmd/irm_flow.h           |  3 ++-
 src/irmd/main.c               | 39 +++++++++++++++++++++++++--------------
 src/lib/dev.c                 | 19 +------------------
 7 files changed, 35 insertions(+), 34 deletions(-)

(limited to 'src')

diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c
index 1ccec0c0..7d23c08d 100644
--- a/src/ipcpd/local/main.c
+++ b/src/ipcpd/local/main.c
@@ -252,6 +252,8 @@ static int ipcp_local_flow_dealloc(int fd)
         pthread_rwlock_unlock(&local_data.lock);
         pthread_rwlock_unlock(&ipcpi.state_lock);
 
+        flow_dealloc(fd);
+
         LOG_INFO("Flow with fd %d deallocated.", fd);
 
         return 0;
diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c
index 130f3945..399d3dc8 100644
--- a/src/ipcpd/shim-eth-llc/main.c
+++ b/src/ipcpd/shim-eth-llc/main.c
@@ -975,6 +975,8 @@ static int eth_llc_ipcp_flow_dealloc(int fd)
         if (ret < 0)
                 LOG_DBG("Could not notify remote.");
 
+        flow_dealloc(fd);
+
         LOG_DBG("Flow with fd %d deallocated.", fd);
 
         return 0;
diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c
index 12f6d82e..7c109a8a 100644
--- a/src/ipcpd/shim-udp/main.c
+++ b/src/ipcpd/shim-udp/main.c
@@ -1117,6 +1117,8 @@ static int ipcp_udp_flow_dealloc(int fd)
 
         close(skfd);
 
+        flow_dealloc(fd);
+
         LOG_DBG("Flow with fd %d deallocated.", fd);
 
         return 0;
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);
diff --git a/src/lib/dev.c b/src/lib/dev.c
index c1f769ad..348b864c 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -566,11 +566,10 @@ int flow_dealloc(int fd)
         shm_ap_rbuff_close_port(ai.rb, msg.port_id);
 
         pthread_rwlock_unlock(&ai.flows_lock);
+        pthread_rwlock_unlock(&ai.data_lock);
 
         send_irm_msg(&msg);
 
-        pthread_rwlock_unlock(&ai.data_lock);
-
         return 0;
 }
 
@@ -864,22 +863,6 @@ int np1_flow_dealloc(int port_id)
         pthread_rwlock_wrlock(&ai.flows_lock);
 
         fd = ai.ports[port_id].fd;
-        if (fd < 0) {
-                pthread_rwlock_unlock(&ai.flows_lock);
-                pthread_rwlock_unlock(&ai.data_lock);
-                return fd;
-        }
-
-        ai.flows[fd].port_id = -1;
-        shm_ap_rbuff_close(ai.flows[fd].rb);
-        ai.flows[fd].rb = NULL;
-        ai.flows[fd].api = -1;
-
-        bmp_release(ai.fds, fd);
-
-        port_destroy(&ai.ports[port_id]);
-
-        shm_ap_rbuff_close_port(ai.rb, port_id);
 
         pthread_rwlock_unlock(&ai.flows_lock);
         pthread_rwlock_unlock(&ai.data_lock);
-- 
cgit v1.2.3