ovs_events: Fix notification metadata garbage.
[collectd.git] / src / ovs_events.c
index d973591..35f749c 100644 (file)
@@ -25,6 +25,8 @@
  *   Volodymyr Mytnyk <volodymyrx.mytnyk@intel.com>
  **/
 
+#include "collectd.h"
+
 #include "common.h" /* auxiliary functions */
 
 #include "utils_ovs.h" /* OVS helpers */
@@ -33,7 +35,6 @@
 #define OVS_EVENTS_IFACE_UUID_SIZE 64
 #define OVS_EVENTS_EXT_IFACE_ID_SIZE 64
 #define OVS_EVENTS_EXT_VM_UUID_SIZE 64
-#define OVS_EVENTS_OVS_DB_URL_SIZE 64
 #define OVS_EVENTS_PLUGIN "ovs_events"
 #define OVS_EVENTS_CTX_LOCK                                                    \
   for (int __i = ovs_events_ctx_lock(); __i != 0; __i = ovs_events_ctx_unlock())
@@ -67,9 +68,11 @@ typedef struct ovs_events_iface_list_s ovs_events_iface_list_t;
 
 /* OVS events configuration data */
 struct ovs_events_config_s {
-  _Bool send_notification; /* sent notification to collectd? */
-  char ovs_db_server_url[OVS_EVENTS_OVS_DB_URL_SIZE]; /* OVS DB server URL */
-  ovs_events_iface_list_t *ifaces;                    /* interface info */
+  _Bool send_notification;                 /* sent notification to collectd? */
+  char ovs_db_node[OVS_DB_ADDR_NODE_SIZE]; /* OVS DB node */
+  char ovs_db_serv[OVS_DB_ADDR_SERVICE_SIZE]; /* OVS DB service */
+  char ovs_db_unix[OVS_DB_ADDR_UNIX_SIZE];    /* OVS DB unix socket path */
+  ovs_events_iface_list_t *ifaces;            /* interface info */
 };
 typedef struct ovs_events_config_s ovs_events_config_t;
 
