From 20921b8300d1699d8b0133b3f5fc360fdd99fc0d Mon Sep 17 00:00:00 2001 From: dimitri staessens 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(-) 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 - #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