From d947aad0aede71936c592d65afcaedcaec0f0beb Mon Sep 17 00:00:00 2001
From: dimitri staessens <dimitri.staessens@ugent.be>
Date: Sat, 29 Apr 2017 12:10:25 +0200
Subject: ipcpd: Fix sending fa dealloc message

The frct instance was previously destroyed before sending the message,
resulting in the destination address being 0 and the message getting
dropped. Some fixes in the normal for deallocation, but will require
further revision once all data transfer protocols are in place.
---
 src/ipcpd/normal/dt.c |  2 +-
 src/ipcpd/normal/fa.c | 47 ++++++++++++++++++++++++++++++-----------------
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c
index 0816ec10..4e0ba51d 100644
--- a/src/ipcpd/normal/dt.c
+++ b/src/ipcpd/normal/dt.c
@@ -275,7 +275,7 @@ int dt_write_sdu(uint64_t             dst_addr,
 
         fd = pff_nhop(dt.pff[qc], dst_addr);
         if (fd < 0) {
-                log_err("Could not get nhop for address %" PRIu64, dst_addr);
+                log_err("Could not get nhop for addr %" PRIu64 ".", dst_addr);
                 return -1;
         }
 
diff --git a/src/ipcpd/normal/fa.c b/src/ipcpd/normal/fa.c
index b116c842..6ea5b711 100644
--- a/src/ipcpd/normal/fa.c
+++ b/src/ipcpd/normal/fa.c
@@ -128,6 +128,7 @@ static struct shm_du_buff * create_fa_sdb(flow_alloc_msg_t * msg)
         return sdb;
 }
 
+/* FIXME: Revise when Delta-t is fully implemented */
 static void destroy_conn(int      fd,
                          cep_id_t cep_id)
 {
@@ -181,7 +182,7 @@ int fa_alloc(int             fd,
 
         free(dst_ipcp);
 
-        if (rib_read(path, &addr, sizeof(addr)) < 0)
+        if (rib_read(path, &addr, sizeof(addr)) != sizeof(addr))
                 return -1;
 
         cep_id = frct_i_create(addr, qc);
@@ -280,6 +281,7 @@ int fa_alloc_resp(int fd,
                          PDU_TYPE_FA,
                          sdb)) {
                 destroy_conn(fd, fa.fd_to_cep_id[fd]);
+                pthread_rwlock_unlock(&fa.flows_lock);
                 ipcp_sdb_release(sdb);
                 return -1;
         }
@@ -294,37 +296,44 @@ int fa_dealloc(int fd)
         flow_alloc_msg_t     msg = FLOW_ALLOC_MSG__INIT;
         struct shm_du_buff * sdb;
         qoscube_t            qc;
-
-        pthread_rwlock_wrlock(&fa.flows_lock);
-
-        sdu_sched_del(fa.sdu_sched, fd);
-
-        destroy_conn(fd, fa.fd_to_cep_id[fd]);
+        uint64_t             addr;
 
         msg.code       = FLOW_ALLOC_CODE__FLOW_DEALLOC;
         msg.has_cep_id = true;
+
+        pthread_rwlock_rdlock(&fa.flows_lock);
+
         msg.cep_id     = frct_i_get_id(fa.fd_to_cep_id[fd]);
 
-        sdb = create_fa_sdb(&msg);
-        if (sdb == NULL) {
-                pthread_rwlock_unlock(&fa.flows_lock);
-                return -1;
-        }
+        addr = frct_i_get_addr(fa.fd_to_cep_id[fd]);
 
         pthread_rwlock_unlock(&fa.flows_lock);
 
+        sdb = create_fa_sdb(&msg);
+        if (sdb == NULL)
+                return -1;
+
         ipcp_flow_get_qoscube(fd, &qc);
 
         assert(qc >= 0 && qc < QOS_CUBE_MAX);
 
-        if (dt_write_sdu(frct_i_get_addr(fa.fd_to_cep_id[fd]),
-                         qc,
-                         PDU_TYPE_FA,
-                         sdb)) {
+        if (dt_write_sdu(addr, qc, PDU_TYPE_FA, sdb)) {
                 ipcp_sdb_release(sdb);
-                return -1;
+                log_warn("Failed to send dealloc message.");
         }
 
+        ipcp_flow_fini(fd);
+
+        pthread_rwlock_wrlock(&fa.flows_lock);
+
+        sdu_sched_del(fa.sdu_sched, fd);
+
+        destroy_conn(fd, fa.fd_to_cep_id[fd]);
+
+        pthread_rwlock_unlock(&fa.flows_lock);
+
+        flow_dealloc(fd);
+
         return 0;
 }
 
@@ -430,7 +439,11 @@ int fa_post_sdu(struct shm_du_buff * sdb)
 
                 break;
         case FLOW_ALLOC_CODE__FLOW_DEALLOC:
+                /* FIXME: mark flow and wait for frct_i to time out */
+                pthread_rwlock_rdlock(&fa.flows_lock);
                 fd = fa.cep_id_to_fd[msg->cep_id];
+                pthread_rwlock_unlock(&fa.flows_lock);
+                ipcp_flow_fini(fd);
                 sdu_sched_del(fa.sdu_sched, fd);
                 flow_dealloc(fd);
                 break;
-- 
cgit v1.2.3