summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ipcpd/shim-data.c113
-rw-r--r--src/ipcpd/shim-data.h9
-rw-r--r--src/ipcpd/shim-eth-llc/main.c26
3 files changed, 87 insertions, 61 deletions
diff --git a/src/ipcpd/shim-data.c b/src/ipcpd/shim-data.c
index 747a210b..355cec68 100644
--- a/src/ipcpd/shim-data.c
+++ b/src/ipcpd/shim-data.c
@@ -46,6 +46,40 @@ struct dir_entry {
uint64_t addr;
};
+static void destroy_dir_query(struct dir_query * query)
+{
+ assert(query);
+
+ pthread_mutex_lock(&query->lock);
+
+ switch (query->state) {
+ case QUERY_INIT:
+ query->state = QUERY_DONE;
+ break;
+ case QUERY_PENDING:
+ query->state = QUERY_DESTROY;
+ pthread_cond_broadcast(&query->cond);
+ break;
+ case QUERY_RESPONSE:
+ case QUERY_DONE:
+ break;
+ case QUERY_DESTROY:
+ pthread_mutex_unlock(&query->lock);
+ return;
+ }
+
+ while (query->state != QUERY_DONE)
+ pthread_cond_wait(&query->cond, &query->lock);
+
+ pthread_mutex_unlock(&query->lock);
+
+ pthread_cond_destroy(&query->cond);
+ pthread_mutex_destroy(&query->lock);
+
+ free(query->hash);
+ free(query);
+}
+
static struct reg_entry * reg_entry_create(uint8_t * hash)
{
struct reg_entry * entry = malloc(sizeof(*entry));
@@ -151,7 +185,7 @@ static void clear_dir_queries(struct shim_data * data)
list_for_each_safe(h, t, &data->dir_queries) {
struct dir_query * e = list_entry(h, struct dir_query, next);
list_del(&e->next);
- shim_data_dir_query_destroy(e);
+ destroy_dir_query(e);
}
}
@@ -391,7 +425,8 @@ uint64_t shim_data_dir_get_addr(struct shim_data * data,
return addr;
}
-struct dir_query * shim_data_dir_query_create(const uint8_t * hash)
+struct dir_query * shim_data_dir_query_create(struct shim_data * data,
+ const uint8_t * hash)
{
struct dir_query * query;
pthread_condattr_t cattr;
@@ -417,58 +452,64 @@ struct dir_query * shim_data_dir_query_create(const uint8_t * hash)
list_head_init(&query->next);
+ pthread_mutex_lock(&data->dir_queries_lock);
+ list_add(&query->next, &data->dir_queries);
+ pthread_mutex_unlock(&data->dir_queries_lock);
+
return query;
}
-void shim_data_dir_query_respond(struct dir_query * query)
+void shim_data_dir_query_respond(struct shim_data * data,
+ const uint8_t * hash)
{
- assert(query);
+ struct dir_query * e = NULL;
+ struct list_head * pos;
+ bool found = false;
- pthread_mutex_lock(&query->lock);
-
- if (query->state != QUERY_PENDING) {
- pthread_mutex_unlock(&query->lock);
- return;
- }
-
- query->state = QUERY_RESPONSE;
- pthread_cond_broadcast(&query->cond);
+ pthread_mutex_lock(&data->dir_queries_lock);
- while (query->state == QUERY_RESPONSE)
- pthread_cond_wait(&query->cond, &query->lock);
+ list_for_each(pos, &data->dir_queries) {
+ e = list_entry(pos, struct dir_query, next);
- pthread_mutex_unlock(&query->lock);
-}
+ if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0) {
+ found = true;
+ break;
+ }
+ }
-void shim_data_dir_query_destroy(struct dir_query * query)
-{
- assert(query);
+ if (!found) {
+ pthread_mutex_unlock(&data->dir_queries_lock);
+ return;
+ }
- pthread_mutex_lock(&query->lock);
+ pthread_mutex_lock(&e->lock);
- if (query->state == QUERY_DESTROY) {
- pthread_mutex_unlock(&query->lock);
+ if (e->state != QUERY_PENDING) {
+ pthread_mutex_unlock(&e->lock);
+ pthread_mutex_unlock(&data->dir_queries_lock);
return;
}
- if (query->state == QUERY_INIT)
- query->state = QUERY_DONE;
+ e->state = QUERY_RESPONSE;
+ pthread_cond_broadcast(&e->cond);
- if (query->state == QUERY_PENDING) {
- query->state = QUERY_DESTROY;
- pthread_cond_broadcast(&query->cond);
- }
+ while (e->state == QUERY_RESPONSE)
+ pthread_cond_wait(&e->cond, &e->lock);
- while (query->state != QUERY_DONE)
- pthread_cond_wait(&query->cond, &query->lock);
+ pthread_mutex_unlock(&e->lock);
- pthread_mutex_unlock(&query->lock);
+ pthread_mutex_unlock(&data->dir_queries_lock);
+}
- pthread_cond_destroy(&query->cond);
- pthread_mutex_destroy(&query->lock);
+void shim_data_dir_query_destroy(struct shim_data * data,
+ struct dir_query * query)
+{
+ pthread_mutex_lock(&data->dir_queries_lock);
- free(query->hash);
- free(query);
+ list_del(&query->next);
+ destroy_dir_query(query);
+
+ pthread_mutex_unlock(&data->dir_queries_lock);
}
int shim_data_dir_query_wait(struct dir_query * query,
diff --git a/src/ipcpd/shim-data.h b/src/ipcpd/shim-data.h
index 983f97f6..6380eea7 100644
--- a/src/ipcpd/shim-data.h
+++ b/src/ipcpd/shim-data.h
@@ -85,11 +85,14 @@ bool shim_data_dir_has(struct shim_data * data,
uint64_t shim_data_dir_get_addr(struct shim_data * data,
const uint8_t * hash);
-struct dir_query * shim_data_dir_query_create(const uint8_t * hash);
+struct dir_query * shim_data_dir_query_create(struct shim_data * data,
+ const uint8_t * hash);
-void shim_data_dir_query_respond(struct dir_query * query);
+void shim_data_dir_query_destroy(struct shim_data * data,
+ struct dir_query * query);
-void shim_data_dir_query_destroy(struct dir_query * query);
+void shim_data_dir_query_respond(struct shim_data * data,
+ const uint8_t * hash);
int shim_data_dir_query_wait(struct dir_query * query,
const struct timespec * timeout);
diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c
index e5f0cba8..b8e987ba 100644
--- a/src/ipcpd/shim-eth-llc/main.c
+++ b/src/ipcpd/shim-eth-llc/main.c
@@ -512,24 +512,13 @@ static int eth_llc_ipcp_name_query_req(const uint8_t * hash,
static int eth_llc_ipcp_name_query_reply(const uint8_t * hash,
uint8_t * r_addr)
{
- uint64_t address = 0;
- struct list_head * pos;
+ uint64_t address = 0;
memcpy(&address, r_addr, MAC_SIZE);
shim_data_dir_add_entry(eth_llc_data.shim_data, hash, address);
- pthread_mutex_lock(&eth_llc_data.shim_data->dir_queries_lock);
-
- list_for_each(pos, &eth_llc_data.shim_data->dir_queries) {
- struct dir_query * e =
- list_entry(pos, struct dir_query, next);
- if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0) {
- shim_data_dir_query_respond(e);
- }
- }
-
- pthread_mutex_unlock(&eth_llc_data.shim_data->dir_queries_lock);
+ shim_data_dir_query_respond(eth_llc_data.shim_data, hash);
return 0;
}
@@ -1053,22 +1042,15 @@ static int eth_llc_ipcp_query(const uint8_t * hash)
memset(r_addr, 0xff, MAC_SIZE);
- query = shim_data_dir_query_create(hash);
+ query = shim_data_dir_query_create(eth_llc_data.shim_data, hash);
if (query == NULL)
return -1;
- pthread_mutex_lock(&eth_llc_data.shim_data->dir_queries_lock);
- list_add(&query->next, &eth_llc_data.shim_data->dir_queries);
- pthread_mutex_unlock(&eth_llc_data.shim_data->dir_queries_lock);
-
eth_llc_ipcp_send_mgmt_frame(&msg, r_addr);
ret = shim_data_dir_query_wait(query, &timeout);
- pthread_mutex_lock(&eth_llc_data.shim_data->dir_queries_lock);
- list_del(&query->next);
- shim_data_dir_query_destroy(query);
- pthread_mutex_unlock(&eth_llc_data.shim_data->dir_queries_lock);
+ shim_data_dir_query_destroy(eth_llc_data.shim_data, query);
return ret;
}