* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#define OVS_DB_POLL_READ_BLOCK_SIZE 512 /* read block size (bytes) */
#define OVS_DB_DEFAULT_DB_NAME "Open_vSwitch"
#define OVS_DB_POLL_READ_BLOCK_SIZE 512 /* read block size (bytes) */
#define OVS_DB_DEFAULT_DB_NAME "Open_vSwitch"
#define OVS_DB_EVENT_TIMEOUT 5 /* event thread timeout (sec) */
#define OVS_DB_EVENT_TERMINATE 1
#define OVS_DB_EVENT_CONN_ESTABLISHED 2
#define OVS_DB_EVENT_TIMEOUT 5 /* event thread timeout (sec) */
#define OVS_DB_EVENT_TERMINATE 1
#define OVS_DB_EVENT_CONN_ESTABLISHED 2
pthread_mutex_lock(&pdb->poll_thread.mutex);
state = pdb->poll_thread.state;
pthread_mutex_unlock(&pdb->poll_thread.mutex);
pthread_mutex_lock(&pdb->poll_thread.mutex);
state = pdb->poll_thread.state;
pthread_mutex_unlock(&pdb->poll_thread.mutex);
/* Remove all callbacks form OVS DB object */
static void ovs_db_callback_remove_all(ovs_db_t *pdb) {
pthread_mutex_lock(&pdb->mutex);
/* Remove all callbacks form OVS DB object */
static void ovs_db_callback_remove_all(ovs_db_t *pdb) {
pthread_mutex_lock(&pdb->mutex);
while (rem > 0) {
if ((nbytes = send(pdb->sock, data + off, rem, 0)) <= 0)
while (rem > 0) {
if ((nbytes = send(pdb->sock, data + off, rem, 0)) <= 0)
if (YAJL_IS_STRING(jval))
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, YAJL_GET_STRING(jval));
if (YAJL_IS_STRING(jval))
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, YAJL_GET_STRING(jval));
array_len = YAJL_GET_ARRAY(jval)->len;
jvalues = YAJL_GET_ARRAY(jval)->values;
OVS_YAJL_CALL(yajl_gen_array_open, jgen);
array_len = YAJL_GET_ARRAY(jval)->len;
jvalues = YAJL_GET_ARRAY(jval)->values;
OVS_YAJL_CALL(yajl_gen_array_open, jgen);
OVS_YAJL_CALL(ovs_yajl_gen_val, jgen, jvalues[i]);
OVS_YAJL_CALL(yajl_gen_array_close, jgen);
} else if (YAJL_IS_OBJECT(jval)) {
/* create new object and add all elements into the object */
OVS_YAJL_CALL(yajl_gen_map_open, jgen);
obj_len = YAJL_GET_OBJECT(jval)->len;
OVS_YAJL_CALL(ovs_yajl_gen_val, jgen, jvalues[i]);
OVS_YAJL_CALL(yajl_gen_array_close, jgen);
} else if (YAJL_IS_OBJECT(jval)) {
/* create new object and add all elements into the object */
OVS_YAJL_CALL(yajl_gen_map_open, jgen);
obj_len = YAJL_GET_OBJECT(jval)->len;
obj_key = YAJL_GET_OBJECT(jval)->keys[i];
jobj_value = YAJL_GET_OBJECT(jval)->values[i];
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, obj_key);
obj_key = YAJL_GET_OBJECT(jval)->keys[i];
jobj_value = YAJL_GET_OBJECT(jval)->values[i];
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, obj_key);
/* check & get request attributes */
if ((jparams = yajl_tree_get(jnode, params_path, yajl_t_array)) == NULL ||
/* check & get request attributes */
if ((jparams = yajl_tree_get(jnode, params_path, yajl_t_array)) == NULL ||
const char *params_path[] = {"params", NULL};
const char *id_path[] = {"id", NULL};
const char *params_path[] = {"params", NULL};
const char *id_path[] = {"id", NULL};
if ((jparams = yajl_tree_get(jnode, params_path, yajl_t_array)) == NULL ||
(yajl_tree_get(jnode, id_path, yajl_t_null) == NULL)) {
OVS_ERROR("invalid OVS DB request received");
if ((jparams = yajl_tree_get(jnode, params_path, yajl_t_array)) == NULL ||
(yajl_tree_get(jnode, id_path, yajl_t_null) == NULL)) {
OVS_ERROR("invalid OVS DB request received");
}
/* check array length: [<json-value>, <table-updates>] */
if ((YAJL_GET_ARRAY(jparams) == NULL) ||
(YAJL_GET_ARRAY(jparams)->len != 2)) {
OVS_ERROR("invalid OVS DB request received");
}
/* check array length: [<json-value>, <table-updates>] */
if ((YAJL_GET_ARRAY(jparams) == NULL) ||
(YAJL_GET_ARRAY(jparams)->len != 2)) {
OVS_ERROR("invalid OVS DB request received");
}
jvalue = YAJL_GET_ARRAY(jparams)->values[0];
jtable_updates = YAJL_GET_ARRAY(jparams)->values[1];
if ((!YAJL_IS_OBJECT(jtable_updates)) || (!YAJL_IS_STRING(jvalue))) {
OVS_ERROR("invalid OVS DB request id or table update received");
}
jvalue = YAJL_GET_ARRAY(jparams)->values[0];
jtable_updates = YAJL_GET_ARRAY(jparams)->values[1];
if ((!YAJL_IS_OBJECT(jtable_updates)) || (!YAJL_IS_STRING(jvalue))) {
OVS_ERROR("invalid OVS DB request id or table update received");
if (cb == NULL || cb->table.call == NULL) {
OVS_ERROR("No OVS DB table update callback found");
pthread_mutex_unlock(&pdb->mutex);
if (cb == NULL || cb->table.call == NULL) {
OVS_ERROR("No OVS DB table update callback found");
pthread_mutex_unlock(&pdb->mutex);
/* duplicate the data to make null-terminated string
* required for yajl_tree_parse() */
if ((sjson = calloc(1, len + 1)) == NULL)
/* duplicate the data to make null-terminated string
* required for yajl_tree_parse() */
if ((sjson = calloc(1, len + 1)) == NULL)
/* parse json data */
jnode = yajl_tree_parse(sjson, yajl_errbuf, sizeof(yajl_errbuf));
if (jnode == NULL) {
OVS_ERROR("yajl_tree_parse() %s", yajl_errbuf);
sfree(sjson);
/* parse json data */
jnode = yajl_tree_parse(sjson, yajl_errbuf, sizeof(yajl_errbuf));
if (jnode == NULL) {
OVS_ERROR("yajl_tree_parse() %s", yajl_errbuf);
sfree(sjson);
if (strcmp("echo", method) == 0) {
/* echo request from the server */
if (ovs_db_table_echo_cb(pdb, jnode) < 0)
if (strcmp("echo", method) == 0) {
/* echo request from the server */
if (ovs_db_table_echo_cb(pdb, jnode) < 0)
/* allocate new chunk of memory */
new_buff = realloc(jreader->buff_ptr, (jreader->buff_size + data_len));
if (new_buff == NULL)
/* allocate new chunk of memory */
new_buff = realloc(jreader->buff_ptr, (jreader->buff_size + data_len));
if (new_buff == NULL)
/* store input data */
memcpy(jreader->buff_ptr + jreader->buff_offset, data, data_len);
jreader->buff_offset += data_len;
/* store input data */
memcpy(jreader->buff_ptr + jreader->buff_offset, data, data_len);
jreader->buff_offset += data_len;
*json_ptr = jreader->buff_ptr + jreader->json_offset;
*json_len_ptr = json_len + 1;
jreader->json_offset = i + 1;
*json_ptr = jreader->buff_ptr + jreader->json_offset;
*json_len_ptr = json_len + 1;
jreader->json_offset = i + 1;
* and zero rest of the buffer data */
json = &jreader->buff_ptr[jreader->json_offset];
json_len = jreader->buff_offset - jreader->json_offset;
* and zero rest of the buffer data */
json = &jreader->buff_ptr[jreader->json_offset];
json_len = jreader->buff_offset - jreader->json_offset;
}
/* try to connect to the server */
for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) {
}
/* try to connect to the server */
for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) {
- sstrerror(errno, errbuff, sizeof(errbuff));
- OVS_DEBUG("socket(): %s", errbuff);
+ OVS_DEBUG("socket(): %s", STRERRNO);
- sstrerror(errno, errbuff, sizeof(errbuff));
- OVS_DEBUG("connect(): %s [family=%d]", errbuff, rp->ai_family);
+ OVS_DEBUG("connect(): %s [family=%d]", STRERRNO, rp->ai_family);
/* create JSON reader instance */
if ((jreader = ovs_json_reader_alloc()) == NULL) {
OVS_ERROR("initialize json reader failed");
/* create JSON reader instance */
if ((jreader = ovs_json_reader_alloc()) == NULL) {
OVS_ERROR("initialize json reader failed");
- sstrerror(errno, errbuff, sizeof(errbuff));
- OVS_ERROR("poll(): %s", errbuff);
+ OVS_ERROR("poll(): %s", STRERRNO);
char buff[OVS_DB_POLL_READ_BLOCK_SIZE];
ssize_t nbytes = recv(poll_fd.fd, buff, sizeof(buff), 0);
if (nbytes < 0) {
char buff[OVS_DB_POLL_READ_BLOCK_SIZE];
ssize_t nbytes = recv(poll_fd.fd, buff, sizeof(buff), 0);
if (nbytes < 0) {
- sstrerror(errno, errbuff, sizeof(errbuff));
- OVS_ERROR("recv(): %s", errbuff);
+ OVS_ERROR("recv(): %s", STRERRNO);
ts.tv_sec += (OVS_DB_EVENT_TIMEOUT);
int ret = pthread_cond_timedwait(&pdb->event_thread.cond,
&pdb->event_thread.mutex, &ts);
ts.tv_sec += (OVS_DB_EVENT_TIMEOUT);
int ret = pthread_cond_timedwait(&pdb->event_thread.cond,
&pdb->event_thread.mutex, &ts);
/* handle the event */
OVS_DEBUG("handle event %d", pdb->event_thread.value);
switch (pdb->event_thread.value) {
case OVS_DB_EVENT_CONN_ESTABLISHED:
if (pdb->cb.post_conn_init)
pdb->cb.post_conn_init(pdb);
/* handle the event */
OVS_DEBUG("handle event %d", pdb->event_thread.value);
switch (pdb->event_thread.value) {
case OVS_DB_EVENT_CONN_ESTABLISHED:
if (pdb->cb.post_conn_init)
pdb->cb.post_conn_init(pdb);
break;
case OVS_DB_EVENT_CONN_TERMINATED:
if (pdb->cb.post_conn_terminate)
pdb->cb.post_conn_terminate();
break;
case OVS_DB_EVENT_CONN_TERMINATED:
if (pdb->cb.post_conn_terminate)
pdb->cb.post_conn_terminate();
/* init event thread condition variable */
if (pthread_cond_init(&pdb->event_thread.cond, NULL)) {
/* init event thread condition variable */
if (pthread_cond_init(&pdb->event_thread.cond, NULL)) {
}
/* init event thread mutex */
if (pthread_mutex_init(&pdb->event_thread.mutex, NULL)) {
pthread_cond_destroy(&pdb->event_thread.cond);
}
/* init event thread mutex */
if (pthread_mutex_init(&pdb->event_thread.mutex, NULL)) {
pthread_cond_destroy(&pdb->event_thread.cond);
}
/* Hold the event thread mutex. It ensures that no events
* will be lost while thread is still starting. Once event
}
/* Hold the event thread mutex. It ensures that no events
* will be lost while thread is still starting. Once event
if (pthread_mutex_lock(&pdb->event_thread.mutex)) {
pthread_mutex_destroy(&pdb->event_thread.mutex);
pthread_cond_destroy(&pdb->event_thread.cond);
if (pthread_mutex_lock(&pdb->event_thread.mutex)) {
pthread_mutex_destroy(&pdb->event_thread.mutex);
pthread_cond_destroy(&pdb->event_thread.cond);
pthread_mutex_unlock(&pdb->event_thread.mutex);
pthread_mutex_destroy(&pdb->event_thread.mutex);
pthread_cond_destroy(&pdb->event_thread.cond);
pthread_mutex_unlock(&pdb->event_thread.mutex);
pthread_mutex_destroy(&pdb->event_thread.mutex);
pthread_cond_destroy(&pdb->event_thread.cond);
-/* Destroy EVENT thread */
-static int ovs_db_event_thread_destroy(ovs_db_t *pdb) {
- if (pdb->event_thread.tid < 0)
- /* already destroyed */
- return (0);
+/* Terminate EVENT thread */
+static int ovs_db_event_thread_terminate(ovs_db_t *pdb) {
+ if (pthread_equal(pdb->event_thread.tid, (pthread_t){0})) {
+ /* already terminated */
+ return 0;
+ }
ovs_db_event_post(pdb, OVS_DB_EVENT_TERMINATE);
if (pthread_join(pdb->event_thread.tid, NULL) != 0)
ovs_db_event_post(pdb, OVS_DB_EVENT_TERMINATE);
if (pthread_join(pdb->event_thread.tid, NULL) != 0)
/* Event thread always holds the thread mutex when
* performs some task (handles event) and releases it when
* while sleeping. Thus, if event thread exits, the mutex
* remains locked */
/* Event thread always holds the thread mutex when
* performs some task (handles event) and releases it when
* while sleeping. Thus, if event thread exits, the mutex
* remains locked */
/* init event thread mutex */
if (pthread_mutex_init(&pdb->poll_thread.mutex, NULL)) {
/* init event thread mutex */
if (pthread_mutex_init(&pdb->poll_thread.mutex, NULL)) {
if (plugin_thread_create(&tid, NULL, ovs_poll_worker, pdb,
"utils_ovs:poll") != 0) {
pthread_mutex_destroy(&pdb->poll_thread.mutex);
if (plugin_thread_create(&tid, NULL, ovs_poll_worker, pdb,
"utils_ovs:poll") != 0) {
pthread_mutex_destroy(&pdb->poll_thread.mutex);
/* change thread state */
pthread_mutex_lock(&pdb->poll_thread.mutex);
pdb->poll_thread.state = OVS_DB_POLL_STATE_EXITING;
pthread_mutex_unlock(&pdb->poll_thread.mutex);
/* join the thread */
if (pthread_join(pdb->poll_thread.tid, NULL) != 0)
/* change thread state */
pthread_mutex_lock(&pdb->poll_thread.mutex);
pdb->poll_thread.state = OVS_DB_POLL_STATE_EXITING;
pthread_mutex_unlock(&pdb->poll_thread.mutex);
/* join the thread */
if (pthread_join(pdb->poll_thread.tid, NULL) != 0)
const char *unix_path, ovs_db_callback_t *cb) {
/* sanity check */
if (node == NULL || service == NULL || unix_path == NULL)
const char *unix_path, ovs_db_callback_t *cb) {
/* sanity check */
if (node == NULL || service == NULL || unix_path == NULL)
/* store the OVS DB address */
sstrncpy(pdb->node, node, sizeof(pdb->node));
/* store the OVS DB address */
sstrncpy(pdb->node, node, sizeof(pdb->node));
}
/* set OVS DB mutex as recursive */
if (pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE)) {
OVS_ERROR("Failed to set OVS DB mutex as recursive");
pthread_mutexattr_destroy(&mutex_attr);
sfree(pdb);
}
/* set OVS DB mutex as recursive */
if (pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE)) {
OVS_ERROR("Failed to set OVS DB mutex as recursive");
pthread_mutexattr_destroy(&mutex_attr);
sfree(pdb);
}
/* init OVS DB mutex */
if (pthread_mutex_init(&pdb->mutex, &mutex_attr)) {
OVS_ERROR("OVS DB mutex init failed");
pthread_mutexattr_destroy(&mutex_attr);
sfree(pdb);
}
/* init OVS DB mutex */
if (pthread_mutex_init(&pdb->mutex, &mutex_attr)) {
OVS_ERROR("OVS DB mutex init failed");
pthread_mutexattr_destroy(&mutex_attr);
sfree(pdb);
/* try to parse params */
if ((jparams = yajl_tree_parse(params, NULL, 0)) == NULL) {
OVS_ERROR("params is not a JSON string");
yajl_gen_clear(jgen);
/* try to parse params */
if ((jparams = yajl_tree_parse(params, NULL, 0)) == NULL) {
OVS_ERROR("params is not a JSON string");
yajl_gen_clear(jgen);
/* generate id field */
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, "id");
uid = ovs_uid_generate();
/* generate id field */
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, "id");
uid = ovs_uid_generate();
- ssnprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid);
+ snprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid);
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_buff);
OVS_YAJL_CALL(yajl_gen_map_close, jgen);
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_buff);
OVS_YAJL_CALL(yajl_gen_map_close, jgen);
/* allocate new update callback */
if ((new_cb = calloc(1, sizeof(ovs_callback_t))) == NULL)
/* allocate new update callback */
if ((new_cb = calloc(1, sizeof(ovs_callback_t))) == NULL)
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, OVS_DB_DEFAULT_DB_NAME);
/* uid string <json-value> */
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, OVS_DB_DEFAULT_DB_NAME);
/* uid string <json-value> */
- ssnprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid);
+ snprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid);
/* try to lock the structure before releasing */
if ((ret = pthread_mutex_lock(&pdb->mutex))) {
OVS_ERROR("pthread_mutex_lock() DB mutex lock failed (%d)", ret);
/* try to lock the structure before releasing */
if ((ret = pthread_mutex_lock(&pdb->mutex))) {
OVS_ERROR("pthread_mutex_lock() DB mutex lock failed (%d)", ret);
- /* stop event thread */
- if (ovs_db_poll_thread_destroy(pdb) < 0) {
- OVS_ERROR("stop event thread failed");
- ovs_db_ret = (-1);
- }
+ /* destroy event thread private data */
+ ovs_db_event_thread_data_destroy(pdb);
+
+ pthread_mutex_unlock(&pdb->mutex);
obj_key = YAJL_GET_OBJECT(jval)->keys[i];
if (strcmp(obj_key, key) == 0)
return YAJL_GET_OBJECT(jval)->values[i];
obj_key = YAJL_GET_OBJECT(jval)->keys[i];
if (strcmp(obj_key, key) == 0)
return YAJL_GET_OBJECT(jval)->values[i];
/* try to find map value by map key */
map_len = YAJL_GET_ARRAY(array_values[1])->len;
map_values = YAJL_GET_ARRAY(array_values[1])->values;
/* try to find map value by map key */
map_len = YAJL_GET_ARRAY(array_values[1])->len;
map_values = YAJL_GET_ARRAY(array_values[1])->values;