@@ -88,9 +91,10 @@ typedef struct ovs_events_ctx_s ovs_events_ctx_t;
  */
 static ovs_events_ctx_t ovs_events_ctx = {
     .mutex = PTHREAD_MUTEX_INITIALIZER,
-    .config = {.send_notification = 0, /* do not send notification */
-               .ovs_db_server_url =
-                   "tcp:127.0.0.1:6640", /* use default OVS DB URL */
+    .config = {.send_notification = 0,     /* do not send notification */
+               .ovs_db_node = "localhost", /* use default OVS DB node */
+               .ovs_db_serv = "6640",      /* use default OVS DB service */
+               .ovs_db_unix = "",          /* UNIX path empty by default */
                .ifaces = NULL},
     .ovs_db_select_params = NULL,
     .is_db_available = 0,
@@ -99,7 +103,7 @@ static ovs_events_ctx_t ovs_events_ctx = {
 /* This function is used only by "OVS_EVENTS_CTX_LOCK" define (see above).
  * It always returns 1 when context is locked.
  */
-static inline int ovs_events_ctx_lock() {
+static int ovs_events_ctx_lock() {
   pthread_mutex_lock(&ovs_events_ctx.mutex);
   return (1);
 }
@@ -107,7 +111,7 @@ static inline int ovs_events_ctx_lock() {
 /* This function is used only by "OVS_EVENTS_CTX_LOCK" define (see above).
  * It always returns 0 when context is unlocked.
  */
-static inline int ovs_events_ctx_unlock() {
+static int ovs_events_ctx_unlock() {
   pthread_mutex_unlock(&ovs_events_ctx.mutex);
   return (0);
 }
@@ -118,25 +122,25 @@ static inline int ovs_events_ctx_unlock() {
  */
 static int ovs_events_config_iface_exists(const char *ifname) {
   if (ovs_events_ctx.config.ifaces == NULL)
-    return -1;
+    return (-1);
 
   /* check if given interface exists */
   for (ovs_events_iface_list_t *iface = ovs_events_ctx.config.ifaces; iface;
        iface = iface->next)
-    return (strcmp(ifname, iface->name) == 0);
+    if (strcmp(ifname, iface->name) == 0)
+      return (1);
 
-  return 0;
+  return (0);
 }
 
 /* Get OVS DB select parameter request based on rfc7047,
  * "Transact" & "Select" section
  */
-static inline char *ovs_events_get_select_params() {
+static char *ovs_events_get_select_params() {
   int ret = 0;
   size_t buff_size = 0;
-  size_t offset = 0;
-  char *buff = NULL;
-  char *new_buff = NULL;
+  size_t buff_off = 0;
+  char *opt_buff = NULL;
   const char params_fmt[] = "[\"Open_vSwitch\"%s]";
   const char option_fmt[] = ",{\"op\":\"select\",\"table\":\"Interface\","
                             "\"where\":[[\"name\",\"==\",\"%s\"]],"
@@ -147,40 +151,40 @@ static inline char *ovs_events_get_select_params() {
                              "\"external_ids\",\"name\",\"_uuid\"]}";
   /* setup OVS DB interface condition */
   for (ovs_events_iface_list_t *iface = ovs_events_ctx.config.ifaces; iface;
-       iface = iface->next, offset += ret) {
+       iface = iface->next, buff_off += ret) {
     /* allocate new buffer (format size + ifname len is good enough) */
     buff_size += (sizeof(option_fmt) + strlen(iface->name));
-    new_buff = realloc(buff, buff_size);
-    if (new_buff == NULL)
-      goto failure;
-    buff = new_buff;
-    ret = ssnprintf(buff + offset, buff_size, option_fmt, iface->name);
-    if (ret < 0)
-      goto failure;
+    char *new_buff = realloc(opt_buff, buff_size);
+    if (new_buff == NULL) {
+      sfree(opt_buff);
+      return NULL;
+    }
+    opt_buff = new_buff;
+    ret = ssnprintf(opt_buff + buff_off, buff_size - buff_off, option_fmt,
+                    iface->name);
+    if (ret < 0) {
+      sfree(opt_buff);
+      return NULL;
+    }
   }
   /* if no interfaces are configured, use default params */
-  if (buff == NULL) {
-    buff = strdup(default_opt);
-    offset = strlen(default_opt);
-  }
+  if (opt_buff == NULL)
+    opt_buff = strdup(default_opt);
 
   /* allocate memory for OVS DB select params */
-  buff_size = offset + sizeof(params_fmt);
-  new_buff = malloc(buff_size);
-  if (new_buff == NULL)
-    goto failure;
+  size_t params_size = sizeof(params_fmt) + strlen(opt_buff);
+  char *params_buff = malloc(params_size);
+  if (params_buff == NULL) {
+    sfree(opt_buff);
+    return NULL;
+  }
 
   /* create OVS DB select params */
-  if (ssnprintf(new_buff, buff_size, params_fmt, buff) < 0)
-    goto failure;
+  if (ssnprintf(params_buff, params_size, params_fmt, opt_buff) < 0)
+    sfree(params_buff);
 
-  sfree(buff);
-  return new_buff;
-
-failure:
-  sfree(new_buff);
-  sfree(buff);
-  return NULL;
+  sfree(opt_buff);
+  return params_buff;
 }
 
 /* Release memory allocated for configuration data */
@@ -203,13 +207,23 @@ static int ovs_events_plugin_config(oconfig_item_t *ci) {
   for (int i = 0; i < ci->children_num; i++) {
     oconfig_item_t *child = ci->children + i;
     if (strcasecmp("SendNotification", child->key) == 0) {
-      if (cf_util_get_boolean(child, &ovs_events_ctx.config.send_notification) <
-          0)
+      if (cf_util_get_boolean(child,
+                              &ovs_events_ctx.config.send_notification) != 0)
+        OVS_EVENTS_CONFIG_ERROR(child->key);
+    } else if (strcasecmp("Address", child->key) == 0) {
+      if (cf_util_get_string_buffer(
+              child, ovs_events_ctx.config.ovs_db_node,
+              sizeof(ovs_events_ctx.config.ovs_db_node)) != 0)
+        OVS_EVENTS_CONFIG_ERROR(child->key);
+    } else if (strcasecmp("Port", child->key) == 0) {
+      if (cf_util_get_string_buffer(
+              child, ovs_events_ctx.config.ovs_db_serv,
+              sizeof(ovs_events_ctx.config.ovs_db_serv)) != 0)
         OVS_EVENTS_CONFIG_ERROR(child->key);
-    } else if (strcasecmp("OvsDbServerUrl", child->key) == 0) {
+    } else if (strcasecmp("Socket", child->key) == 0) {
       if (cf_util_get_string_buffer(
-              child, ovs_events_ctx.config.ovs_db_server_url,
-              sizeof(ovs_events_ctx.config.ovs_db_server_url)) < 0)
+              child, ovs_events_ctx.config.ovs_db_unix,
+              sizeof(ovs_events_ctx.config.ovs_db_unix)) != 0)
         OVS_EVENTS_CONFIG_ERROR(child->key);
     } else if (strcasecmp("Interfaces", child->key) == 0) {
       for (int j = 0; j < child->values_num; j++) {
@@ -354,6 +368,9 @@ static int ovs_events_get_iface_info(yajl_val jobject,
   if (!YAJL_IS_OBJECT(jobject))
     return (-1);
 
+  /* zero the interface info structure */
+  memset(ifinfo, 0, sizeof(*ifinfo));
+
   /* try to find external_ids, name and link_state fields */
   jexternal_ids = ovs_utils_get_value_by_key(jobject, "external_ids");
   if (jexternal_ids == NULL || ifinfo == NULL)
@@ -455,15 +472,18 @@ static void ovs_events_table_update_cb(yajl_val jupdates) {
             " :unexpected interface information data received");
       return;
     }
-    if (ovs_events_config_iface_exists(ifinfo.name) != 0)
+    if (ovs_events_config_iface_exists(ifinfo.name) != 0) {
+      DEBUG("name=%s, uuid=%s, ext_iface_id=%s, ext_vm_uuid=%s", ifinfo.name,
+            ifinfo.uuid, ifinfo.ext_iface_id, ifinfo.ext_vm_uuid);
       /* dispatch notification */
       ovs_events_dispatch_notification(&ifinfo);
+    }
   }
 }
 
-/* OVD DB reply callback. It parses reply, receives
+/* OVS DB reply callback. It parses reply, receives
  * interface information and dispatches the info to
- * collecd
+ * collectd
  */
 static void ovs_events_poll_result_cb(yajl_val jresult, yajl_val jerror) {
   yajl_val *jvalues = NULL;
@@ -491,7 +511,6 @@ static void ovs_events_poll_result_cb(yajl_val jresult, yajl_val jerror) {
     }
     /* get interfaces info */
     for (int j = 0; j < YAJL_GET_ARRAY(jvalue)->len; j++) {
-      memset(&ifinfo, 0, sizeof(ifinfo));
       if (ovs_events_get_iface_info(YAJL_GET_ARRAY(jvalue)->values[j],
                                     &ifinfo) < 0) {
         ERROR(OVS_EVENTS_PLUGIN
@@ -524,7 +543,7 @@ static void ovs_events_conn_initialize(ovs_db_t *pdb) {
     }
   }
   OVS_EVENTS_CTX_LOCK { ovs_events_ctx.is_db_available = 1; }
-  DEBUG(OVS_EVENTS_PLUGIN ": OVS DB has been initialized");
+  DEBUG(OVS_EVENTS_PLUGIN ": OVS DB connection has been initialized");
 }
 
 /* OVS DB terminate connection notification callback */
@@ -556,8 +575,9 @@ static int ovs_events_plugin_init(void) {
   ovs_db_callback_t cb = {.post_conn_init = ovs_events_conn_initialize,
                           .post_conn_terminate = ovs_events_conn_terminate};
 
-  DEBUG(OVS_EVENTS_PLUGIN ": OVS DB url = %s",
-        ovs_events_ctx.config.ovs_db_server_url);
+  DEBUG(OVS_EVENTS_PLUGIN ": OVS DB address=%s, service=%s, unix=%s",
+        ovs_events_ctx.config.ovs_db_node, ovs_events_ctx.config.ovs_db_serv,
+        ovs_events_ctx.config.ovs_db_unix);
 
   /* generate OVS DB select condition based on list on configured interfaces */
   ovs_events_ctx.ovs_db_select_params = ovs_events_get_select_params();
@@ -567,7 +587,9 @@ static int ovs_events_plugin_init(void) {
   }
 
   /* initialize OVS DB */
-  ovs_db = ovs_db_init(ovs_events_ctx.config.ovs_db_server_url, &cb);
+  ovs_db = ovs_db_init(ovs_events_ctx.config.ovs_db_node,
+                       ovs_events_ctx.config.ovs_db_serv,
+                       ovs_events_ctx.config.ovs_db_unix, &cb);
   if (ovs_db == NULL) {
     ERROR(OVS_EVENTS_PLUGIN ": fail to connect to OVS DB server");
     goto ovs_events_failure;