summaryrefslogtreecommitdiffstats
path: root/vnfs/VES/code/evel_library
diff options
context:
space:
mode:
authorplatania <platania@research.att.com>2017-02-16 11:20:22 -0500
committerplatania <platania@research.att.com>2017-02-16 11:20:47 -0500
commit3426556541256f93d2cba65df3b9c8d1d1772861 (patch)
tree56e5b26481400d35e3e2e36be20df953793e348d /vnfs/VES/code/evel_library
parentf525cb9014ae27ddd795f933dee54a78b214a589 (diff)
Initial OpenECOMP Demo commit
Change-Id: Ibf8696196a7ac2c84ac8aa7cde1982c9c89fb64d Signed-off-by: platania <platania@research.att.com>
Diffstat (limited to 'vnfs/VES/code/evel_library')
-rw-r--r--vnfs/VES/code/evel_library/double_list.c194
-rw-r--r--vnfs/VES/code/evel_library/double_list.h70
-rw-r--r--vnfs/VES/code/evel_library/evel.c395
-rw-r--r--vnfs/VES/code/evel_library/evel.h3677
-rw-r--r--vnfs/VES/code/evel_library/evel_event.c568
-rw-r--r--vnfs/VES/code/evel_library/evel_event_mgr.c1053
-rw-r--r--vnfs/VES/code/evel_library/evel_fault.c337
-rw-r--r--vnfs/VES/code/evel_library/evel_internal.h867
-rw-r--r--vnfs/VES/code/evel_library/evel_internal_event.c124
-rw-r--r--vnfs/VES/code/evel_library/evel_json_buffer.c853
-rw-r--r--vnfs/VES/code/evel_library/evel_logging.c181
-rw-r--r--vnfs/VES/code/evel_library/evel_mobile_flow.c2036
-rw-r--r--vnfs/VES/code/evel_library/evel_option.c442
-rw-r--r--vnfs/VES/code/evel_library/evel_other.c231
-rw-r--r--vnfs/VES/code/evel_library/evel_reporting_measurement.c450
-rw-r--r--vnfs/VES/code/evel_library/evel_scaling_measurement.c1711
-rw-r--r--vnfs/VES/code/evel_library/evel_service.c1313
-rw-r--r--vnfs/VES/code/evel_library/evel_signaling.c509
-rw-r--r--vnfs/VES/code/evel_library/evel_state_change.c295
-rw-r--r--vnfs/VES/code/evel_library/evel_strings.c477
-rw-r--r--vnfs/VES/code/evel_library/evel_syslog.c500
-rw-r--r--vnfs/VES/code/evel_library/evel_throttle.c2114
-rw-r--r--vnfs/VES/code/evel_library/evel_throttle.h228
-rw-r--r--vnfs/VES/code/evel_library/jsmn.c311
-rw-r--r--vnfs/VES/code/evel_library/jsmn.h76
-rw-r--r--vnfs/VES/code/evel_library/license.md95
-rw-r--r--vnfs/VES/code/evel_library/metadata.c607
-rw-r--r--vnfs/VES/code/evel_library/metadata.h72
-rw-r--r--vnfs/VES/code/evel_library/quickstart.md445
-rw-r--r--vnfs/VES/code/evel_library/readme.md236
-rw-r--r--vnfs/VES/code/evel_library/ring_buffer.c206
-rw-r--r--vnfs/VES/code/evel_library/ring_buffer.h109
32 files changed, 20782 insertions, 0 deletions
diff --git a/vnfs/VES/code/evel_library/double_list.c b/vnfs/VES/code/evel_library/double_list.c
new file mode 100644
index 00000000..a480accb
--- /dev/null
+++ b/vnfs/VES/code/evel_library/double_list.c
@@ -0,0 +1,194 @@
+/**************************************************************************//**
+ * @file
+ * A simple double-linked list.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <malloc.h>
+
+#include "double_list.h"
+#include "evel.h"
+
+/**************************************************************************//**
+ * List initialization.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param list Pointer to the list to be initialized.
+
+ * @returns Nothing
+******************************************************************************/
+void dlist_initialize(DLIST * list)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(list != NULL);
+
+ /***************************************************************************/
+ /* Initialize the list as empty. */
+ /***************************************************************************/
+ list->head = NULL;
+ list->tail = NULL;
+
+ EVEL_EXIT();
+}
+
+void * dlist_pop_last(DLIST * list)
+{
+ void *item = NULL;
+ DLIST_ITEM *current_tail = NULL;
+ DLIST_ITEM *new_tail = NULL;
+
+ assert(list != NULL);
+
+ current_tail = list->tail;
+ if (current_tail != NULL)
+ {
+ item = current_tail->item;
+ new_tail = current_tail->previous;
+ if (new_tail == NULL)
+ {
+ list->head = NULL;
+ list->tail = NULL;
+ }
+ else
+ {
+ new_tail->next = NULL;
+ list->tail = new_tail;
+ }
+ free(current_tail);
+ }
+
+ return item;
+}
+
+void dlist_push_first(DLIST * list, void * item)
+{
+ DLIST_ITEM * new_element = NULL;
+ DLIST_ITEM * current_head = NULL;
+
+ /***************************************************************************/
+ /* Check assumptions. Note that we do allow putting NULL pointers into */
+ /* the list - not sure you'd want to, but let it happen. */
+ /***************************************************************************/
+ assert(list != NULL);
+
+ current_head = list->head;
+
+ new_element = malloc(sizeof(DLIST_ITEM));
+ assert(new_element != NULL);
+ new_element->next = current_head;
+ new_element->previous = NULL;
+ new_element->item = item;
+ list->head = new_element;
+
+ if (current_head != NULL)
+ {
+ current_head->previous = new_element;
+ }
+ else
+ {
+ list->tail = new_element;
+ }
+}
+
+void dlist_push_last(DLIST * list, void * item)
+{
+ DLIST_ITEM * new_element = NULL;
+ DLIST_ITEM * current_tail = NULL;
+
+ /***************************************************************************/
+ /* Check assumptions. Note that we do allow putting NULL pointers into */
+ /* the list - not sure you'd want to, but let it happen. */
+ /***************************************************************************/
+ assert(list != NULL);
+
+ current_tail = list->tail;
+
+ new_element = malloc(sizeof(DLIST_ITEM));
+ assert(new_element != NULL);
+ new_element->next = NULL;
+ new_element->previous = current_tail;
+ new_element->item = item;
+ list->tail = new_element;
+
+ if (current_tail != NULL)
+ {
+ current_tail->next = new_element;
+ }
+ else
+ {
+ list->head = new_element;
+ }
+}
+
+DLIST_ITEM * dlist_get_first(DLIST * list)
+{
+ return list->head;
+}
+
+DLIST_ITEM * dlist_get_last(DLIST * list)
+{
+ return list->tail;
+}
+
+DLIST_ITEM * dlist_get_next(DLIST_ITEM * item)
+{
+ return item->next;
+}
+
+int dlist_is_empty(DLIST * list)
+{
+ return (list->head == NULL);
+}
+
+int dlist_count(DLIST * list)
+{
+ int count = 0;
+ DLIST_ITEM * item = list->head;
+
+ while (item != NULL)
+ {
+ count++;
+ item = item->next;
+ }
+
+ return count;
+}
diff --git a/vnfs/VES/code/evel_library/double_list.h b/vnfs/VES/code/evel_library/double_list.h
new file mode 100644
index 00000000..e8bdd742
--- /dev/null
+++ b/vnfs/VES/code/evel_library/double_list.h
@@ -0,0 +1,70 @@
+#ifndef DOUBLE_LIST_INCLUDED
+#define DOUBLE_LIST_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * A simple double-linked list.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+typedef struct dlist_item
+{
+ struct dlist_item * previous;
+ struct dlist_item * next;
+ void * item;
+} DLIST_ITEM;
+
+/**************************************************************************//**
+ * Double-linked list structure
+ *****************************************************************************/
+typedef struct dlist
+{
+ DLIST_ITEM * head;
+ DLIST_ITEM * tail;
+} DLIST;
+
+
+void dlist_initialize(DLIST * list);
+void * dlist_pop_last(DLIST * list);
+void dlist_push_first(DLIST * list, void * item);
+void dlist_push_last(DLIST * list, void * item);
+DLIST_ITEM * dlist_get_first(DLIST * list);
+DLIST_ITEM * dlist_get_last(DLIST * list);
+DLIST_ITEM * dlist_get_next(DLIST_ITEM * item);
+int dlist_is_empty(DLIST * list);
+int dlist_count(DLIST * list);
+
+#endif
diff --git a/vnfs/VES/code/evel_library/evel.c b/vnfs/VES/code/evel_library/evel.c
new file mode 100644
index 00000000..3380cace
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel.c
@@ -0,0 +1,395 @@
+/**************************************************************************//**
+ * @file
+ * Source module isolating the ECOMP Vendor Event Listener (EVEL) API.
+ *
+ * This file implements the EVEL library which is intended to provide a
+ * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
+ * that VNFs can use it without worrying about details of:
+ *
+ * * The API's encoding into JSON.
+ * * The API's transport over HTTP/HTTPS.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <curl/curl.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+#include "metadata.h"
+
+/**************************************************************************//**
+ * The type of equipment represented by this VNF.
+ *****************************************************************************/
+EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
+
+/**************************************************************************//**
+ * The Functional Role of the equipment represented by this VNF.
+ *****************************************************************************/
+char *functional_role = NULL;
+
+/**************************************************************************//**
+ * Library initialization.
+ *
+ * Initialize the EVEL library.
+ *
+ * @note This function initializes the cURL library. Applications making use
+ * of libcurl may need to pull the initialization out of here. Note
+ * also that this function is not threadsafe as a result - refer to
+ * libcurl's API documentation for relevant warnings.
+ *
+ * @sa Matching Term function.
+ *
+ * @param fqdn The API's FQDN or IP address.
+ * @param port The API's port.
+ * @param path The optional path (may be NULL).
+ * @param topic The optional topic part of the URL (may be NULL).
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param username Username for Basic Authentication of requests.
+ * @param password Password for Basic Authentication of requests.
+ * @param source_type The kind of node we represent.
+ * @param role The role this node undertakes.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_initialize(const char * const fqdn,
+ int port,
+ const char * const path,
+ const char * const topic,
+ int secure,
+ const char * const username,
+ const char * const password,
+ EVEL_SOURCE_TYPES source_type,
+ const char * const role,
+ int verbosity
+ )
+{
+ EVEL_ERR_CODES rc = EVEL_SUCCESS;
+ char base_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char event_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char path_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char topic_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char version_string[10] = {0};
+ int offset;
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(fqdn != NULL);
+ assert(port > 0 && port <= 65535);
+ assert(source_type < EVEL_MAX_SOURCE_TYPES);
+ assert(role != NULL);
+
+ /***************************************************************************/
+ /* Start logging so we can report on progress. */
+ /***************************************************************************/
+ log_initialize(verbosity == 0 ? EVEL_LOG_INFO : EVEL_LOG_DEBUG, "EVEL");
+ EVEL_INFO("EVEL started");
+ EVEL_INFO("API server is: %s", fqdn);
+ EVEL_INFO("API port is: %d", port);
+
+ if (path != NULL)
+ {
+ EVEL_INFO("API path is: %s", path);
+ }
+ else
+ {
+ EVEL_INFO("No API path");
+ }
+
+ if (topic != NULL)
+ {
+ EVEL_INFO("API topic is: %s", topic);
+ }
+ else
+ {
+ EVEL_INFO("No API topic");
+ }
+
+ EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP");
+ EVEL_INFO("Event Source Type is: %d", source_type);
+ EVEL_INFO("Functional Role is: %s", role);
+ EVEL_INFO("Log verbosity is: %d", verbosity);
+
+ /***************************************************************************/
+ /* Initialize event throttling to the default state. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+
+ /***************************************************************************/
+ /* Save values we will need during operation. */
+ /***************************************************************************/
+ event_source_type = source_type;
+ functional_role = strdup(role);
+
+ /***************************************************************************/
+ /* Ensure there are no trailing zeroes and unnecessary decimal points in */
+ /* the version. */
+ /***************************************************************************/
+ offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
+
+ if (EVEL_API_MINOR_VERSION != 0)
+ {
+ sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
+ }
+
+ /***************************************************************************/
+ /* Build a common base of the API URLs. */
+ /***************************************************************************/
+ strcpy(path_url, "/");
+ snprintf(base_api_url,
+ EVEL_MAX_URL_LEN,
+ "%s://%s:%d%s/eventListener/v%s",
+ secure ? "https" : "http",
+ fqdn,
+ port,
+ (((path != NULL) && (strlen(path) > 0)) ?
+ strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
+ version_string);
+
+ /***************************************************************************/
+ /* Build the URL to the event API. */
+ /***************************************************************************/
+ strcpy(topic_url, "/");
+ snprintf(event_api_url,
+ EVEL_MAX_URL_LEN,
+ "%s%s",
+ base_api_url,
+ (((topic != NULL) && (strlen(topic) > 0)) ?
+ strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
+ EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url);
+
+ /***************************************************************************/
+ /* Build the URL to the throttling API. */
+ /***************************************************************************/
+ snprintf(throt_api_url,
+ EVEL_MAX_URL_LEN,
+ "%s/clientThrottlingState",
+ base_api_url);
+ EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
+
+ /***************************************************************************/
+ /* Spin-up the event-handler, which gets cURL readied for use. */
+ /***************************************************************************/
+ rc = event_handler_initialize(event_api_url,
+ throt_api_url,
+ username,
+ password,
+ verbosity);
+ if (rc != EVEL_SUCCESS)
+ {
+ log_error_state("Failed to initialize event handler (including cURL)");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Extract the metadata from OpenStack. If we fail to extract it, we */
+ /* record that in the logs, but carry on, assuming we're in a test */
+ /* without a metadata service. */
+ /***************************************************************************/
+ rc = openstack_metadata(verbosity);
+ if (rc != EVEL_SUCCESS)
+ {
+ EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
+ rc = EVEL_SUCCESS;
+ }
+
+ /***************************************************************************/
+ /* Start the event handler thread. */
+ /***************************************************************************/
+ rc = event_handler_run();
+ if (rc != EVEL_SUCCESS)
+ {
+ log_error_state("Failed to start event handler thread. "
+ "Error code=%d", rc);
+ goto exit_label;
+ }
+
+exit_label:
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Clean up the EVEL library.
+ *
+ * @note that at present don't expect Init/Term cycling not to leak memory!
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_terminate(void)
+{
+ int rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* First terminate any pending transactions in the event-posting thread. */
+ /***************************************************************************/
+ rc = event_handler_terminate();
+ if (rc != EVEL_SUCCESS)
+ {
+ log_error_state("Failed to terminate EVEL library cleanly!");
+ }
+
+ /***************************************************************************/
+ /* Shut down the Event Handler library in a tidy manner. */
+ /***************************************************************************/
+ curl_global_cleanup();
+
+ /***************************************************************************/
+ /* Clean up allocated memory. */
+ /***************************************************************************/
+ free(functional_role);
+
+ /***************************************************************************/
+ /* Clean up event throttling. */
+ /***************************************************************************/
+ evel_throttle_terminate();
+
+ EVEL_INFO("EVEL stopped");
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Free an event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It is safe to free a NULL pointer.
+ *****************************************************************************/
+void evel_free_event(void * event)
+{
+ EVENT_HEADER * evt_ptr = event;
+ EVEL_ENTER();
+
+ if (event != NULL)
+ {
+ /*************************************************************************/
+ /* Work out what kind of event we're dealing with so we can cast it */
+ /* appropriately. */
+ /*************************************************************************/
+ switch (evt_ptr->event_domain)
+ {
+ case EVEL_DOMAIN_INTERNAL:
+ EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr);
+ evel_free_internal_event((EVENT_INTERNAL *) evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_INTERNAL));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_HEARTBEAT:
+ EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr);
+ evel_free_header(evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_HEADER));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_FAULT:
+ EVEL_DEBUG("Event is a Fault at %lp", evt_ptr);
+ evel_free_fault((EVENT_FAULT *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_FAULT));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_MEASUREMENT:
+ EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr);
+ evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_MOBILE_FLOW:
+ EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr);
+ evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_REPORT:
+ EVEL_DEBUG("Event is a Report at %lp", evt_ptr);
+ evel_free_report((EVENT_REPORT *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_REPORT));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_SERVICE:
+ EVEL_DEBUG("Event is a Service Event at %lp", evt_ptr);
+ evel_free_service((EVENT_SERVICE *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_SERVICE));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_SIGNALING:
+ EVEL_DEBUG("Event is a Signaling at %lp", evt_ptr);
+ evel_free_signaling((EVENT_SIGNALING *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_SIGNALING));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_STATE_CHANGE:
+ EVEL_DEBUG("Event is a State Change at %lp", evt_ptr);
+ evel_free_state_change((EVENT_STATE_CHANGE *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_STATE_CHANGE));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_SYSLOG:
+ EVEL_DEBUG("Event is a Syslog at %lp", evt_ptr);
+ evel_free_syslog((EVENT_SYSLOG *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_SYSLOG));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_OTHER:
+ EVEL_DEBUG("Event is an Other at %lp", evt_ptr);
+ evel_free_other((EVENT_OTHER *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_OTHER));
+ free(evt_ptr);
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);
+ assert(0);
+ }
+ }
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel.h b/vnfs/VES/code/evel_library/evel.h
new file mode 100644
index 00000000..a97dadc8
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel.h
@@ -0,0 +1,3677 @@
+#ifndef EVEL_INCLUDED
+#define EVEL_INCLUDED
+/**************************************************************************//**
+ * @file
+ * Header for EVEL library
+ *
+ * This file implements the EVEL library which is intended to provide a
+ * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
+ * that VNFs can use it without worrying about details of the API transport.
+ *
+ * Zero return value is success (::EVEL_SUCCESS), non-zero is failure and will
+ * be one of ::EVEL_ERR_CODES.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "double_list.h"
+
+/*****************************************************************************/
+/* Supported API version. */
+/*****************************************************************************/
+#define EVEL_API_MAJOR_VERSION 3
+#define EVEL_API_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * Error codes
+ *
+ * Error codes for EVEL low level interface
+ *****************************************************************************/
+typedef enum {
+ EVEL_SUCCESS, /** The operation was successful. */
+ EVEL_ERR_GEN_FAIL, /** Non-specific failure. */
+ EVEL_CURL_LIBRARY_FAIL, /** A cURL library operation failed. */
+ EVEL_PTHREAD_LIBRARY_FAIL, /** A Posix threads operation failed. */
+ EVEL_OUT_OF_MEMORY, /** A memory allocation failure occurred. */
+ EVEL_EVENT_BUFFER_FULL, /** Too many events in the ring-buffer. */
+ EVEL_EVENT_HANDLER_INACTIVE, /** Attempt to raise event when inactive. */
+ EVEL_NO_METADATA, /** Failed to retrieve OpenStack metadata. */
+ EVEL_BAD_METADATA, /** OpenStack metadata invalid format. */
+ EVEL_BAD_JSON_FORMAT, /** JSON failed to parse correctly. */
+ EVEL_JSON_KEY_NOT_FOUND, /** Failed to find the specified JSON key. */
+ EVEL_MAX_ERROR_CODES /** Maximum number of valid error codes. */
+} EVEL_ERR_CODES;
+
+/**************************************************************************//**
+ * Logging levels
+ *
+ * Variable levels of verbosity in the logging functions.
+ *****************************************************************************/
+typedef enum {
+ EVEL_LOG_MIN = 0,
+ EVEL_LOG_SPAMMY = 30,
+ EVEL_LOG_DEBUG = 40,
+ EVEL_LOG_INFO = 50,
+ EVEL_LOG_ERROR = 60,
+ EVEL_LOG_MAX = 101
+} EVEL_LOG_LEVELS;
+
+/*****************************************************************************/
+/* Maximum string lengths. */
+/*****************************************************************************/
+#define EVEL_MAX_STRING_LEN 4096
+#define EVEL_MAX_JSON_BODY 16000
+#define EVEL_MAX_ERROR_STRING_LEN 255
+#define EVEL_MAX_URL_LEN 511
+
+/**************************************************************************//**
+ * This value represents there being no restriction on the reporting interval.
+ *****************************************************************************/
+static const int EVEL_MEASUREMENT_INTERVAL_UKNOWN = 0;
+
+/**************************************************************************//**
+ * How many events can be backed-up before we start dropping events on the
+ * floor.
+ *
+ * @note This value should be tuned in accordance with expected burstiness of
+ * the event load and the expected response time of the ECOMP event
+ * listener so that the probability of the buffer filling is suitably
+ * low.
+ *****************************************************************************/
+static const int EVEL_EVENT_BUFFER_DEPTH = 100;
+
+/*****************************************************************************/
+/* How many different IP Types-of-Service are supported. */
+/*****************************************************************************/
+#define EVEL_TOS_SUPPORTED 256
+
+/**************************************************************************//**
+ * Event domains for the various events we support.
+ * JSON equivalent field: domain
+ *****************************************************************************/
+typedef enum {
+ EVEL_DOMAIN_INTERNAL, /** Internal event, not for external routing. */
+ EVEL_DOMAIN_HEARTBEAT, /** A Heartbeat event (event header only). */
+ EVEL_DOMAIN_FAULT, /** A Fault event. */
+ EVEL_DOMAIN_MEASUREMENT, /** A Measurement for VF Scaling event. */
+ EVEL_DOMAIN_MOBILE_FLOW, /** A Mobile Flow event. */
+ EVEL_DOMAIN_REPORT, /** A Measurement for VF Reporting event. */
+ EVEL_DOMAIN_SERVICE, /** A Service event. */
+ EVEL_DOMAIN_SIGNALING, /** A Signaling event. */
+ EVEL_DOMAIN_STATE_CHANGE, /** A State Change event. */
+ EVEL_DOMAIN_SYSLOG, /** A Syslog event. */
+ EVEL_DOMAIN_OTHER, /** Another event. */
+ EVEL_MAX_DOMAINS /** Maximum number of recognized Event types. */
+} EVEL_EVENT_DOMAINS;
+
+/**************************************************************************//**
+ * Event priorities.
+ * JSON equivalent field: priority
+ *****************************************************************************/
+typedef enum {
+ EVEL_PRIORITY_HIGH,
+ EVEL_PRIORITY_MEDIUM,
+ EVEL_PRIORITY_NORMAL,
+ EVEL_PRIORITY_LOW,
+ EVEL_MAX_PRIORITIES
+} EVEL_EVENT_PRIORITIES;
+
+/**************************************************************************//**
+ * Fault / Threshold severities.
+ * JSON equivalent field: eventSeverity
+ *****************************************************************************/
+typedef enum {
+ EVEL_SEVERITY_CRITICAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SEVERITY_MINOR,
+ EVEL_SEVERITY_WARNING,
+ EVEL_SEVERITY_NORMAL,
+ EVEL_MAX_SEVERITIES
+} EVEL_SEVERITIES;
+
+/**************************************************************************//**
+ * Fault source types.
+ * JSON equivalent field: eventSourceType
+ *****************************************************************************/
+typedef enum {
+ EVEL_SOURCE_OTHER,
+ EVEL_SOURCE_ROUTER,
+ EVEL_SOURCE_SWITCH,
+ EVEL_SOURCE_HOST,
+ EVEL_SOURCE_CARD,
+ EVEL_SOURCE_PORT,
+ EVEL_SOURCE_SLOT_THRESHOLD,
+ EVEL_SOURCE_PORT_THRESHOLD,
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION,
+ /***************************************************************************/
+ /* START OF VENDOR-SPECIFIC VALUES */
+ /* */
+ /* Vendor-specific values should be added here, and handled appropriately */
+ /* in evel_event.c. */
+ /***************************************************************************/
+
+ /***************************************************************************/
+ /* END OF VENDOR-SPECIFIC VALUES */
+ /***************************************************************************/
+ EVEL_MAX_SOURCE_TYPES
+} EVEL_SOURCE_TYPES;
+
+/**************************************************************************//**
+ * Fault VNF Status.
+ * JSON equivalent field: vfStatus
+ *****************************************************************************/
+typedef enum {
+ EVEL_VF_STATUS_ACTIVE,
+ EVEL_VF_STATUS_IDLE,
+ EVEL_VF_STATUS_PREP_TERMINATE,
+ EVEL_VF_STATUS_READY_TERMINATE,
+ EVEL_VF_STATUS_REQ_TERMINATE,
+ EVEL_MAX_VF_STATUSES
+} EVEL_VF_STATUSES;
+
+/**************************************************************************//**
+ * Counter criticalities.
+ * JSON equivalent field: criticality
+ *****************************************************************************/
+typedef enum {
+ EVEL_COUNTER_CRITICALITY_CRIT,
+ EVEL_COUNTER_CRITICALITY_MAJ,
+ EVEL_MAX_COUNTER_CRITICALITIES
+} EVEL_COUNTER_CRITICALITIES;
+
+/**************************************************************************//**
+ * Alert actions.
+ * JSON equivalent field: alertAction
+ *****************************************************************************/
+typedef enum {
+ EVEL_ALERT_ACTION_CLEAR,
+ EVEL_ALERT_ACTION_CONT,
+ EVEL_ALERT_ACTION_SET,
+ EVEL_MAX_ALERT_ACTIONS
+} EVEL_ALERT_ACTIONS;
+
+/**************************************************************************//**
+ * Alert types.
+ * JSON equivalent field: alertType
+ *****************************************************************************/
+typedef enum {
+ EVEL_ALERT_TYPE_CARD,
+ EVEL_ALERT_TYPE_ELEMENT,
+ EVEL_ALERT_TYPE_INTERFACE,
+ EVEL_ALERT_TYPE_SERVICE,
+ EVEL_MAX_ALERT_TYPES
+} EVEL_ALERT_TYPES;
+
+/**************************************************************************//**
+ * Alert types.
+ * JSON equivalent fields: newState, oldState
+ *****************************************************************************/
+typedef enum {
+ EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_MAINTENANCE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ EVEL_MAX_ENTITY_STATES
+} EVEL_ENTITY_STATE;
+
+/**************************************************************************//**
+ * Syslog facilities.
+ * JSON equivalent field: syslogFacility
+ *****************************************************************************/
+typedef enum {
+ EVEL_SYSLOG_FACILITY_KERNEL,
+ EVEL_SYSLOG_FACILITY_USER,
+ EVEL_SYSLOG_FACILITY_MAIL,
+ EVEL_SYSLOG_FACILITY_SYSTEM_DAEMON,
+ EVEL_SYSLOG_FACILITY_SECURITY_AUTH,
+ EVEL_SYSLOG_FACILITY_INTERNAL,
+ EVEL_SYSLOG_FACILITY_LINE_PRINTER,
+ EVEL_SYSLOG_FACILITY_NETWORK_NEWS,
+ EVEL_SYSLOG_FACILITY_UUCP,
+ EVEL_SYSLOG_FACILITY_CLOCK_DAEMON,
+ EVEL_SYSLOG_FACILITY_SECURITY_AUTH2,
+ EVEL_SYSLOG_FACILITY_FTP_DAEMON,
+ EVEL_SYSLOG_FACILITY_NTP,
+ EVEL_SYSLOG_FACILITY_LOG_AUDIT,
+ EVEL_SYSLOG_FACILITY_LOG_ALERT,
+ EVEL_SYSLOG_FACILITY_CLOCK_DAEMON2,
+ EVEL_SYSLOG_FACILITY_LOCAL0,
+ EVEL_SYSLOG_FACILITY_LOCAL1,
+ EVEL_SYSLOG_FACILITY_LOCAL2,
+ EVEL_SYSLOG_FACILITY_LOCAL3,
+ EVEL_SYSLOG_FACILITY_LOCAL4,
+ EVEL_SYSLOG_FACILITY_LOCAL5,
+ EVEL_SYSLOG_FACILITY_LOCAL6,
+ EVEL_SYSLOG_FACILITY_LOCAL7,
+ EVEL_MAX_SYSLOG_FACILITIES
+} EVEL_SYSLOG_FACILITIES;
+
+/**************************************************************************//**
+ * TCP flags.
+ * JSON equivalent fields: tcpFlagCountList, tcpFlagList
+ *****************************************************************************/
+typedef enum {
+ EVEL_TCP_NS,
+ EVEL_TCP_CWR,
+ EVEL_TCP_ECE,
+ EVEL_TCP_URG,
+ EVEL_TCP_ACK,
+ EVEL_TCP_PSH,
+ EVEL_TCP_RST,
+ EVEL_TCP_SYN,
+ EVEL_TCP_FIN,
+ EVEL_MAX_TCP_FLAGS
+} EVEL_TCP_FLAGS;
+
+/**************************************************************************//**
+ * Mobile QCI Classes of Service.
+ * JSON equivalent fields: mobileQciCosCountList, mobileQciCosList
+ *****************************************************************************/
+typedef enum {
+
+ /***************************************************************************/
+ /* UMTS Classes of Service. */
+ /***************************************************************************/
+ EVEL_QCI_COS_UMTS_CONVERSATIONAL,
+ EVEL_QCI_COS_UMTS_STREAMING,
+ EVEL_QCI_COS_UMTS_INTERACTIVE,
+ EVEL_QCI_COS_UMTS_BACKGROUND,
+
+ /***************************************************************************/
+ /* LTE Classes of Service. */
+ /***************************************************************************/
+ EVEL_QCI_COS_LTE_1,
+ EVEL_QCI_COS_LTE_2,
+ EVEL_QCI_COS_LTE_3,
+ EVEL_QCI_COS_LTE_4,
+ EVEL_QCI_COS_LTE_65,
+ EVEL_QCI_COS_LTE_66,
+ EVEL_QCI_COS_LTE_5,
+ EVEL_QCI_COS_LTE_6,
+ EVEL_QCI_COS_LTE_7,
+ EVEL_QCI_COS_LTE_8,
+ EVEL_QCI_COS_LTE_9,
+ EVEL_QCI_COS_LTE_69,
+ EVEL_QCI_COS_LTE_70,
+ EVEL_MAX_QCI_COS_TYPES
+} EVEL_QCI_COS_TYPES;
+
+/**************************************************************************//**
+ * Service Event endpoint description
+ * JSON equivalent field: endpointDesc
+ *****************************************************************************/
+typedef enum {
+ EVEL_SERVICE_ENDPOINT_CALLEE,
+ EVEL_SERVICE_ENDPOINT_CALLER,
+ EVEL_MAX_SERVICE_ENDPOINT_DESC
+} EVEL_SERVICE_ENDPOINT_DESC;
+
+/**************************************************************************//**
+ * Boolean type for EVEL library.
+ *****************************************************************************/
+typedef enum {
+ EVEL_FALSE,
+ EVEL_TRUE
+} EVEL_BOOLEAN;
+
+/**************************************************************************//**
+ * Optional parameter holder for double.
+ *****************************************************************************/
+typedef struct evel_option_double
+{
+ double value;
+ EVEL_BOOLEAN is_set;
+} EVEL_OPTION_DOUBLE;
+
+/**************************************************************************//**
+ * Optional parameter holder for string.
+ *****************************************************************************/
+typedef struct evel_option_string
+{
+ char * value;
+ EVEL_BOOLEAN is_set;
+} EVEL_OPTION_STRING;
+
+/**************************************************************************//**
+ * Optional parameter holder for int.
+ *****************************************************************************/
+typedef struct evel_option_int
+{
+ int value;
+ EVEL_BOOLEAN is_set;
+} EVEL_OPTION_INT;
+
+/**************************************************************************//**
+ * Optional parameter holder for unsigned long long.
+ *****************************************************************************/
+typedef struct evel_option_ull
+{
+ unsigned long long value;
+ EVEL_BOOLEAN is_set;
+} EVEL_OPTION_ULL;
+
+/**************************************************************************//**
+ * Optional parameter holder for time_t.
+ *****************************************************************************/
+typedef struct evel_option_time
+{
+ time_t value;
+ EVEL_BOOLEAN is_set;
+} EVEL_OPTION_TIME;
+
+/*****************************************************************************/
+/* Supported Common Event Header version. */
+/*****************************************************************************/
+#define EVEL_HEADER_MAJOR_VERSION 1
+#define EVEL_HEADER_MINOR_VERSION 2
+
+/**************************************************************************//**
+ * Event header.
+ * JSON equivalent field: commonEventHeader
+ *****************************************************************************/
+typedef struct event_header {
+ /***************************************************************************/
+ /* Version */
+ /***************************************************************************/
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ EVEL_EVENT_DOMAINS event_domain;
+ char * event_id;
+ char * source_name;
+ char * functional_role;
+ char * reporting_entity_name;
+ EVEL_EVENT_PRIORITIES priority;
+ unsigned long long start_epoch_microsec;
+ unsigned long long last_epoch_microsec;
+ int sequence;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING event_type;
+ EVEL_OPTION_STRING source_id;
+ EVEL_OPTION_STRING reporting_entity_id;
+
+} EVENT_HEADER;
+
+/*****************************************************************************/
+/* Supported Fault version. */
+/*****************************************************************************/
+#define EVEL_FAULT_MAJOR_VERSION 1
+#define EVEL_FAULT_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Fault.
+ * JSON equivalent field: faultFields
+ *****************************************************************************/
+typedef struct event_fault {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ EVEL_SEVERITIES event_severity;
+ EVEL_SOURCE_TYPES event_source_type;
+ char * alarm_condition;
+ char * specific_problem;
+ EVEL_VF_STATUSES vf_status;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING alarm_interface_a;
+ DLIST additional_info;
+
+} EVENT_FAULT;
+
+/**************************************************************************//**
+ * Fault Additional Info.
+ * JSON equivalent field: alarmAdditionalInformation
+ *****************************************************************************/
+typedef struct fault_additional_info {
+ char * name;
+ char * value;
+} FAULT_ADDL_INFO;
+
+/*****************************************************************************/
+/* Supported Measurement version. */
+/*****************************************************************************/
+#define EVEL_MEASUREMENT_MAJOR_VERSION 1
+#define EVEL_MEASUREMENT_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Errors.
+ * JSON equivalent field: errors
+ *****************************************************************************/
+typedef struct measurement_errors {
+ int receive_discards;
+ int receive_errors;
+ int transmit_discards;
+ int transmit_errors;
+} MEASUREMENT_ERRORS;
+
+/**************************************************************************//**
+ * Measurement.
+ * JSON equivalent field: measurementsForVfScalingFields
+ *****************************************************************************/
+typedef struct event_measurement {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ double measurement_interval;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ DLIST additional_measurements;
+ EVEL_OPTION_DOUBLE aggregate_cpu_usage;
+ DLIST codec_usage;
+ EVEL_OPTION_INT concurrent_sessions;
+ EVEL_OPTION_INT configured_entities;
+ DLIST cpu_usage;
+ MEASUREMENT_ERRORS * errors;
+ DLIST feature_usage;
+ DLIST filesystem_usage;
+ DLIST latency_distribution;
+ EVEL_OPTION_DOUBLE mean_request_latency;
+ EVEL_OPTION_DOUBLE memory_configured;
+ EVEL_OPTION_DOUBLE memory_used;
+ EVEL_OPTION_INT media_ports_in_use;
+ EVEL_OPTION_INT request_rate;
+ EVEL_OPTION_DOUBLE vnfc_scaling_metric;
+ DLIST vnic_usage;
+
+} EVENT_MEASUREMENT;
+
+/**************************************************************************//**
+ * CPU Usage.
+ * JSON equivalent field: cpuUsage
+ *****************************************************************************/
+typedef struct measurement_cpu_use {
+ char * id;
+ double usage;
+} MEASUREMENT_CPU_USE;
+
+/**************************************************************************//**
+ * Filesystem Usage.
+ * JSON equivalent field: filesystemUsage
+ *****************************************************************************/
+typedef struct measurement_fsys_use {
+ char * filesystem_name;
+ double block_configured;
+ int block_iops;
+ double block_used;
+ double ephemeral_configured;
+ int ephemeral_iops;
+ double ephemeral_used;
+} MEASUREMENT_FSYS_USE;
+
+/**************************************************************************//**
+ * Latency Bucket.
+ * JSON equivalent field: latencyBucketMeasure
+ *****************************************************************************/
+typedef struct measurement_latency_bucket {
+ int count;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_DOUBLE high_end;
+ EVEL_OPTION_DOUBLE low_end;
+
+} MEASUREMENT_LATENCY_BUCKET;
+
+/**************************************************************************//**
+ * Virtual NIC usage.
+ * JSON equivalent field: vNicUsage
+ *****************************************************************************/
+typedef struct measurement_vnic_use {
+ int bytes_in;
+ int bytes_out;
+ int packets_in;
+ int packets_out;
+ char * vnic_id;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_INT broadcast_packets_in;
+ EVEL_OPTION_INT broadcast_packets_out;
+ EVEL_OPTION_INT multicast_packets_in;
+ EVEL_OPTION_INT multicast_packets_out;
+ EVEL_OPTION_INT unicast_packets_in;
+ EVEL_OPTION_INT unicast_packets_out;
+
+} MEASUREMENT_VNIC_USE;
+
+/**************************************************************************//**
+ * Codec Usage.
+ * JSON equivalent field: codecsInUse
+ *****************************************************************************/
+typedef struct measurement_codec_use {
+ char * codec_id;
+ int number_in_use;
+} MEASUREMENT_CODEC_USE;
+
+/**************************************************************************//**
+ * Feature Usage.
+ * JSON equivalent field: featuresInUse
+ *****************************************************************************/
+typedef struct measurement_feature_use {
+ char * feature_id;
+ int feature_utilization;
+} MEASUREMENT_FEATURE_USE;
+
+/**************************************************************************//**
+ * Measurement Group.
+ * JSON equivalent field: additionalMeasurements
+ *****************************************************************************/
+typedef struct measurement_group {
+ char * name;
+ DLIST measurements;
+} MEASUREMENT_GROUP;
+
+/**************************************************************************//**
+ * Custom Defined Measurement.
+ * JSON equivalent field: measurements
+ *****************************************************************************/
+typedef struct custom_measurement {
+ char * name;
+ char * value;
+} CUSTOM_MEASUREMENT;
+
+/*****************************************************************************/
+/* Supported Report version. */
+/*****************************************************************************/
+#define EVEL_REPORT_MAJOR_VERSION 1
+#define EVEL_REPORT_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Report.
+ * JSON equivalent field: measurementsForVfReportingFields
+ *
+ * @note This is an experimental event type and is not currently a formal part
+ * of AT&T's specification.
+ *****************************************************************************/
+typedef struct event_report {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ double measurement_interval;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ DLIST feature_usage;
+ DLIST measurement_groups;
+
+} EVENT_REPORT;
+
+/**************************************************************************//**
+ * Mobile GTP Per Flow Metrics.
+ * JSON equivalent field: gtpPerFlowMetrics
+ *****************************************************************************/
+typedef struct mobile_gtp_per_flow_metrics {
+ double avg_bit_error_rate;
+ double avg_packet_delay_variation;
+ int avg_packet_latency;
+ int avg_receive_throughput;
+ int avg_transmit_throughput;
+ int flow_activation_epoch;
+ int flow_activation_microsec;
+ int flow_deactivation_epoch;
+ int flow_deactivation_microsec;
+ time_t flow_deactivation_time;
+ char * flow_status;
+ int max_packet_delay_variation;
+ int num_activation_failures;
+ int num_bit_errors;
+ int num_bytes_received;
+ int num_bytes_transmitted;
+ int num_dropped_packets;
+ int num_l7_bytes_received;
+ int num_l7_bytes_transmitted;
+ int num_lost_packets;
+ int num_out_of_order_packets;
+ int num_packet_errors;
+ int num_packets_received_excl_retrans;
+ int num_packets_received_incl_retrans;
+ int num_packets_transmitted_incl_retrans;
+ int num_retries;
+ int num_timeouts;
+ int num_tunneled_l7_bytes_received;
+ int round_trip_time;
+ int time_to_first_byte;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_INT ip_tos_counts[EVEL_TOS_SUPPORTED];
+ EVEL_OPTION_INT tcp_flag_counts[EVEL_MAX_TCP_FLAGS];
+ EVEL_OPTION_INT qci_cos_counts[EVEL_MAX_QCI_COS_TYPES];
+ EVEL_OPTION_INT dur_connection_failed_status;
+ EVEL_OPTION_INT dur_tunnel_failed_status;
+ EVEL_OPTION_STRING flow_activated_by;
+ EVEL_OPTION_TIME flow_activation_time;
+ EVEL_OPTION_STRING flow_deactivated_by;
+ EVEL_OPTION_STRING gtp_connection_status;
+ EVEL_OPTION_STRING gtp_tunnel_status;
+ EVEL_OPTION_INT large_packet_rtt;
+ EVEL_OPTION_DOUBLE large_packet_threshold;
+ EVEL_OPTION_INT max_receive_bit_rate;
+ EVEL_OPTION_INT max_transmit_bit_rate;
+ EVEL_OPTION_INT num_gtp_echo_failures;
+ EVEL_OPTION_INT num_gtp_tunnel_errors;
+ EVEL_OPTION_INT num_http_errors;
+
+} MOBILE_GTP_PER_FLOW_METRICS;
+
+/*****************************************************************************/
+/* Supported Mobile Flow version. */
+/*****************************************************************************/
+#define EVEL_MOBILE_FLOW_MAJOR_VERSION 1
+#define EVEL_MOBILE_FLOW_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Mobile Flow.
+ * JSON equivalent field: mobileFlow
+ *****************************************************************************/
+typedef struct event_mobile_flow {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ char * flow_direction;
+ MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics;
+ char * ip_protocol_type;
+ char * ip_version;
+ char * other_endpoint_ip_address;
+ int other_endpoint_port;
+ char * reporting_endpoint_ip_addr;
+ int reporting_endpoint_port;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING application_type;
+ EVEL_OPTION_STRING app_protocol_type;
+ EVEL_OPTION_STRING app_protocol_version;
+ EVEL_OPTION_STRING cid;
+ EVEL_OPTION_STRING connection_type;
+ EVEL_OPTION_STRING ecgi;
+ EVEL_OPTION_STRING gtp_protocol_type;
+ EVEL_OPTION_STRING gtp_version;
+ EVEL_OPTION_STRING http_header;
+ EVEL_OPTION_STRING imei;
+ EVEL_OPTION_STRING imsi;
+ EVEL_OPTION_STRING lac;
+ EVEL_OPTION_STRING mcc;
+ EVEL_OPTION_STRING mnc;
+ EVEL_OPTION_STRING msisdn;
+ EVEL_OPTION_STRING other_functional_role;
+ EVEL_OPTION_STRING rac;
+ EVEL_OPTION_STRING radio_access_technology;
+ EVEL_OPTION_STRING sac;
+ EVEL_OPTION_INT sampling_algorithm;
+ EVEL_OPTION_STRING tac;
+ EVEL_OPTION_STRING tunnel_id;
+ EVEL_OPTION_STRING vlan_id;
+
+} EVENT_MOBILE_FLOW;
+
+/**************************************************************************//**
+ * Other.
+ * JSON equivalent field: otherFields
+ *****************************************************************************/
+typedef struct event_other {
+ EVENT_HEADER header;
+ DLIST other_fields;
+
+} EVENT_OTHER;
+
+/**************************************************************************//**
+ * Other Field.
+ * JSON equivalent field: otherFields
+ *****************************************************************************/
+typedef struct other_field {
+ char * name;
+ char * value;
+} OTHER_FIELD;
+
+/**************************************************************************//**
+ * Event Instance Identifier
+ * JSON equivalent field: eventInstanceIdentifier
+ *****************************************************************************/
+typedef struct evel_event_instance_id {
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ char * vendor_id; /* JSON: vendorId */
+ char * event_id; /* JSON: eventId */
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING product_id; /* JSON: productId */
+ EVEL_OPTION_STRING subsystem_id; /* JSON: subsystemId */
+ EVEL_OPTION_STRING event_friendly_name; /* JSON: eventFriendlyName */
+
+} EVEL_EVENT_INSTANCE_ID;
+
+/*****************************************************************************/
+/* Supported Service Events version. */
+/*****************************************************************************/
+#define EVEL_SERVICE_MAJOR_VERSION 1
+#define EVEL_SERVICE_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Service Events.
+ * JSON equivalent field: serviceEventsFields
+ *****************************************************************************/
+typedef struct event_service {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ EVEL_EVENT_INSTANCE_ID instance_id; /* JSON: eventInstanceIdentifier */
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ EVEL_OPTION_STRING correlator; /* JSON: correlator */
+ DLIST additional_fields; /* JSON: additionalFields */
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: codecSelected */
+ /***************************************************************************/
+ EVEL_OPTION_STRING codec; /* JSON: codec */
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: codecSelectedTranscoding */
+ /***************************************************************************/
+ EVEL_OPTION_STRING callee_side_codec; /* JSON: calleeSideCodec */
+ EVEL_OPTION_STRING caller_side_codec; /* JSON: callerSideCodec */
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: midCallRtcp */
+ /***************************************************************************/
+ EVEL_OPTION_STRING rtcp_data; /* JSON: rtcpData */
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: endOfCallVqmSummaries */
+ /***************************************************************************/
+ EVEL_OPTION_STRING adjacency_name; /* JSON: adjacencyName */
+ EVEL_OPTION_STRING endpoint_description; /* JSON: endpointDescription */
+ EVEL_OPTION_INT endpoint_jitter; /* JSON: endpointJitter */
+ EVEL_OPTION_INT endpoint_rtp_oct_disc; /* JSON: endpointRtpOctetsDiscarded */
+ EVEL_OPTION_INT endpoint_rtp_oct_recv; /* JSON: endpointRtpOctetsReceived */
+ EVEL_OPTION_INT endpoint_rtp_oct_sent; /* JSON: endpointRtpOctetsSent */
+ EVEL_OPTION_INT endpoint_rtp_pkt_disc;/* JSON: endpointRtpPacketsDiscarded */
+ EVEL_OPTION_INT endpoint_rtp_pkt_recv; /* JSON: endpointRtpPacketsReceived */
+ EVEL_OPTION_INT endpoint_rtp_pkt_sent; /* JSON: endpointRtpPacketsSent */
+ EVEL_OPTION_INT local_jitter; /* JSON: localJitter */
+ EVEL_OPTION_INT local_rtp_oct_disc; /* JSON: localRtpOctetsDiscarded */
+ EVEL_OPTION_INT local_rtp_oct_recv; /* JSON: localRtpOctetsReceived */
+ EVEL_OPTION_INT local_rtp_oct_sent; /* JSON: localRtpOctetsSent */
+ EVEL_OPTION_INT local_rtp_pkt_disc; /* JSON: localRtpPacketsDiscarded */
+ EVEL_OPTION_INT local_rtp_pkt_recv; /* JSON: localRtpPacketsReceived */
+ EVEL_OPTION_INT local_rtp_pkt_sent; /* JSON: localRtpPacketsSent */
+ EVEL_OPTION_DOUBLE mos_cqe; /* JSON: mosCqe */
+ EVEL_OPTION_INT packets_lost; /* JSON: packetsLost */
+ EVEL_OPTION_DOUBLE packet_loss_percent; /* JSON: packetLossPercent */
+ EVEL_OPTION_INT r_factor; /* JSON: rFactor */
+ EVEL_OPTION_INT round_trip_delay; /* JSON: roundTripDelay */
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: marker */
+ /***************************************************************************/
+ EVEL_OPTION_STRING phone_number; /* JSON: phoneNumber */
+
+} EVENT_SERVICE;
+
+/*****************************************************************************/
+/* Supported Signaling version. */
+/*****************************************************************************/
+#define EVEL_SIGNALING_MAJOR_VERSION 1
+#define EVEL_SIGNALING_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Signaling.
+ * JSON equivalent field: signalingFields
+ *****************************************************************************/
+typedef struct event_signaling {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ EVEL_EVENT_INSTANCE_ID instance_id; /* JSON: eventInstanceIdentifier */
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING correlator; /* JSON: correlator */
+ EVEL_OPTION_STRING local_ip_address; /* JSON: localIpAddress */
+ EVEL_OPTION_STRING local_port; /* JSON: localPort */
+ EVEL_OPTION_STRING remote_ip_address; /* JSON: remoteIpAddress */
+ EVEL_OPTION_STRING remote_port; /* JSON: remotePort */
+ EVEL_OPTION_STRING compressed_sip; /* JSON: compressedSip */
+ EVEL_OPTION_STRING summary_sip; /* JSON: summarySip */
+
+} EVENT_SIGNALING;
+
+/*****************************************************************************/
+/* Supported State Change version. */
+/*****************************************************************************/
+#define EVEL_STATE_CHANGE_MAJOR_VERSION 1
+#define EVEL_STATE_CHANGE_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * State Change.
+ * JSON equivalent field: stateChangeFields
+ *****************************************************************************/
+typedef struct event_state_change {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ EVEL_ENTITY_STATE new_state;
+ EVEL_ENTITY_STATE old_state;
+ char * state_interface;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ DLIST additional_fields;
+
+} EVENT_STATE_CHANGE;
+
+/**************************************************************************//**
+ * State Change Additional Field.
+ * JSON equivalent field: additionalFields
+ *****************************************************************************/
+typedef struct state_change_additional_field {
+ char * name;
+ char * value;
+} STATE_CHANGE_ADDL_FIELD;
+
+/*****************************************************************************/
+/* Supported Syslog version. */
+/*****************************************************************************/
+#define EVEL_SYSLOG_MAJOR_VERSION 1
+#define EVEL_SYSLOG_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Syslog.
+ * JSON equivalent field: syslogFields
+ *****************************************************************************/
+typedef struct event_syslog {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ EVEL_SOURCE_TYPES event_source_type;
+ char * syslog_msg;
+ char * syslog_tag;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ DLIST additional_fields;
+ EVEL_OPTION_STRING event_source_host;
+ EVEL_OPTION_INT syslog_facility;
+ EVEL_OPTION_STRING syslog_proc;
+ EVEL_OPTION_INT syslog_proc_id;
+ EVEL_OPTION_STRING syslog_s_data;
+ EVEL_OPTION_INT syslog_ver;
+
+} EVENT_SYSLOG;
+
+/**************************************************************************//**
+ * Syslog Additional Field.
+ * JSON equivalent field: additionalFields
+ *****************************************************************************/
+typedef struct syslog_additional_field {
+ char * name;
+ char * value;
+} SYSLOG_ADDL_FIELD;
+
+/**************************************************************************//**
+ * Copyright.
+ * JSON equivalent object: attCopyrightNotice
+ *****************************************************************************/
+typedef struct copyright {
+ char * useAndRedistribution;
+ char * condition1;
+ char * condition2;
+ char * condition3;
+ char * condition4;
+ char * disclaimerLine1;
+ char * disclaimerLine2;
+ char * disclaimerLine3;
+ char * disclaimerLine4;
+} COPYRIGHT;
+
+/**************************************************************************//**
+ * Library initialization.
+ *
+ * Initialize the EVEL library.
+ *
+ * @note This function initializes the cURL library. Applications making use
+ * of libcurl may need to pull the initialization out of here. Note
+ * also that this function is not threadsafe as a result - refer to
+ * libcurl's API documentation for relevant warnings.
+ *
+ * @sa Matching Term function.
+ *
+ * @param fqdn The API's FQDN or IP address.
+ * @param port The API's port.
+ * @param path The optional path (may be NULL).
+ * @param topic The optional topic part of the URL (may be NULL).
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS).
+ * @param username Username for Basic Authentication of requests.
+ * @param password Password for Basic Authentication of requests.
+ * @param source_type The kind of node we represent.
+ * @param role The role this node undertakes.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_initialize(const char * const fqdn,
+ int port,
+ const char * const path,
+ const char * const topic,
+ int secure,
+ const char * const username,
+ const char * const password,
+ EVEL_SOURCE_TYPES source_type,
+ const char * const role,
+ int verbosity
+ );
+
+/**************************************************************************//**
+ * Clean up the EVEL library.
+ *
+ * @note that at present don't expect Init/Term cycling not to leak memory!
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_terminate(void);
+
+EVEL_ERR_CODES evel_post_event(EVENT_HEADER * event);
+const char * evel_error_string(void);
+
+
+/**************************************************************************//**
+ * Free an event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It is safe to free a NULL pointer.
+ *****************************************************************************/
+void evel_free_event(void * event);
+
+/**************************************************************************//**
+ * Encode the event as a JSON event object according to AT&T's schema.
+ *
+ * @param json Pointer to where to store the JSON encoded data.
+ * @param max_size Size of storage available in json_body.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ * @returns Number of bytes actually written.
+ *****************************************************************************/
+int evel_json_encode_event(char * json,
+ int max_size,
+ EVENT_HEADER * event);
+
+/**************************************************************************//**
+ * Callback function to provide returned data.
+ *
+ * Copy data into the supplied buffer, write_callback::ptr, checking size
+ * limits.
+ *
+ * @returns Number of bytes placed into write_callback::ptr. 0 for EOF.
+ *****************************************************************************/
+size_t evel_write_callback(void *contents,
+ size_t size,
+ size_t nmemb,
+ void *userp);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* HEARTBEAT - (includes common header, too) */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new heartbeat event.
+ *
+ * @note that the heartbeat is just a "naked" commonEventHeader!
+ *
+ * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is
+ * not used it must be released using ::evel_free_event
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_HEADER * evel_new_heartbeat(void);
+
+/**************************************************************************//**
+ * Free an event header.
+ *
+ * Free off the event header supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the header itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_header(EVENT_HEADER * const event);
+
+/**************************************************************************//**
+ * Initialize a newly created event header.
+ *
+ * @param header Pointer to the header being initialized.
+ *****************************************************************************/
+void evel_init_header(EVENT_HEADER * const header);
+
+/**************************************************************************//**
+ * Set the Event Type property of the event header.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_header_type_set(EVENT_HEADER * const header,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Start Epoch property of the event header.
+ *
+ * @note The Start Epoch defaults to the time of event creation.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param start_epoch_microsec
+ * The start epoch to set, in microseconds.
+ *****************************************************************************/
+void evel_start_epoch_set(EVENT_HEADER * const header,
+ const unsigned long long start_epoch_microsec);
+
+/**************************************************************************//**
+ * Set the Last Epoch property of the event header.
+ *
+ * @note The Last Epoch defaults to the time of event creation.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param last_epoch_microsec
+ * The last epoch to set, in microseconds.
+ *****************************************************************************/
+void evel_last_epoch_set(EVENT_HEADER * const header,
+ const unsigned long long last_epoch_microsec);
+
+/**************************************************************************//**
+ * Set the Reporting Entity Name property of the event header.
+ *
+ * @note The Reporting Entity Name defaults to the OpenStack VM Name.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param entity_name The entity name to set.
+ *****************************************************************************/
+void evel_reporting_entity_name_set(EVENT_HEADER * const header,
+ const char * const entity_name);
+
+/**************************************************************************//**
+ * Set the Reporting Entity Id property of the event header.
+ *
+ * @note The Reporting Entity Id defaults to the OpenStack VM UUID.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param entity_id The entity id to set.
+ *****************************************************************************/
+void evel_reporting_entity_id_set(EVENT_HEADER * const header,
+ const char * const entity_id);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* FAULT */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new fault event.
+ *
+ *
+ * @returns pointer to the newly manufactured ::EVENT_FAULT. If the event is
+ * not used it must be released using ::evel_free_fault
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_FAULT * evel_new_fault(const char * const condition,
+ const char * const specific_problem,
+ EVEL_EVENT_PRIORITIES priority,
+ EVEL_SEVERITIES severity);
+
+/**************************************************************************//**
+ * Free a Fault.
+ *
+ * Free off the Fault supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Fault itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_fault(EVENT_FAULT * event);
+
+
+/**************************************************************************//**
+ * Set the Alarm Interface A property of the Fault.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param fault Pointer to the fault.
+ * @param interface The Alarm Interface A to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_interface_set(EVENT_FAULT * fault,
+ const char * const interface);
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the Fault.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param fault Pointer to the fault.
+ * @param name ASCIIZ string with the attribute's name.
+ * @param value ASCIIZ string with the attribute's value.
+ *****************************************************************************/
+void evel_fault_addl_info_add(EVENT_FAULT * fault, char * name, char * value);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Fault.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param fault Pointer to the fault.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_type_set(EVENT_FAULT * fault, const char * const type);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* MEASUREMENT */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Measurement event.
+ *
+ * @note The mandatory fields on the Measurement must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Measurement has immutable properties.
+ *
+ * @param measurement_interval
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval);
+
+/**************************************************************************//**
+ * Free a Measurement.
+ *
+ * Free off the Measurement supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Measurement itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement(EVENT_MEASUREMENT * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_measurement_type_set(EVENT_MEASUREMENT * measurement,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Concurrent Sessions property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param concurrent_sessions The Concurrent Sessions to be set.
+ *****************************************************************************/
+void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement,
+ int concurrent_sessions);
+
+/**************************************************************************//**
+ * Set the Configured Entities property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param configured_entities The Configured Entities to be set.
+ *****************************************************************************/
+void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement,
+ int configured_entities);
+
+/**************************************************************************//**
+ * Add an additional set of Errors to the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param receive_discards The number of receive discards.
+ * @param receive_errors The number of receive errors.
+ * @param transmit_discards The number of transmit discards.
+ * @param transmit_errors The number of transmit errors.
+ *****************************************************************************/
+void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement,
+ int receive_discards,
+ int receive_errors,
+ int transmit_discards,
+ int transmit_errors);
+
+/**************************************************************************//**
+ * Set the Mean Request Latency property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param mean_request_latency The Mean Request Latency to be set.
+ *****************************************************************************/
+void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement,
+ double mean_request_latency);
+
+/**************************************************************************//**
+ * Set the Memory Configured property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param memory_configured The Memory Configured to be set.
+ *****************************************************************************/
+void evel_measurement_mem_cfg_set(EVENT_MEASUREMENT * measurement,
+ double memory_configured);
+
+/**************************************************************************//**
+ * Set the Memory Used property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param memory_used The Memory Used to be set.
+ *****************************************************************************/
+void evel_measurement_mem_used_set(EVENT_MEASUREMENT * measurement,
+ double memory_used);
+
+/**************************************************************************//**
+ * Set the Request Rate property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param request_rate The Request Rate to be set.
+ *****************************************************************************/
+void evel_measurement_request_rate_set(EVENT_MEASUREMENT * measurement,
+ int request_rate);
+
+/**************************************************************************//**
+ * Add an additional CPU usage value name/value pair to the Measurement.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param id ASCIIZ string with the CPU's identifier.
+ * @param usage CPU utilization.
+ *****************************************************************************/
+void evel_measurement_cpu_use_add(EVENT_MEASUREMENT * measurement,
+ char * id, double usage);
+
+/**************************************************************************//**
+ * Add an additional File System usage value name/value pair to the
+ * Measurement.
+ *
+ * The filesystem_name is null delimited ASCII string. The library takes a
+ * copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param filesystem_name ASCIIZ string with the file-system's UUID.
+ * @param block_configured Block storage configured.
+ * @param block_used Block storage in use.
+ * @param block_iops Block storage IOPS.
+ * @param ephemeral_configured Ephemeral storage configured.
+ * @param ephemeral_used Ephemeral storage in use.
+ * @param ephemeral_iops Ephemeral storage IOPS.
+ *****************************************************************************/
+void evel_measurement_fsys_use_add(EVENT_MEASUREMENT * measurement,
+ char * filesystem_name,
+ double block_configured,
+ double block_used,
+ int block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ int ephemeral_iops);
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement,
+ char * feature,
+ int utilization);
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param name ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement,
+ const char * const group,
+ const char * const name,
+ const char * const value);
+
+/**************************************************************************//**
+ * Add a Codec usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param codec ASCIIZ string with the codec's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement,
+ char * codec,
+ int utilization);
+
+/**************************************************************************//**
+}
+ * Set the Aggregate CPU Use property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param cpu_use The CPU use to set.
+ *****************************************************************************/
+void evel_measurement_agg_cpu_use_set(EVENT_MEASUREMENT * measurement,
+ double cpu_use);
+
+/**************************************************************************//**
+ * Set the Media Ports in Use property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param media_ports_in_use The media port usage to set.
+ *****************************************************************************/
+void evel_measurement_media_port_use_set(EVENT_MEASUREMENT * measurement,
+ int media_ports_in_use);
+
+/**************************************************************************//**
+ * Set the VNFC Scaling Metric property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param scaling_metric The scaling metric to set.
+ *****************************************************************************/
+void evel_measurement_vnfc_scaling_metric_set(EVENT_MEASUREMENT * measurement,
+ double scaling_metric);
+
+/**************************************************************************//**
+ * Create a new Latency Bucket to be added to a Measurement event.
+ *
+ * @note The mandatory fields on the ::MEASUREMENT_LATENCY_BUCKET must be
+ * supplied to this factory function and are immutable once set.
+ * Optional fields have explicit setter functions, but again values
+ * may only be set once so that the ::MEASUREMENT_LATENCY_BUCKET has
+ * immutable properties.
+ *
+ * @param count Count of events in this bucket.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_LATENCY_BUCKET.
+ * @retval NULL Failed to create the Latency Bucket.
+ *****************************************************************************/
+MEASUREMENT_LATENCY_BUCKET * evel_new_meas_latency_bucket(const int count);
+
+/**************************************************************************//**
+ * Set the High End property of the Measurement Latency Bucket.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param bucket Pointer to the Measurement Latency Bucket.
+ * @param high_end High end of the bucket's range.
+ *****************************************************************************/
+void evel_meas_latency_bucket_high_end_set(
+ MEASUREMENT_LATENCY_BUCKET * const bucket,
+ const double high_end);
+
+/**************************************************************************//**
+ * Set the Low End property of the Measurement Latency Bucket.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param bucket Pointer to the Measurement Latency Bucket.
+ * @param low_end Low end of the bucket's range.
+ *****************************************************************************/
+void evel_meas_latency_bucket_low_end_set(
+ MEASUREMENT_LATENCY_BUCKET * const bucket,
+ const double low_end);
+
+/**************************************************************************//**
+ * Add an additional Measurement Latency Bucket to the specified event.
+ *
+ * @param measurement Pointer to the Measurement event.
+ * @param bucket Pointer to the Measurement Latency Bucket to add.
+ *****************************************************************************/
+void evel_meas_latency_bucket_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_LATENCY_BUCKET * const bucket);
+
+/**************************************************************************//**
+ * Add an additional Latency Distribution bucket to the Measurement.
+ *
+ * This function implements the previous API, purely for convenience.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param low_end Low end of the bucket's range.
+ * @param high_end High end of the bucket's range.
+ * @param count Count of events in this bucket.
+ *****************************************************************************/
+void evel_measurement_latency_add(EVENT_MEASUREMENT * const measurement,
+ const double low_end,
+ const double high_end,
+ const int count);
+
+/**************************************************************************//**
+ * Create a new vNIC Use to be added to a Measurement event.
+ *
+ * @note The mandatory fields on the ::MEASUREMENT_VNIC_USE must be supplied
+ * to this factory function and are immutable once set. Optional
+ * fields have explicit setter functions, but again values may only be
+ * set once so that the ::MEASUREMENT_VNIC_USE has immutable
+ * properties.
+ *
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param packets_in Total packets received.
+ * @param packets_out Total packets transmitted.
+ * @param bytes_in Total bytes received.
+ * @param bytes_out Total bytes transmitted.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_USE.
+ * If the structure is not used it must be released using
+ * ::evel_free_measurement_vnic_use.
+ * @retval NULL Failed to create the vNIC Use.
+ *****************************************************************************/
+MEASUREMENT_VNIC_USE * evel_new_measurement_vnic_use(char * const vnic_id,
+ const int packets_in,
+ const int packets_out,
+ const int bytes_in,
+ const int bytes_out);
+
+/**************************************************************************//**
+ * Free a vNIC Use.
+ *
+ * Free off the ::MEASUREMENT_VNIC_USE supplied. Will free all the contained
+ * allocated memory.
+ *
+ * @note It does not free the vNIC Use itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement_vnic_use(MEASUREMENT_VNIC_USE * const vnic_use);
+
+/**************************************************************************//**
+ * Set the Broadcast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param broadcast_packets_in
+ * Broadcast packets received.
+ *****************************************************************************/
+void evel_vnic_use_bcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int broadcast_packets_in);
+
+/**************************************************************************//**
+ * Set the Broadcast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param broadcast_packets_out
+ * Broadcast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_bcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int broadcast_packets_out);
+
+/**************************************************************************//**
+ * Set the Multicast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param multicast_packets_in
+ * Multicast packets received.
+ *****************************************************************************/
+void evel_vnic_use_mcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int multicast_packets_in);
+
+/**************************************************************************//**
+ * Set the Multicast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param multicast_packets_out
+ * Multicast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_mcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int multicast_packets_out);
+
+/**************************************************************************//**
+ * Set the Unicast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param unicast_packets_in
+ * Unicast packets received.
+ *****************************************************************************/
+void evel_vnic_use_ucast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int unicast_packets_in);
+
+/**************************************************************************//**
+ * Set the Unicast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param unicast_packets_out
+ * Unicast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_ucast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int unicast_packets_out);
+
+/**************************************************************************//**
+ * Add an additional vNIC Use to the specified Measurement event.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_use Pointer to the vNIC Use to add.
+ *****************************************************************************/
+void evel_meas_vnic_use_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_VNIC_USE * const vnic_use);
+
+/**************************************************************************//**
+ * Add an additional vNIC usage record Measurement.
+ *
+ * This function implements the previous API, purely for convenience.
+ *
+ * The ID is null delimited ASCII string. The library takes a copy so the
+ * caller does not have to preserve values after the function returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param packets_in Total packets received.
+ * @param packets_out Total packets transmitted.
+ * @param broadcast_packets_in Broadcast packets received.
+ * @param broadcast_packets_out Broadcast packets transmitted.
+ * @param bytes_in Total bytes received.
+ * @param bytes_out Total bytes transmitted.
+ * @param multicast_packets_in Multicast packets received.
+ * @param multicast_packets_out Multicast packets transmitted.
+ * @param unicast_packets_in Unicast packets received.
+ * @param unicast_packets_out Unicast packets transmitted.
+ *****************************************************************************/
+void evel_measurement_vnic_use_add(EVENT_MEASUREMENT * const measurement,
+ char * const vnic_id,
+ const int packets_in,
+ const int packets_out,
+ const int broadcast_packets_in,
+ const int broadcast_packets_out,
+ const int bytes_in,
+ const int bytes_out,
+ const int multicast_packets_in,
+ const int multicast_packets_out,
+ const int unicast_packets_in,
+ const int unicast_packets_out);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* REPORT */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Report event.
+ *
+ * @note The mandatory fields on the Report must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Report has immutable properties.
+ *
+ * @param measurement_interval
+ *
+ * @returns pointer to the newly manufactured ::EVENT_REPORT. If the event is
+ * not used (i.e. posted) it must be released using
+ * ::evel_free_report.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_REPORT * evel_new_report(double measurement_interval);
+
+/**************************************************************************//**
+ * Free a Report.
+ *
+ * Free off the Report supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Report itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_report(EVENT_REPORT * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Report.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param report Pointer to the Report.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_report_type_set(EVENT_REPORT * report, const char * const type);
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param report Pointer to the report.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_report_feature_use_add(EVENT_REPORT * report,
+ char * feature,
+ int utilization);
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param report Pointer to the report.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param value ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_report_custom_measurement_add(EVENT_REPORT * report,
+ const char * const group,
+ const char * const name,
+ const char * const value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* MOBILE_FLOW */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Mobile Flow event.
+ *
+ * @note The mandatory fields on the Mobile Flow must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Mobile Flow has immutable properties.
+ *
+ * @param flow_direction
+ * @param gtp_per_flow_metrics
+ * @param ip_protocol_type
+ * @param ip_version
+ * @param other_endpoint_ip_address
+ * @param other_endpoint_port
+ * @param reporting_endpoint_ip_addr
+ * @param reporting_endpoint_port
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MOBILE_FLOW. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_mobile_flow.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MOBILE_FLOW * evel_new_mobile_flow(
+ const char * const flow_direction,
+ MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics,
+ const char * const ip_protocol_type,
+ const char * const ip_version,
+ const char * const other_endpoint_ip_address,
+ int other_endpoint_port,
+ const char * const reporting_endpoint_ip_addr,
+ int reporting_endpoint_port);
+
+/**************************************************************************//**
+ * Free a Mobile Flow.
+ *
+ * Free off the Mobile Flow supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Mobile Flow itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_mobile_flow(EVENT_MOBILE_FLOW * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Application Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Application Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Application Protocol Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Application Protocol Type to be set. ASCIIZ string.
+ * The caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Application Protocol Version property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param version The Application Protocol Version to be set. ASCIIZ
+ * string. The caller does not need to preserve the value
+ * once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const version);
+
+/**************************************************************************//**
+ * Set the CID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param cid The CID to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_cid_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const cid);
+
+/**************************************************************************//**
+ * Set the Connection Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Connection Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_con_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the ECGI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param ecgi The ECGI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_ecgi_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const ecgi);
+
+/**************************************************************************//**
+ * Set the GTP Protocol Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The GTP Protocol Type to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_gtp_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the GTP Protocol Version property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param version The GTP Protocol Version to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_gtp_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const version);
+
+/**************************************************************************//**
+ * Set the HTTP Header property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param header The HTTP header to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_http_header_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const header);
+
+/**************************************************************************//**
+ * Set the IMEI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param imei The IMEI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_imei_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const imei);
+
+/**************************************************************************//**
+ * Set the IMSI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param imsi The IMSI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_imsi_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const imsi);
+
+/**************************************************************************//**
+ * Set the LAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param lac The LAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_lac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const lac);
+
+/**************************************************************************//**
+ * Set the MCC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param mcc The MCC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_mcc_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const mcc);
+
+/**************************************************************************//**
+ * Set the MNC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param mnc The MNC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_mnc_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const mnc);
+
+/**************************************************************************//**
+ * Set the MSISDN property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param msisdn The MSISDN to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_msisdn_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const msisdn);
+
+/**************************************************************************//**
+ * Set the Other Functional Role property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param role The Other Functional Role to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_other_func_role_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const role);
+
+/**************************************************************************//**
+ * Set the RAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param rac The RAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_rac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const rac);
+
+/**************************************************************************//**
+ * Set the Radio Access Technology property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tech The Radio Access Technology to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_radio_acc_tech_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tech);
+
+/**************************************************************************//**
+ * Set the SAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param sac The SAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_sac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const sac);
+
+/**************************************************************************//**
+ * Set the Sampling Algorithm property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param algorithm The Sampling Algorithm to be set.
+ *****************************************************************************/
+void evel_mobile_flow_samp_alg_set(EVENT_MOBILE_FLOW * mobile_flow,
+ int algorithm);
+
+/**************************************************************************//**
+ * Set the TAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tac The TAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_tac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tac);
+
+/**************************************************************************//**
+ * Set the Tunnel ID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tunnel_id The Tunnel ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_tunnel_id_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tunnel_id);
+
+/**************************************************************************//**
+ * Set the VLAN ID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param vlan_id The VLAN ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_vlan_id_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const vlan_id);
+
+/**************************************************************************//**
+ * Create a new Mobile GTP Per Flow Metrics.
+ *
+ * @note The mandatory fields on the Mobile GTP Per Flow Metrics must be
+ * supplied to this factory function and are immutable once set.
+ * Optional fields have explicit setter functions, but again values
+ * may only be set once so that the Mobile GTP Per Flow Metrics has
+ * immutable properties.
+ *
+ * @param avg_bit_error_rate
+ * @param avg_packet_delay_variation
+ * @param avg_packet_latency
+ * @param avg_receive_throughput
+ * @param avg_transmit_throughput
+ * @param flow_activation_epoch
+ * @param flow_activation_microsec
+ * @param flow_deactivation_epoch
+ * @param flow_deactivation_microsec
+ * @param flow_deactivation_time
+ * @param flow_status
+ * @param max_packet_delay_variation
+ * @param num_activation_failures
+ * @param num_bit_errors
+ * @param num_bytes_received
+ * @param num_bytes_transmitted
+ * @param num_dropped_packets
+ * @param num_l7_bytes_received
+ * @param num_l7_bytes_transmitted
+ * @param num_lost_packets
+ * @param num_out_of_order_packets
+ * @param num_packet_errors
+ * @param num_packets_received_excl_retrans
+ * @param num_packets_received_incl_retrans
+ * @param num_packets_transmitted_incl_retrans
+ * @param num_retries
+ * @param num_timeouts
+ * @param num_tunneled_l7_bytes_received
+ * @param round_trip_time
+ * @param time_to_first_byte
+ *
+ * @returns pointer to the newly manufactured ::MOBILE_GTP_PER_FLOW_METRICS.
+ * If the structure is not used it must be released using
+ * ::evel_free_mobile_gtp_flow_metrics.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+MOBILE_GTP_PER_FLOW_METRICS * evel_new_mobile_gtp_flow_metrics(
+ double avg_bit_error_rate,
+ double avg_packet_delay_variation,
+ int avg_packet_latency,
+ int avg_receive_throughput,
+ int avg_transmit_throughput,
+ int flow_activation_epoch,
+ int flow_activation_microsec,
+ int flow_deactivation_epoch,
+ int flow_deactivation_microsec,
+ time_t flow_deactivation_time,
+ const char * const flow_status,
+ int max_packet_delay_variation,
+ int num_activation_failures,
+ int num_bit_errors,
+ int num_bytes_received,
+ int num_bytes_transmitted,
+ int num_dropped_packets,
+ int num_l7_bytes_received,
+ int num_l7_bytes_transmitted,
+ int num_lost_packets,
+ int num_out_of_order_packets,
+ int num_packet_errors,
+ int num_packets_received_excl_retrans,
+ int num_packets_received_incl_retrans,
+ int num_packets_transmitted_incl_retrans,
+ int num_retries,
+ int num_timeouts,
+ int num_tunneled_l7_bytes_received,
+ int round_trip_time,
+ int time_to_first_byte);
+
+/**************************************************************************//**
+ * Free a Mobile GTP Per Flow Metrics.
+ *
+ * Free off the Mobile GTP Per Flow Metrics supplied. Will free all the
+ * contained allocated memory.
+ *
+ * @note It does not free the Mobile GTP Per Flow Metrics itself, since that
+ * may be part of a larger structure.
+ *****************************************************************************/
+void evel_free_mobile_gtp_flow_metrics(MOBILE_GTP_PER_FLOW_METRICS * metrics);
+
+/**************************************************************************//**
+ * Set the Duration of Connection Failed Status property of the Mobile GTP Per
+ * Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param duration The Duration of Connection Failed Status to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_dur_con_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int duration);
+
+/**************************************************************************//**
+ * Set the Duration of Tunnel Failed Status property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param duration The Duration of Tunnel Failed Status to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_dur_tun_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int duration);
+
+/**************************************************************************//**
+ * Set the Activated By property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param act_by The Activated By to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_act_by_set(MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const act_by);
+
+/**************************************************************************//**
+ * Set the Activation Time property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param act_time The Activation Time to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_act_time_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ time_t act_time);
+
+/**************************************************************************//**
+ * Set the Deactivated By property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param deact_by The Deactivated By to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_deact_by_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const deact_by);
+
+/**************************************************************************//**
+ * Set the GTP Connection Status property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param status The GTP Connection Status to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_con_status_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const status);
+
+/**************************************************************************//**
+ * Set the GTP Tunnel Status property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param status The GTP Tunnel Status to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_tun_status_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const status);
+
+/**************************************************************************//**
+ * Set an IP Type-of-Service count property of the Mobile GTP Per Flow metrics.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param index The index of the IP Type-of-Service.
+ * @param count The count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_iptos_set(MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int index,
+ int count);
+
+/**************************************************************************//**
+ * Set the Large Packet Round-Trip Time property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rtt The Large Packet Round-Trip Time to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_large_pkt_rtt_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rtt);
+
+/**************************************************************************//**
+ * Set the Large Packet Threshold property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param threshold The Large Packet Threshold to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_large_pkt_thresh_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ double threshold);
+
+/**************************************************************************//**
+ * Set the Max Receive Bit Rate property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rate The Max Receive Bit Rate to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_max_rcv_bit_rate_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rate);
+
+/**************************************************************************//**
+ * Set the Max Transmit Bit Rate property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rate The Max Transmit Bit Rate to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_max_trx_bit_rate_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rate);
+
+/**************************************************************************//**
+ * Set the Number of GTP Echo Failures property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of GTP Echo Failures to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_echo_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num);
+
+/**************************************************************************//**
+ * Set the Number of GTP Tunnel Errors property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of GTP Tunnel Errors to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_tun_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num);
+
+/**************************************************************************//**
+ * Set the Number of HTTP Errors property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of HTTP Errors to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_http_errors_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num);
+
+/**************************************************************************//**
+ * Add a TCP flag count to the metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param tcp_flag The TCP flag count to be updated.
+ * @param count The associated flag count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_tcp_flag_count_add(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const EVEL_TCP_FLAGS tcp_flag,
+ const int count);
+
+/**************************************************************************//**
+ * Add a QCI COS count to the metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param qci_cos The QCI COS count to be updated.
+ * @param count The associated QCI COS count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_qci_cos_count_add(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const EVEL_QCI_COS_TYPES qci_cos,
+ const int count);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* SERVICE EVENTS */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Service event.
+ *
+ * @note The mandatory fields on the Service must be supplied to
+ * this factory function and are immutable once set. Optional fields
+ * have explicit setter functions, but again values may only be set
+ * once so that the event has immutable properties.
+ * @param vendor_id The vendor id to encode in the event instance id.
+ * @param event_id The vendor event id to encode in the event instance id.
+ * @returns pointer to the newly manufactured ::EVENT_SERVICE. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_service.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SERVICE * evel_new_service(const char * const vendor_id,
+ const char * const event_id);
+
+/**************************************************************************//**
+ * Free a Service Events event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the event itself, since that may be part of a larger
+ * structure.
+ *****************************************************************************/
+void evel_free_service(EVENT_SERVICE * const event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_type_set(EVENT_SERVICE * const event,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Product Id property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param product_id The vendor product id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_service_product_id_set(EVENT_SERVICE * const event,
+ const char * const product_id);
+
+/**************************************************************************//**
+ * Set the Subsystem Id property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param subsystem_id The vendor subsystem id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_service_subsystem_id_set(EVENT_SERVICE * const event,
+ const char * const subsystem_id);
+
+/**************************************************************************//**
+ * Set the Friendly Name property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param friendly_name The vendor friendly name to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_service_friendly_name_set(EVENT_SERVICE * const event,
+ const char * const friendly_name);
+
+/**************************************************************************//**
+ * Set the correlator property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param correlator The correlator to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_correlator_set(EVENT_SERVICE * const event,
+ const char * const correlator);
+
+/**************************************************************************//**
+ * Set the Codec property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param codec The codec to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_codec_set(EVENT_SERVICE * const event,
+ const char * const codec);
+
+/**************************************************************************//**
+ * Set the Callee Side Codec property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param codec The codec to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_callee_codec_set(EVENT_SERVICE * const event,
+ const char * const codec);
+
+/**************************************************************************//**
+ * Set the Caller Side Codec property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param codec The codec to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_caller_codec_set(EVENT_SERVICE * const event,
+ const char * const codec);
+
+/**************************************************************************//**
+ * Set the RTCP Data property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtcp_data The RTCP Data to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_rtcp_data_set(EVENT_SERVICE * const event,
+ const char * const rtcp_data);
+
+/**************************************************************************//**
+ * Set the Adjacency Name property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param adjacency_name
+ * The adjacency name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_adjacency_name_set(EVENT_SERVICE * const event,
+ const char * const adjacency_name);
+
+/**************************************************************************//**
+ * Set the Endpoint Descriptor property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param endpoint_desc The endpoint descriptor to be set.
+ *****************************************************************************/
+void evel_service_endpoint_desc_set(
+ EVENT_SERVICE * const event,
+ const EVEL_SERVICE_ENDPOINT_DESC endpoint_desc);
+
+/**************************************************************************//**
+ * Set the Endpoint Jitter property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param jitter The jitter to be set.
+ *****************************************************************************/
+void evel_service_endpoint_jitter_set(EVENT_SERVICE * const event,
+ const int jitter);
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Octets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_disc The discard count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_oct_disc_set(EVENT_SERVICE * const event,
+ const int rtp_oct_disc);
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Octets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_recv The receive count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_oct_recv_set(EVENT_SERVICE * const event,
+ const int rtp_oct_recv);
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Octets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_sent The send count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_oct_sent_set(EVENT_SERVICE * const event,
+ const int rtp_oct_sent);
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Packets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_disc The discard count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_pkt_disc_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_disc);
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Packets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_recv The receive count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_pkt_recv_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_recv);
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Packets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_sent The send count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_pkt_sent_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_sent);
+
+/**************************************************************************//**
+ * Set the Local Jitter property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param jitter The jitter to be set.
+ *****************************************************************************/
+void evel_service_local_jitter_set(EVENT_SERVICE * const event,
+ const int jitter);
+
+/**************************************************************************//**
+ * Set the Local Rtp Octets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_disc The discard count.
+ *****************************************************************************/
+void evel_service_local_rtp_oct_disc_set(EVENT_SERVICE * const event,
+ const int rtp_oct_disc);
+
+/**************************************************************************//**
+ * Set the Local Rtp Octets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_recv The receive count.
+ *****************************************************************************/
+void evel_service_local_rtp_oct_recv_set(EVENT_SERVICE * const event,
+ const int rtp_oct_recv);
+
+/**************************************************************************//**
+ * Set the Local Rtp Octets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_sent The send count.
+ *****************************************************************************/
+void evel_service_local_rtp_oct_sent_set(EVENT_SERVICE * const event,
+ const int rtp_oct_sent);
+
+/**************************************************************************//**
+ * Set the Local Rtp Packets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_disc The discard count.
+ *****************************************************************************/
+void evel_service_local_rtp_pkt_disc_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_disc);
+
+/**************************************************************************//**
+ * Set the Local Rtp Packets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_recv The receive count.
+ *****************************************************************************/
+void evel_service_local_rtp_pkt_recv_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_recv);
+
+/**************************************************************************//**
+ * Set the Local Rtp Packets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_sent The send count.
+ *****************************************************************************/
+void evel_service_local_rtp_pkt_sent_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_sent);
+
+/**************************************************************************//**
+ * Set the Mos Cqe property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param mos_cqe The mosCqe to be set.
+ *****************************************************************************/
+void evel_service_mos_cqe_set(EVENT_SERVICE * const event,
+ const double mos_cqe);
+
+/**************************************************************************//**
+ * Set the Packets Lost property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param packets_lost The number of packets lost to be set.
+ *****************************************************************************/
+void evel_service_packets_lost_set(EVENT_SERVICE * const event,
+ const int packets_lost);
+
+/**************************************************************************//**
+ * Set the packet Loss Percent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param packet_loss_percent
+ * The packet loss in percent.
+ *****************************************************************************/
+void evel_service_packet_loss_percent_set(EVENT_SERVICE * const event,
+ const double packet_loss_percent);
+
+/**************************************************************************//**
+ * Set the R Factor property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param r_factor The R Factor to be set.
+ *****************************************************************************/
+void evel_service_r_factor_set(EVENT_SERVICE * const event,
+ const int r_factor);
+
+/**************************************************************************//**
+ * Set the Round Trip Delay property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param round_trip_delay
+ * The Round trip delay to be set.
+ *****************************************************************************/
+void evel_service_round_trip_delay_set(EVENT_SERVICE * const event,
+ const int round_trip_delay);
+
+/**************************************************************************//**
+ * Set the Phone Number property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param phone_number The Phone Number to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_phone_number_set(EVENT_SERVICE * const event,
+ const char * const phone_number);
+
+/**************************************************************************//**
+ * Add a name/value pair to the Service, under the additionalFields array.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param event Pointer to the Service event.
+ * @param name ASCIIZ string with the field's name. The caller does not
+ * need to preserve the value once the function returns.
+ * @param value ASCIIZ string with the field's value. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_addl_field_add(EVENT_SERVICE * const event,
+ const char * const name,
+ const char * const value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* SIGNALING */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Signaling event.
+ *
+ * @note The mandatory fields on the Signaling must be supplied to
+ * this factory function and are immutable once set. Optional fields
+ * have explicit setter functions, but again values may only be set
+ * once so that the event has immutable properties.
+ * @param vendor_id The vendor id to encode in the event instance id.
+ * @param event_id The vendor event id to encode in the event instance id.
+ * @returns pointer to the newly manufactured ::EVENT_SIGNALING. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_signaling.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SIGNALING * evel_new_signaling(const char * const vendor_id,
+ const char * const event_id);
+
+/**************************************************************************//**
+ * Free a Signaling event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the event itself, since that may be part of a larger
+ * structure.
+ *****************************************************************************/
+void evel_free_signaling(EVENT_SIGNALING * const event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_type_set(EVENT_SIGNALING * const event,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Product Id property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param product_id The vendor product id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_product_id_set(EVENT_SIGNALING * const event,
+ const char * const product_id);
+
+/**************************************************************************//**
+ * Set the Subsystem Id property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param subsystem_id The vendor subsystem id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_subsystem_id_set(EVENT_SIGNALING * const event,
+ const char * const subsystem_id);
+
+/**************************************************************************//**
+ * Set the Friendly Name property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param friendly_name The vendor friendly name to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_friendly_name_set(EVENT_SIGNALING * const event,
+ const char * const friendly_name);
+
+/**************************************************************************//**
+ * Set the Correlator property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param correlator The correlator to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_correlator_set(EVENT_SIGNALING * const event,
+ const char * const correlator);
+
+/**************************************************************************//**
+ * Set the Local Ip Address property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param local_ip_address
+ * The Local Ip Address to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_local_ip_address_set(EVENT_SIGNALING * const event,
+ const char * const local_ip_address);
+
+/**************************************************************************//**
+ * Set the Local Port property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param local_port The Local Port to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_local_port_set(EVENT_SIGNALING * const event,
+ const char * const local_port);
+
+/**************************************************************************//**
+ * Set the Remote Ip Address property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param remote_ip_address
+ * The Remote Ip Address to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_remote_ip_address_set(EVENT_SIGNALING * const event,
+ const char * const remote_ip_address);
+
+/**************************************************************************//**
+ * Set the Remote Port property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param remote_port The Remote Port to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_remote_port_set(EVENT_SIGNALING * const event,
+ const char * const remote_port);
+
+/**************************************************************************//**
+ * Set the Compressed SIP property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param compressed_sip
+ * The Compressed SIP to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_compressed_sip_set(EVENT_SIGNALING * const event,
+ const char * const compressed_sip);
+
+/**************************************************************************//**
+ * Set the Summary SIP property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param summary_sip The Summary SIP to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_summary_sip_set(EVENT_SIGNALING * const event,
+ const char * const summary_sip);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* STATE CHANGE */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new State Change event.
+ *
+ * @note The mandatory fields on the Syslog must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Syslog has immutable properties.
+ *
+ * @param new_state The new state of the reporting entity.
+ * @param old_state The old state of the reporting entity.
+ * @param interface The card or port name of the reporting entity.
+ *
+ * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE. If the
+ * event is not used it must be released using
+ * ::evel_free_state_change
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_STATE_CHANGE * evel_new_state_change(const EVEL_ENTITY_STATE new_state,
+ const EVEL_ENTITY_STATE old_state,
+ const char * const interface);
+
+/**************************************************************************//**
+ * Free a State Change.
+ *
+ * Free off the State Change supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the State Change itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_state_change(EVENT_STATE_CHANGE * const state_change);
+
+/**************************************************************************//**
+ * Set the Event Type property of the State Change.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_state_change_type_set(EVENT_STATE_CHANGE * const state_change,
+ const char * const type);
+
+/**************************************************************************//**
+ * Add an additional field name/value pair to the State Change.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE.
+ * @param name ASCIIZ string with the attribute's name. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ * @param value ASCIIZ string with the attribute's value. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_state_change_addl_field_add(EVENT_STATE_CHANGE * const state_change,
+ const char * const name,
+ const char * const value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* SYSLOG */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new syslog event.
+ *
+ * @note The mandatory fields on the Syslog must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Syslog has immutable properties.
+ *
+ * @param event_source_type
+ * @param syslog_msg
+ * @param syslog_tag
+ *
+ * @returns pointer to the newly manufactured ::EVENT_SYSLOG. If the event is
+ * not used it must be released using ::evel_free_syslog
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SYSLOG * evel_new_syslog(EVEL_SOURCE_TYPES event_source_type,
+ const char * const syslog_msg,
+ const char * const syslog_tag);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the syslog.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_type_set(EVENT_SYSLOG * syslog,
+ const char * const type);
+
+/**************************************************************************//**
+ * Free a Syslog.
+ *
+ * Free off the Syslog supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Syslog itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_syslog(EVENT_SYSLOG * event);
+
+/**************************************************************************//**
+ * Add an additional field name/value pair to the Syslog.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param syslog Pointer to the syslog.
+ * @param name ASCIIZ string with the attribute's name. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ * @param value ASCIIZ string with the attribute's value. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_addl_field_add(EVENT_SYSLOG * syslog,
+ char * name,
+ char * value);
+
+/**************************************************************************//**
+ * Set the Event Source Host property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param host The Event Source Host to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_syslog_event_source_host_set(EVENT_SYSLOG * syslog,
+ const char * const host);
+
+/**************************************************************************//**
+ * Set the Syslog Facility property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param facility The Syslog Facility to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_facility_set(EVENT_SYSLOG * syslog,
+ EVEL_SYSLOG_FACILITIES facility);
+
+/**************************************************************************//**
+ * Set the Process property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param proc The Process to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_syslog_proc_set(EVENT_SYSLOG * syslog, const char * const proc);
+
+/**************************************************************************//**
+ * Set the Process ID property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param proc_id The Process ID to be set.
+ *****************************************************************************/
+void evel_syslog_proc_id_set(EVENT_SYSLOG * syslog, int proc_id);
+
+/**************************************************************************//**
+ * Set the Version property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param version The Version to be set.
+ *****************************************************************************/
+void evel_syslog_version_set(EVENT_SYSLOG * syslog, int version);
+
+/**************************************************************************//**
+ * Set the Structured Data property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param s_data The Structured Data to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_s_data_set(EVENT_SYSLOG * syslog, const char * const s_data);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* OTHER */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new other event.
+ *
+ *
+ * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is
+ * not used it must be released using ::evel_free_other.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_OTHER * evel_new_other(void);
+
+/**************************************************************************//**
+ * Free an Other.
+ *
+ * Free off the Other supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Other itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_other(EVENT_OTHER * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Other.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param other Pointer to the Other.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_other_type_set(EVENT_OTHER * other,
+ const char * const type);
+
+/**************************************************************************//**
+ * Add a value name/value pair to the Other.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param other Pointer to the Other.
+ * @param name ASCIIZ string with the attribute's name.
+ * @param value ASCIIZ string with the attribute's value.
+ *****************************************************************************/
+void evel_other_field_add(EVENT_OTHER * other,
+ char * name,
+ char * value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* THROTTLING */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Return the current measurement interval provided by the Event Listener.
+ *
+ * @returns The current measurement interval
+ * @retval EVEL_MEASUREMENT_INTERVAL_UKNOWN (0) - interval has not been
+ * specified
+ *****************************************************************************/
+int evel_get_measurement_interval();
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* LOGGING */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* Debug macros. */
+/*****************************************************************************/
+#define EVEL_DEBUG(FMT, ...) log_debug(EVEL_LOG_DEBUG, (FMT), ##__VA_ARGS__)
+#define EVEL_INFO(FMT, ...) log_debug(EVEL_LOG_INFO, (FMT), ##__VA_ARGS__)
+#define EVEL_SPAMMY(FMT, ...) log_debug(EVEL_LOG_SPAMMY, (FMT), ##__VA_ARGS__)
+#define EVEL_ERROR(FMT, ...) log_debug(EVEL_LOG_ERROR, "ERROR: " FMT, \
+ ##__VA_ARGS__)
+#define EVEL_ENTER() \
+ { \
+ log_debug(EVEL_LOG_DEBUG, "Enter %s {", __FUNCTION__); \
+ debug_indent += 2; \
+ }
+#define EVEL_EXIT() \
+ { \
+ debug_indent -= 2; \
+ log_debug(EVEL_LOG_DEBUG, "Exit %s }", __FUNCTION__); \
+ }
+
+#define INDENT_SEPARATORS \
+ "| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | "
+
+extern EVEL_LOG_LEVELS debug_level;
+extern int debug_indent;
+extern FILE * fout;
+
+#define EVEL_DEBUG_ON() ((debug_level) >= EVEL_LOG_DEBUG)
+
+/**************************************************************************//**
+ * Initialize logging
+ *
+ * @param[in] level The debugging level - one of ::EVEL_LOG_LEVELS.
+ * @param[in] ident The identifier for our logs.
+ *****************************************************************************/
+void log_initialize(EVEL_LOG_LEVELS level, const char * ident);
+
+/**************************************************************************//**
+ * Log debug information
+ *
+ * Logs debugging information in a platform independent manner.
+ *
+ * @param[in] level The debugging level - one of ::EVEL_LOG_LEVELS.
+ * @param[in] format Log formatting string in printf format.
+ * @param[in] ... Variable argument list.
+ *****************************************************************************/
+void log_debug(EVEL_LOG_LEVELS level, char * format, ...);
+
+/***************************************************************************//*
+ * Store the formatted string into the static error string and log the error.
+ *
+ * @param format Error string in standard printf format.
+ * @param ... Variable parameters to be substituted into the format string.
+ *****************************************************************************/
+void log_error_state(char * format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vnfs/VES/code/evel_library/evel_event.c b/vnfs/VES/code/evel_library/evel_event.c
new file mode 100644
index 00000000..2e49870f
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_event.c
@@ -0,0 +1,568 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Event Headers - since
+ * Heartbeats only contain the Event Header, the Heartbeat factory function is
+ * here too.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+#include "metadata.h"
+
+/**************************************************************************//**
+ * Unique sequence number for events from this VNF.
+ *****************************************************************************/
+static int event_sequence = 1;
+
+/**************************************************************************//**
+ * Set the next event_sequence to use.
+ *
+ * @param sequence The next sequence number to use.
+ *****************************************************************************/
+void evel_set_next_event_sequence(const int sequence)
+{
+ EVEL_ENTER();
+
+ EVEL_INFO("Setting event sequence to %d, was %d ", sequence, event_sequence);
+ event_sequence = sequence;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new heartbeat event.
+ *
+ * @note that the heartbeat is just a "naked" commonEventHeader!
+ *
+ * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is
+ * not used it must be released using ::evel_free_event
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_HEADER * evel_new_heartbeat()
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Allocate the header. */
+ /***************************************************************************/
+ heartbeat = malloc(sizeof(EVENT_HEADER));
+ if (heartbeat == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(heartbeat, 0, sizeof(EVENT_HEADER));
+
+ /***************************************************************************/
+ /* Initialize the header. Get a new event sequence number. Note that if */
+ /* any memory allocation fails in here we will fail gracefully because */
+ /* everything downstream can cope with NULLs. */
+ /***************************************************************************/
+ evel_init_header(heartbeat);
+ evel_force_option_string(&heartbeat->event_type, "Autonomous heartbeat");
+
+exit_label:
+ EVEL_EXIT();
+ return heartbeat;
+}
+
+/**************************************************************************//**
+ * Initialize a newly created event header.
+ *
+ * @param header Pointer to the header being initialized.
+ *****************************************************************************/
+void evel_init_header(EVENT_HEADER * const header)
+{
+ char scratchpad[EVEL_MAX_STRING_LEN + 1] = {0};
+ struct timeval tv;
+
+ EVEL_ENTER();
+
+ assert(header != NULL);
+
+ gettimeofday(&tv, NULL);
+
+ /***************************************************************************/
+ /* Initialize the header. Get a new event sequence number. Note that if */
+ /* any memory allocation fails in here we will fail gracefully because */
+ /* everything downstream can cope with NULLs. */
+ /***************************************************************************/
+ header->event_domain = EVEL_DOMAIN_HEARTBEAT;
+ snprintf(scratchpad, EVEL_MAX_STRING_LEN, "%d", event_sequence);
+ header->event_id = strdup(scratchpad);
+ header->functional_role = strdup(functional_role);
+ header->last_epoch_microsec = tv.tv_usec + 1000000 * tv.tv_sec;
+ header->priority = EVEL_PRIORITY_NORMAL;
+ header->reporting_entity_name = strdup(openstack_vm_name());
+ header->source_name = strdup(openstack_vm_name());
+ header->sequence = event_sequence;
+ header->start_epoch_microsec = header->last_epoch_microsec;
+ header->major_version = EVEL_HEADER_MAJOR_VERSION;
+ header->minor_version = EVEL_HEADER_MINOR_VERSION;
+ event_sequence++;
+
+ /***************************************************************************/
+ /* Optional parameters. */
+ /***************************************************************************/
+ evel_init_option_string(&header->event_type);
+ evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid());
+ evel_force_option_string(&header->source_id, openstack_vm_uuid());
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the event header.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_header_type_set(EVENT_HEADER * const header,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(header != NULL);
+ assert(type != NULL);
+
+ evel_set_option_string(&header->event_type, type, "Event Type");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Start Epoch property of the event header.
+ *
+ * @note The Start Epoch defaults to the time of event creation.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param start_epoch_microsec
+ * The start epoch to set, in microseconds.
+ *****************************************************************************/
+void evel_start_epoch_set(EVENT_HEADER * const header,
+ const unsigned long long start_epoch_microsec)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and assign the new value. */
+ /***************************************************************************/
+ assert(header != NULL);
+ header->start_epoch_microsec = start_epoch_microsec;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Last Epoch property of the event header.
+ *
+ * @note The Last Epoch defaults to the time of event creation.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param last_epoch_microsec
+ * The last epoch to set, in microseconds.
+ *****************************************************************************/
+void evel_last_epoch_set(EVENT_HEADER * const header,
+ const unsigned long long last_epoch_microsec)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and assign the new value. */
+ /***************************************************************************/
+ assert(header != NULL);
+ header->last_epoch_microsec = last_epoch_microsec;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Reporting Entity Name property of the event header.
+ *
+ * @note The Reporting Entity Name defaults to the OpenStack VM Name.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param entity_name The entity name to set.
+ *****************************************************************************/
+void evel_reporting_entity_name_set(EVENT_HEADER * const header,
+ const char * const entity_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and assign the new value. */
+ /***************************************************************************/
+ assert(header != NULL);
+ assert(entity_name != NULL);
+ assert(header->reporting_entity_name != NULL);
+
+ /***************************************************************************/
+ /* Free the previously allocated memory and replace it with a copy of the */
+ /* provided one. */
+ /***************************************************************************/
+ free(header->reporting_entity_name);
+ header->reporting_entity_name = strdup(entity_name);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Reporting Entity Id property of the event header.
+ *
+ * @note The Reporting Entity Id defaults to the OpenStack VM UUID.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param entity_id The entity id to set.
+ *****************************************************************************/
+void evel_reporting_entity_id_set(EVENT_HEADER * const header,
+ const char * const entity_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and assign the new value. */
+ /***************************************************************************/
+ assert(header != NULL);
+ assert(entity_id != NULL);
+
+ /***************************************************************************/
+ /* Free the previously allocated memory and replace it with a copy of the */
+ /* provided one. Note that evel_force_option_string strdups entity_id. */
+ /***************************************************************************/
+ evel_free_option_string(&header->reporting_entity_id);
+ evel_force_option_string(&header->reporting_entity_id, entity_id);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the event as a JSON event object according to AT&T's schema.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf,
+ EVENT_HEADER * event)
+{
+ char * domain;
+ char * priority;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(jbuf->json != NULL);
+ assert(jbuf->max_size > 0);
+ assert(event != NULL);
+
+ domain = evel_event_domain(event->event_domain);
+ priority = evel_event_priority(event->priority);
+ evel_json_open_named_object(jbuf, "commonEventHeader");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "domain", domain);
+ evel_enc_kv_string(jbuf, "eventId", event->event_id);
+ evel_enc_kv_string(jbuf, "functionalRole", event->functional_role);
+ evel_enc_kv_ull(jbuf, "lastEpochMicrosec", event->last_epoch_microsec);
+ evel_enc_kv_string(jbuf, "priority", priority);
+ evel_enc_kv_string(
+ jbuf, "reportingEntityName", event->reporting_entity_name);
+ evel_enc_kv_int(jbuf, "sequence", event->sequence);
+ evel_enc_kv_string(jbuf, "sourceName", event->source_name);
+ evel_enc_kv_ull(jbuf, "startEpochMicrosec", event->start_epoch_microsec);
+ evel_enc_version(
+ jbuf, "version", event->major_version, event->minor_version);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "eventType", &event->event_type);
+ evel_enc_kv_opt_string(
+ jbuf, "reportingEntityId", &event->reporting_entity_id);
+ evel_enc_kv_opt_string(jbuf, "sourceId", &event->source_id);
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free an event header.
+ *
+ * Free off the event header supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the header itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_header(EVENT_HEADER * const event)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+
+ /***************************************************************************/
+ /* Free all internal strings. */
+ /***************************************************************************/
+ free(event->event_id);
+ evel_free_option_string(&event->event_type);
+ free(event->functional_role);
+ evel_free_option_string(&event->reporting_entity_id);
+ free(event->reporting_entity_name);
+ evel_free_option_string(&event->source_id);
+ free(event->source_name);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the event as a JSON event object according to AT&T's schema.
+ *
+ * @param json Pointer to where to store the JSON encoded data.
+ * @param max_size Size of storage available in json_body.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ * @returns Number of bytes actually written.
+ *****************************************************************************/
+int evel_json_encode_event(char * json,
+ int max_size,
+ EVENT_HEADER * event)
+{
+ EVEL_JSON_BUFFER json_buffer;
+ EVEL_JSON_BUFFER * jbuf = &json_buffer;
+ EVEL_THROTTLE_SPEC * throttle_spec;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Get the latest throttle specification for the domain. */
+ /***************************************************************************/
+ throttle_spec = evel_get_throttle_spec(event->event_domain);
+
+ /***************************************************************************/
+ /* Initialize the JSON_BUFFER and open the top-level objects. */
+ /***************************************************************************/
+ evel_json_buffer_init(jbuf, json, max_size, throttle_spec);
+ evel_json_open_object(jbuf);
+ evel_json_open_named_object(jbuf, "event");
+
+ switch (event->event_domain)
+ {
+ case EVEL_DOMAIN_HEARTBEAT:
+ evel_json_encode_header(jbuf, event);
+ break;
+
+ case EVEL_DOMAIN_FAULT:
+ evel_json_encode_fault(jbuf, (EVENT_FAULT *)event);
+ break;
+
+ case EVEL_DOMAIN_MEASUREMENT:
+ evel_json_encode_measurement(jbuf, (EVENT_MEASUREMENT *)event);
+ break;
+
+ case EVEL_DOMAIN_MOBILE_FLOW:
+ evel_json_encode_mobile_flow(jbuf, (EVENT_MOBILE_FLOW *)event);
+ break;
+
+ case EVEL_DOMAIN_REPORT:
+ evel_json_encode_report(jbuf, (EVENT_REPORT *)event);
+ break;
+
+ case EVEL_DOMAIN_SERVICE:
+ evel_json_encode_service(jbuf, (EVENT_SERVICE *)event);
+ break;
+
+ case EVEL_DOMAIN_SIGNALING:
+ evel_json_encode_signaling(jbuf, (EVENT_SIGNALING *)event);
+ break;
+
+ case EVEL_DOMAIN_STATE_CHANGE:
+ evel_json_encode_state_change(jbuf, (EVENT_STATE_CHANGE *)event);
+ break;
+
+ case EVEL_DOMAIN_SYSLOG:
+ evel_json_encode_syslog(jbuf, (EVENT_SYSLOG *)event);
+ break;
+
+ case EVEL_DOMAIN_OTHER:
+ evel_json_encode_other(jbuf, (EVENT_OTHER *)event);
+ break;
+
+ case EVEL_DOMAIN_INTERNAL:
+ default:
+ EVEL_ERROR("Unexpected domain %d", event->event_domain);
+ assert(0);
+ }
+
+ evel_json_close_object(jbuf);
+ evel_json_close_object(jbuf);
+
+ /***************************************************************************/
+ /* Sanity check. */
+ /***************************************************************************/
+ assert(jbuf->depth == 0);
+
+ EVEL_EXIT();
+
+ return jbuf->offset;
+}
+
+/**************************************************************************//**
+ * Initialize an event instance id.
+ *
+ * @param instance_id Pointer to the event instance id being initialized.
+ * @param vendor_id The vendor id to encode in the event instance id.
+ * @param event_id The event id to encode in the event instance id.
+ *****************************************************************************/
+void evel_init_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id,
+ const char * const vendor_id,
+ const char * const event_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(instance_id != NULL);
+ assert(vendor_id != NULL);
+ assert(event_id != NULL);
+
+ /***************************************************************************/
+ /* Store the mandatory parts. */
+ /***************************************************************************/
+ instance_id->vendor_id = strdup(vendor_id);
+ instance_id->event_id = strdup(event_id);
+
+ /***************************************************************************/
+ /* Initialize the optional parts. */
+ /***************************************************************************/
+ evel_init_option_string(&instance_id->product_id);
+ evel_init_option_string(&instance_id->subsystem_id);
+ evel_init_option_string(&instance_id->event_friendly_name);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free an event instance id.
+ *
+ * @param instance_id Pointer to the event instance id being initialized.
+ *****************************************************************************/
+void evel_free_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(instance_id != NULL);
+ assert(instance_id->vendor_id != NULL);
+ assert(instance_id->event_id != NULL);
+
+ /***************************************************************************/
+ /* Free everything. */
+ /***************************************************************************/
+ free(instance_id->vendor_id);
+ free(instance_id->event_id);
+ evel_free_option_string(&instance_id->product_id);
+ evel_free_option_string(&instance_id->subsystem_id);
+ evel_free_option_string(&instance_id->event_friendly_name);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the instance id as a JSON object according to AT&T's schema.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param instance_id Pointer to the ::EVEL_EVENT_INSTANCE_ID to encode.
+ *****************************************************************************/
+void evel_json_encode_instance_id(EVEL_JSON_BUFFER * jbuf,
+ EVEL_EVENT_INSTANCE_ID * instance_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(jbuf->json != NULL);
+ assert(jbuf->max_size > 0);
+ assert(instance_id != NULL);
+ assert(instance_id->vendor_id != NULL);
+ assert(instance_id->event_id != NULL);
+
+ evel_json_open_named_object(jbuf, "eventInstanceIdentifier");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "vendorId", instance_id->vendor_id);
+ evel_enc_kv_string(jbuf, "eventId", instance_id->event_id);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "productId", &instance_id->product_id);
+ evel_enc_kv_opt_string(jbuf, "subsystemId", &instance_id->subsystem_id);
+ evel_enc_kv_opt_string(
+ jbuf, "eventFriendlyName", &instance_id->event_friendly_name);
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_event_mgr.c b/vnfs/VES/code/evel_library/evel_event_mgr.c
new file mode 100644
index 00000000..0cc049f5
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_event_mgr.c
@@ -0,0 +1,1053 @@
+/**************************************************************************//**
+ * @file
+ * Event Manager
+ *
+ * Simple event manager that is responsible for taking events (Heartbeats,
+ * Faults and Measurements) from the ring-buffer and posting them to the API.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <curl/curl.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "ring_buffer.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * How long we're prepared to wait for the API service to respond in
+ * seconds.
+ *****************************************************************************/
+static const int EVEL_API_TIMEOUT = 5;
+
+/*****************************************************************************/
+/* Prototypes of locally scoped functions. */
+/*****************************************************************************/
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
+static void * event_handler(void *arg);
+static bool evel_handle_response_tokens(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post);
+static bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_token,
+ const int num_tokens);
+static bool evel_token_equals_string(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_token,
+ const char * check_string);
+
+/**************************************************************************//**
+ * Buffers for error strings from libcurl.
+ *****************************************************************************/
+static char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
+
+/**************************************************************************//**
+ * Handle for the API into libcurl.
+ *****************************************************************************/
+static CURL * curl_handle = NULL;
+
+/**************************************************************************//**
+ * Special headers that we send.
+ *****************************************************************************/
+static struct curl_slist * hdr_chunk = NULL;
+
+/**************************************************************************//**
+ * Message queue for sending events to the API.
+ *****************************************************************************/
+static ring_buffer event_buffer;
+
+/**************************************************************************//**
+ * Single pending priority post, which can be generated as a result of a
+ * response to an event. Currently only used to respond to a commandList.
+ *****************************************************************************/
+static MEMORY_CHUNK priority_post;
+
+/**************************************************************************//**
+ * The thread which is responsible for handling events off of the ring-buffer
+ * and posting them to the Event Handler API.
+ *****************************************************************************/
+static pthread_t evt_handler_thread;
+
+/**************************************************************************//**
+ * Variable to convey to the event handler thread what the foreground wants it
+ * to do.
+ *****************************************************************************/
+static EVT_HANDLER_STATE evt_handler_state = EVT_HANDLER_UNINITIALIZED;
+
+/**************************************************************************//**
+ * The configured API URL for event and throttling.
+ *****************************************************************************/
+static char * evel_event_api_url;
+static char * evel_throt_api_url;
+
+/**************************************************************************//**
+ * Initialize the event handler.
+ *
+ * Primarily responsible for getting CURL ready for use.
+ *
+ * @param[in] event_api_url
+ * The URL where the Vendor Event Listener API is expected
+ * to be.
+ * @param[in] throt_api_url
+ * The URL where the Throttling API is expected to be.
+ * @param[in] username The username for the Basic Authentication of requests.
+ * @param[in] password The password for the Basic Authentication of requests.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url,
+ const char * const throt_api_url,
+ const char * const username,
+ const char * const password,
+ int verbosity)
+{
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc = CURLE_OK;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(event_api_url != NULL);
+ assert(throt_api_url != NULL);
+ assert(username != NULL);
+ assert(password != NULL);
+
+ /***************************************************************************/
+ /* Store the API URLs. */
+ /***************************************************************************/
+ evel_event_api_url = strdup(event_api_url);
+ assert(evel_event_api_url != NULL);
+ evel_throt_api_url = strdup(throt_api_url);
+ assert(evel_throt_api_url != NULL);
+
+ /***************************************************************************/
+ /* Start the CURL library. Note that this initialization is not threadsafe */
+ /* which imposes a constraint that the EVEL library is initialized before */
+ /* any threads are started. */
+ /***************************************************************************/
+ curl_rc = curl_global_init(CURL_GLOBAL_SSL);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL. Error code=%d", curl_rc);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Get a curl handle which we'll use for all of our output. */
+ /***************************************************************************/
+ curl_handle = curl_easy_init();
+ if (curl_handle == NULL)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to get libCURL handle");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Prime the library to give friendly error codes. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_ERRORBUFFER,
+ curl_err_string);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to provide friendly errors. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* If running in verbose mode generate more output. */
+ /***************************************************************************/
+ if (verbosity > 0)
+ {
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to be verbose. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+ }
+
+ /***************************************************************************/
+ /* Set the URL for the API. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, event_api_url);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with the API URL. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_INFO("Initializing CURL to send events to: %s", event_api_url);
+
+ /***************************************************************************/
+ /* send all data to this function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_WRITEFUNCTION,
+ evel_write_callback);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with the write callback. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* some servers don't like requests that are made without a user-agent */
+ /* field, so we provide one. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_USERAGENT,
+ "libcurl-agent/1.0");
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Specify that we are going to POST data. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* we want to use our own read function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload using read "
+ "function. Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* All of our events are JSON encoded. We also suppress the */
+ /* Expect: 100-continue header that we would otherwise get since it */
+ /* confuses some servers. */
+ /* */
+ /* @TODO: do AT&T want this behavior? */
+ /***************************************************************************/
+ hdr_chunk = curl_slist_append(hdr_chunk, "Content-type: application/json");
+ hdr_chunk = curl_slist_append(hdr_chunk, "Expect:");
+
+ /***************************************************************************/
+ /* set our custom set of headers. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, hdr_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to use custom headers. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set the timeout for the operation. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_TIMEOUT,
+ EVEL_API_TIMEOUT);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL for API timeout. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set that we want Basic authentication with username:password Base-64 */
+ /* encoded for the operation. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL for Basic Authentication. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_USERNAME, username);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with username. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_PASSWORD, password);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with password. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Initialize a message ring-buffer to be used between the foreground and */
+ /* the thread which sends the messages. This can't fail. */
+ /***************************************************************************/
+ ring_buffer_initialize(&event_buffer, EVEL_EVENT_BUFFER_DEPTH);
+
+ /***************************************************************************/
+ /* Initialize the priority post buffer to empty. */
+ /***************************************************************************/
+ priority_post.memory = NULL;
+
+exit_label:
+ EVEL_EXIT();
+
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Run the event handler.
+ *
+ * Spawns the thread responsible for handling events and sending them to the
+ * API.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_run()
+{
+ EVEL_ERR_CODES rc = EVEL_SUCCESS;
+ int pthread_rc = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Start the event handler thread. */
+ /***************************************************************************/
+ evt_handler_state = EVT_HANDLER_INACTIVE;
+ pthread_rc = pthread_create(&evt_handler_thread, NULL, event_handler, NULL);
+ if (pthread_rc != 0)
+ {
+ rc = EVEL_PTHREAD_LIBRARY_FAIL;
+ log_error_state("Failed to start event handler thread. "
+ "Error code=%d", pthread_rc);
+ }
+
+ EVEL_EXIT()
+ return rc;
+}
+
+/**************************************************************************//**
+ * Terminate the event handler.
+ *
+ * Shuts down the event handler thread in as clean a way as possible. Sets the
+ * global exit flag and then signals the thread to interrupt it since it's
+ * most likely waiting on the ring-buffer.
+ *
+ * Having achieved an orderly shutdown of the event handler thread, clean up
+ * the cURL library's resources cleanly.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_terminate()
+{
+ EVEL_ERR_CODES rc = EVEL_SUCCESS;
+
+ EVEL_ENTER();
+ EVENT_INTERNAL *event = NULL;
+
+ /***************************************************************************/
+ /* Make sure that we were initialized before trying to terminate the */
+ /* event handler thread. */
+ /***************************************************************************/
+ if (evt_handler_state != EVT_HANDLER_UNINITIALIZED)
+ {
+ /*************************************************************************/
+ /* Make sure that the event handler knows it's time to die. */
+ /*************************************************************************/
+ event = evel_new_internal_event(EVT_CMD_TERMINATE);
+ if (event == NULL)
+ {
+ /***********************************************************************/
+ /* We failed to get an event, but we don't bail out - we will just */
+ /* clean up what we can and continue on our way, since we're exiting */
+ /* anyway. */
+ /***********************************************************************/
+ EVEL_ERROR("Failed to get internal event - perform dirty exit instead!");
+ }
+ else
+ {
+ /***********************************************************************/
+ /* Post the event then wait for the Event Handler to exit. Set the */
+ /* global command, too, in case the ring-buffer is full. */
+ /***********************************************************************/
+ EVEL_DEBUG("Sending event to Event Hander to request it to exit.");
+ evt_handler_state = EVT_HANDLER_REQUEST_TERMINATE;
+ evel_post_event((EVENT_HEADER *) event);
+ pthread_join(evt_handler_thread, NULL);
+ EVEL_DEBUG("Event Handler thread has exited.");
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("Event handler was not initialized, so no need to kill it");
+ }
+
+ /***************************************************************************/
+ /* Clean-up the cURL library. */
+ /***************************************************************************/
+ if (curl_handle != NULL)
+ {
+ curl_easy_cleanup(curl_handle);
+ curl_handle = NULL;
+ }
+ if (hdr_chunk != NULL)
+ {
+ curl_slist_free_all(hdr_chunk);
+ hdr_chunk = NULL;
+ }
+
+ /***************************************************************************/
+ /* Free off the stored API URL strings. */
+ /***************************************************************************/
+ if (evel_event_api_url != NULL)
+ {
+ free(evel_event_api_url);
+ evel_event_api_url = NULL;
+ }
+ if (evel_throt_api_url != NULL)
+ {
+ free(evel_throt_api_url);
+ evel_throt_api_url = NULL;
+ }
+
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Post an event.
+ *
+ * @note So far as the caller is concerned, successfully posting the event
+ * relinquishes all responsibility for the event - the library will take care
+ * of freeing the event in due course.
+
+ * @param event The event to be posted.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_post_event(EVENT_HEADER * event)
+{
+ int rc = EVEL_SUCCESS;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+
+ /***************************************************************************/
+ /* We need to make sure that we are either initializing or running */
+ /* normally before writing the event into the buffer so that we can */
+ /* guarantee that the ring-buffer empties properly on exit. */
+ /***************************************************************************/
+ if ((evt_handler_state == EVT_HANDLER_ACTIVE) ||
+ (evt_handler_state == EVT_HANDLER_INACTIVE) ||
+ (evt_handler_state == EVT_HANDLER_REQUEST_TERMINATE))
+ {
+ if (ring_buffer_write(&event_buffer, event) == 0)
+ {
+ log_error_state("Failed to write event to buffer - event dropped!");
+ rc = EVEL_EVENT_BUFFER_FULL;
+ evel_free_event(event);
+ }
+ }
+ else
+ {
+ /*************************************************************************/
+ /* System is not in active operation, so reject the event. */
+ /*************************************************************************/
+ log_error_state("Event Handler system not active - event dropped!");
+ rc = EVEL_EVENT_HANDLER_INACTIVE;
+ evel_free_event(event);
+ }
+
+ EVEL_EXIT();
+ return (rc);
+}
+
+/**************************************************************************//**
+ * Post an event to the Vendor Event Listener API.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+static EVEL_ERR_CODES evel_post_api(char * msg, size_t size)
+{
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc = CURLE_OK;
+ MEMORY_CHUNK rx_chunk;
+ MEMORY_CHUNK tx_chunk;
+ int http_response_code = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Create the memory chunk to be used for the response to the post. The */
+ /* will be realloced. */
+ /***************************************************************************/
+ rx_chunk.memory = malloc(1);
+ assert(rx_chunk.memory != NULL);
+ rx_chunk.size = 0;
+
+ /***************************************************************************/
+ /* Create the memory chunk to be sent as the body of the post. */
+ /***************************************************************************/
+ tx_chunk.memory = msg;
+ tx_chunk.size = size;
+ EVEL_DEBUG("Sending chunk of size %d", tx_chunk.size);
+
+ /***************************************************************************/
+ /* Point to the data to be received. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &rx_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized data to receive");
+
+ /***************************************************************************/
+ /* Pointer to pass to our read function */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READDATA, &tx_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to set upload data for libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized data to send");
+
+ /***************************************************************************/
+ /* Size of the data to transmit. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_POSTFIELDSIZE,
+ tx_chunk.size);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to set length of upload data for libCURL to "
+ "upload. Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized length of data to send");
+
+ /***************************************************************************/
+ /* Now run off and do what you've been told! */
+ /***************************************************************************/
+ curl_rc = curl_easy_perform(curl_handle);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to transfer an event to Vendor Event Listener! "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ EVEL_ERROR("Dropped event: %s", msg);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* See what response we got - any 2XX response is good. */
+ /***************************************************************************/
+ curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_response_code);
+ EVEL_DEBUG("HTTP response code: %d", http_response_code);
+ if ((http_response_code / 100) == 2)
+ {
+ /*************************************************************************/
+ /* If the server responded with data it may be interesting but not a */
+ /* problem. */
+ /*************************************************************************/
+ if ((rx_chunk.size > 0) && (rx_chunk.memory != NULL))
+ {
+ EVEL_DEBUG("Server returned data = %d (%s)",
+ rx_chunk.size,
+ rx_chunk.memory);
+
+ /***********************************************************************/
+ /* If this is a response to priority post, then we're not interested. */
+ /***********************************************************************/
+ if (priority_post.memory != NULL)
+ {
+ EVEL_ERROR("Ignoring priority post response");
+ }
+ else
+ {
+ evel_handle_event_response(&rx_chunk, &priority_post);
+ }
+ }
+ }
+ else
+ {
+ EVEL_ERROR("Unexpected HTTP response code: %d with data size %d (%s)",
+ http_response_code,
+ rx_chunk.size,
+ rx_chunk.size > 0 ? rx_chunk.memory : "NONE");
+ EVEL_ERROR("Potentially dropped event: %s", msg);
+ }
+
+exit_label:
+ free(rx_chunk.memory);
+ EVEL_EXIT();
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Callback function to provide data to send.
+ *
+ * Copy data into the supplied buffer, read_callback::ptr, checking size
+ * limits.
+ *
+ * @returns Number of bytes placed into read_callback::ptr. 0 for EOF.
+ *****************************************************************************/
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
+{
+ size_t rtn = 0;
+ size_t bytes_to_write = 0;
+ MEMORY_CHUNK *tx_chunk = (MEMORY_CHUNK *)userp;
+
+ EVEL_ENTER();
+
+ bytes_to_write = min(size*nmemb, tx_chunk->size);
+
+ if (bytes_to_write > 0)
+ {
+ EVEL_DEBUG("Going to try to write %d bytes", bytes_to_write);
+ strncpy((char *)ptr, tx_chunk->memory, bytes_to_write);
+ tx_chunk->memory += bytes_to_write;
+ tx_chunk->size -= bytes_to_write;
+ rtn = bytes_to_write;
+ }
+ else
+ {
+ EVEL_DEBUG("Reached EOF");
+ }
+
+ EVEL_EXIT();
+ return rtn;
+}
+
+/**************************************************************************//**
+ * Callback function to provide returned data.
+ *
+ * Copy data into the supplied buffer, write_callback::ptr, checking size
+ * limits.
+ *
+ * @returns Number of bytes placed into write_callback::ptr. 0 for EOF.
+ *****************************************************************************/
+size_t evel_write_callback(void *contents,
+ size_t size,
+ size_t nmemb,
+ void *userp)
+{
+ size_t realsize = size * nmemb;
+ MEMORY_CHUNK * rx_chunk = (MEMORY_CHUNK *)userp;
+
+ EVEL_ENTER();
+
+ EVEL_DEBUG("Called with %d chunks of %d size = %d", nmemb, size, realsize);
+ EVEL_DEBUG("rx chunk size is %d", rx_chunk->size);
+
+ rx_chunk->memory = realloc(rx_chunk->memory, rx_chunk->size + realsize + 1);
+ if(rx_chunk->memory == NULL) {
+ /* out of memory! */
+ printf("not enough memory (realloc returned NULL)\n");
+ return 0;
+ }
+
+ memcpy(&(rx_chunk->memory[rx_chunk->size]), contents, realsize);
+ rx_chunk->size += realsize;
+ rx_chunk->memory[rx_chunk->size] = 0;
+
+ EVEL_DEBUG("Rx data: %s", rx_chunk->memory);
+ EVEL_DEBUG("Returning: %d", realsize);
+
+ EVEL_EXIT();
+ return realsize;
+}
+
+/**************************************************************************//**
+ * Event Handler.
+ *
+ * Watch for messages coming on the internal queue and send them to the
+ * listener.
+ *
+ * param[in] arg Argument - unused.
+ *****************************************************************************/
+static void * event_handler(void * arg __attribute__ ((unused)))
+{
+ int old_type = 0;
+ EVENT_HEADER * msg = NULL;
+ EVENT_INTERNAL * internal_msg = NULL;
+ int json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc;
+
+ EVEL_INFO("Event handler thread started");
+
+ /***************************************************************************/
+ /* Set this thread to be cancellable immediately. */
+ /***************************************************************************/
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
+
+ /***************************************************************************/
+ /* Set the handler as active, defending against weird situations like */
+ /* immediately shutting down after initializing the library so the */
+ /* handler never gets started up properly. */
+ /***************************************************************************/
+ if (evt_handler_state == EVT_HANDLER_INACTIVE)
+ {
+ evt_handler_state = EVT_HANDLER_ACTIVE;
+ }
+ else
+ {
+ EVEL_ERROR("Event Handler State was not INACTIVE at start-up - "
+ "Handler will exit immediately!");
+ }
+
+ while (evt_handler_state == EVT_HANDLER_ACTIVE)
+ {
+ /*************************************************************************/
+ /* Wait for a message to be received. */
+ /*************************************************************************/
+ EVEL_DEBUG("Event handler getting any messages");
+ msg = ring_buffer_read(&event_buffer);
+
+ /*************************************************************************/
+ /* Internal events get special treatment while regular events get posted */
+ /* to the far side. */
+ /*************************************************************************/
+ if (msg->event_domain != EVEL_DOMAIN_INTERNAL)
+ {
+ EVEL_DEBUG("External event received");
+
+ /***********************************************************************/
+ /* Encode the event in JSON. */
+ /***********************************************************************/
+ json_size = evel_json_encode_event(json_body, EVEL_MAX_JSON_BODY, msg);
+
+ /***********************************************************************/
+ /* Send the JSON across the API. */
+ /***********************************************************************/
+ EVEL_DEBUG("Sending JSON of size %d is: %s", json_size, json_body);
+ rc = evel_post_api(json_body, json_size);
+ if (rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Failed to transfer the data. Error code=%d", rc);
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("Internal event received");
+ internal_msg = (EVENT_INTERNAL *) msg;
+ assert(internal_msg->command == EVT_CMD_TERMINATE);
+ evt_handler_state = EVT_HANDLER_TERMINATING;
+ }
+
+ /*************************************************************************/
+ /* We are responsible for freeing the memory. */
+ /*************************************************************************/
+ evel_free_event(msg);
+ msg = NULL;
+
+ /*************************************************************************/
+ /* There may be a single priority post to be sent. */
+ /*************************************************************************/
+ if (priority_post.memory != NULL)
+ {
+ EVEL_DEBUG("Priority Post");
+
+ /***********************************************************************/
+ /* Set the URL for the throttling API. */
+ /***********************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_throt_api_url);
+ if (curl_rc != CURLE_OK)
+ {
+ /*********************************************************************/
+ /* This is only likely to happen with CURLE_OUT_OF_MEMORY, in which */
+ /* case we carry on regardless. */
+ /*********************************************************************/
+ EVEL_ERROR("Failed to set throttling URL. Error code=%d", rc);
+ }
+ else
+ {
+ rc = evel_post_api(priority_post.memory, priority_post.size);
+ if (rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Failed to transfer priority post. Error code=%d", rc);
+ }
+ }
+
+ /***********************************************************************/
+ /* Reinstate the URL for the event API. */
+ /***********************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_event_api_url);
+ if (curl_rc != CURLE_OK)
+ {
+ /*********************************************************************/
+ /* This is only likely to happen with CURLE_OUT_OF_MEMORY, in which */
+ /* case we carry on regardless. */
+ /*********************************************************************/
+ EVEL_ERROR("Failed to reinstate events URL. Error code=%d", rc);
+ }
+
+ /***********************************************************************/
+ /* We are responsible for freeing the memory. */
+ /***********************************************************************/
+ free(priority_post.memory);
+ priority_post.memory = NULL;
+ }
+ }
+
+ /***************************************************************************/
+ /* The event handler is now exiting. The ring-buffer could contain events */
+ /* which have not been processed, so deplete those. Because we've been */
+ /* asked to exit we can be confident that the foreground will have stopped */
+ /* sending events in so we know that this process will conclude! */
+ /***************************************************************************/
+ evt_handler_state = EVT_HANDLER_TERMINATING;
+ while (!ring_buffer_is_empty(&event_buffer))
+ {
+ EVEL_DEBUG("Reading event from buffer");
+ msg = ring_buffer_read(&event_buffer);
+ evel_free_event(msg);
+ }
+ evt_handler_state = EVT_HANDLER_TERMINATED;
+ EVEL_INFO("Event handler thread stopped");
+
+ return (NULL);
+}
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, contained in a ::MEMORY_CHUNK.
+ *
+ * Tokenize the response, and decode any tokens found.
+ *
+ * @param chunk The memory chunk containing the response.
+ * @param post The memory chunk in which to place any resulting POST.
+ *****************************************************************************/
+void evel_handle_event_response(const MEMORY_CHUNK * const chunk,
+ MEMORY_CHUNK * const post)
+{
+ jsmn_parser json_parser;
+ jsmntok_t json_tokens[EVEL_MAX_RESPONSE_TOKENS];
+ int num_tokens = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(priority_post.memory == NULL);
+
+ EVEL_DEBUG("Response size = %d", chunk->size);
+ EVEL_DEBUG("Response = %s", chunk->memory);
+
+ /***************************************************************************/
+ /* Initialize the parser and tokenize the response. */
+ /***************************************************************************/
+ jsmn_init(&json_parser);
+ num_tokens = jsmn_parse(&json_parser,
+ chunk->memory,
+ chunk->size,
+ json_tokens,
+ EVEL_MAX_RESPONSE_TOKENS);
+
+ if (num_tokens < 0)
+ {
+ EVEL_ERROR("Failed to parse JSON response. "
+ "Error code=%d", num_tokens);
+ }
+ else if (num_tokens == 0)
+ {
+ EVEL_DEBUG("No tokens found in JSON response");
+ }
+ else
+ {
+ EVEL_DEBUG("Decode JSON response tokens");
+ if (!evel_handle_response_tokens(chunk, json_tokens, num_tokens, post))
+ {
+ EVEL_ERROR("Failed to handle JSON response.");
+ }
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, as a list of tokens from JSMN.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Array of tokens to handle.
+ * @param num_tokens The number of tokens to handle.
+ * @param post The memory chunk in which to place any resulting POST.
+ * @return true if we handled the response, false otherwise.
+ *****************************************************************************/
+bool evel_handle_response_tokens(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post)
+{
+ bool json_ok = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(json_tokens != NULL);
+ assert(num_tokens < EVEL_MAX_RESPONSE_TOKENS);
+
+ /***************************************************************************/
+ /* Peek at the tokens to decide what the response it, then call the */
+ /* appropriate handler to handle it. There is only one handler at this */
+ /* point. */
+ /***************************************************************************/
+ if (evel_tokens_match_command_list(chunk, json_tokens, num_tokens))
+ {
+ json_ok = evel_handle_command_list(chunk, json_tokens, num_tokens, post);
+ }
+
+ EVEL_EXIT();
+
+ return json_ok;
+}
+
+/**************************************************************************//**
+ * Determine whether a list of tokens looks like a "commandList" response.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Token to check.
+ * @param num_tokens The number of tokens to handle.
+ * @return true if the tokens look like a "commandList" match, or false.
+ *****************************************************************************/
+bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens)
+{
+ bool result = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Make some checks on the basic layout of the commandList. */
+ /***************************************************************************/
+ if ((num_tokens > 3) &&
+ (json_tokens[0].type == JSMN_OBJECT) &&
+ (json_tokens[1].type == JSMN_STRING) &&
+ (json_tokens[2].type == JSMN_ARRAY) &&
+ (evel_token_equals_string(chunk, &json_tokens[1], "commandList")))
+ {
+ result = true;
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Check that a string token matches a given input string.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_token Token to check.
+ * @param check_string String to check it against.
+ * @return true if the strings match, or false.
+ *****************************************************************************/
+bool evel_token_equals_string(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * json_token,
+ const char * check_string)
+{
+ bool result = false;
+
+ EVEL_ENTER();
+
+ const int token_length = json_token->end - json_token->start;
+ const char * const token_string = chunk->memory + json_token->start;
+
+ if (token_length == (int)strlen(check_string))
+ {
+ result = (strncmp(token_string, check_string, token_length) == 0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
diff --git a/vnfs/VES/code/evel_library/evel_fault.c b/vnfs/VES/code/evel_library/evel_fault.c
new file mode 100644
index 00000000..cbb80d71
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_fault.c
@@ -0,0 +1,337 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Fault.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new fault event.
+ *
+ * @note The mandatory fields on the Fault must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Fault has immutable properties.
+ * @param condition The condition indicated by the Fault.
+ * @param specific_problem The specific problem triggering the fault.
+ * @param priority The priority of the event.
+ * @param severity The severity of the Fault.
+ * @returns pointer to the newly manufactured ::EVENT_FAULT. If the event is
+ * not used (i.e. posted) it must be released using ::evel_free_fault.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_FAULT * evel_new_fault(const char * const condition,
+ const char * const specific_problem,
+ EVEL_EVENT_PRIORITIES priority,
+ EVEL_SEVERITIES severity)
+{
+ EVENT_FAULT * fault = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(condition != NULL);
+ assert(specific_problem != NULL);
+ assert(priority < EVEL_MAX_PRIORITIES);
+ assert(severity < EVEL_MAX_SEVERITIES);
+
+ /***************************************************************************/
+ /* Allocate the fault. */
+ /***************************************************************************/
+ fault = malloc(sizeof(EVENT_FAULT));
+ if (fault == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(fault, 0, sizeof(EVENT_FAULT));
+ EVEL_DEBUG("New fault is at %lp", fault);
+
+ /***************************************************************************/
+ /* Initialize the header & the fault fields. Optional string values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&fault->header);
+ fault->header.event_domain = EVEL_DOMAIN_FAULT;
+ fault->header.priority = priority;
+ fault->major_version = EVEL_FAULT_MAJOR_VERSION;
+ fault->minor_version = EVEL_FAULT_MINOR_VERSION;
+ fault->event_severity = severity;
+ fault->event_source_type = event_source_type;
+ fault->vf_status = EVEL_VF_STATUS_ACTIVE;
+ fault->alarm_condition = strdup(condition);
+ fault->specific_problem = strdup(specific_problem);
+ evel_init_option_string(&fault->alarm_interface_a);
+ dlist_initialize(&fault->additional_info);
+
+exit_label:
+ EVEL_EXIT();
+ return fault;
+}
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the Fault.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param fault Pointer to the fault.
+ * @param name ASCIIZ string with the attribute's name. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ * @param value ASCIIZ string with the attribute's value. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_addl_info_add(EVENT_FAULT * fault, char * name, char * value)
+{
+ FAULT_ADDL_INFO * addl_info = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(fault != NULL);
+ assert(fault->header.event_domain == EVEL_DOMAIN_FAULT);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ addl_info = malloc(sizeof(FAULT_ADDL_INFO));
+ assert(addl_info != NULL);
+ memset(addl_info, 0, sizeof(FAULT_ADDL_INFO));
+ addl_info->name = strdup(name);
+ addl_info->value = strdup(value);
+ assert(addl_info->name != NULL);
+ assert(addl_info->value != NULL);
+
+ dlist_push_last(&fault->additional_info, addl_info);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Alarm Interface A property of the Fault.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param fault Pointer to the fault.
+ * @param interface The Alarm Interface A to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_interface_set(EVENT_FAULT * fault,
+ const char * const interface)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(fault != NULL);
+ assert(fault->header.event_domain == EVEL_DOMAIN_FAULT);
+ assert(interface != NULL);
+
+ evel_set_option_string(&fault->alarm_interface_a,
+ interface,
+ "Alarm Interface A");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Fault.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param fault Pointer to the fault.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_type_set(EVENT_FAULT * fault, const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(fault != NULL);
+ assert(fault->header.event_domain == EVEL_DOMAIN_FAULT);
+ evel_header_type_set(&fault->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the fault in JSON according to AT&T's schema for the fault type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_fault(EVEL_JSON_BUFFER * jbuf,
+ EVENT_FAULT * event)
+{
+ FAULT_ADDL_INFO * addl_info = NULL;
+ DLIST_ITEM * addl_info_item = NULL;
+ char * fault_severity;
+ char * fault_source_type;
+ char * fault_vf_status;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_FAULT);
+
+ fault_severity = evel_severity(event->event_severity);
+ fault_source_type = evel_source_type(event->event_source_type);
+ fault_vf_status = evel_vf_status(event->vf_status);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "faultFields");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "alarmCondition", event->alarm_condition);
+ evel_enc_kv_string(jbuf, "eventSeverity", fault_severity);
+ evel_enc_kv_string(jbuf, "eventSourceType", fault_source_type);
+ evel_enc_kv_string(jbuf, "specificProblem", event->specific_problem);
+ evel_enc_kv_string(jbuf, "vfStatus", fault_vf_status);
+ evel_enc_version(
+ jbuf, "faultFieldsVersion", event->major_version, event->minor_version);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+
+ /***************************************************************************/
+ /* Checkpoint, so that we can wind back if all fields are suppressed. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "alarmAdditionalInformation"))
+ {
+ bool item_added = false;
+
+ addl_info_item = dlist_get_first(&event->additional_info);
+ while (addl_info_item != NULL)
+ {
+ addl_info = (FAULT_ADDL_INFO*) addl_info_item->item;
+ assert(addl_info != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "alarmAdditionalInformation",
+ addl_info->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", addl_info->name);
+ evel_enc_kv_string(jbuf, "value", addl_info->value);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ addl_info_item = dlist_get_next(addl_info_item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+ evel_enc_kv_opt_string(jbuf, "alarmInterfaceA", &event->alarm_interface_a);
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Fault.
+ *
+ * Free off the Fault supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Fault itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_fault(EVENT_FAULT * event)
+{
+ FAULT_ADDL_INFO * addl_info = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_FAULT);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ addl_info = dlist_pop_last(&event->additional_info);
+ while (addl_info != NULL)
+ {
+ EVEL_DEBUG("Freeing Additional Info (%s, %s)",
+ addl_info->name,
+ addl_info->value);
+ free(addl_info->name);
+ free(addl_info->value);
+ free(addl_info);
+ addl_info = dlist_pop_last(&event->additional_info);
+ }
+ free(event->alarm_condition);
+ evel_free_option_string(&event->alarm_interface_a);
+ free(event->specific_problem);
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_internal.h b/vnfs/VES/code/evel_library/evel_internal.h
new file mode 100644
index 00000000..fc887c95
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_internal.h
@@ -0,0 +1,867 @@
+#ifndef EVEL_INTERNAL_INCLUDED
+#define EVEL_INTERNAL_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * EVEL internal definitions.
+ *
+ * These are internal definitions which need to be shared between modules
+ * within the library but are not intended for external consumption.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Define some type-safe min/max macros. */
+/*****************************************************************************/
+#define max(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a > _b ? _a : _b; })
+
+#define min(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+
+/**************************************************************************//**
+ * Compile-time assertion.
+ *****************************************************************************/
+#define EVEL_CT_ASSERT(X) switch (0) {case 0: case (X):;}
+
+/**************************************************************************//**
+ * The Functional Role of the equipment represented by this VNF.
+ *****************************************************************************/
+extern char * functional_role;
+
+/**************************************************************************//**
+ * The type of equipment represented by this VNF.
+ *****************************************************************************/
+extern EVEL_SOURCE_TYPES event_source_type;
+
+/**************************************************************************//**
+ * A chunk of memory used in the cURL functions.
+ *****************************************************************************/
+typedef struct memory_chunk {
+ char * memory;
+ size_t size;
+} MEMORY_CHUNK;
+
+/**************************************************************************//**
+ * Global commands that may be sent to the Event Handler thread.
+ *****************************************************************************/
+typedef enum {
+ EVT_CMD_TERMINATE,
+ EVT_CMD_MAX_COMMANDS
+} EVT_HANDLER_COMMAND;
+
+/**************************************************************************//**
+ * State of the Event Handler thread.
+ *****************************************************************************/
+typedef enum {
+ EVT_HANDLER_UNINITIALIZED, /** The library cannot handle events. */
+ EVT_HANDLER_INACTIVE, /** The event handler thread not started. */
+ EVT_HANDLER_ACTIVE, /** The event handler thread is started. */
+ EVT_HANDLER_REQUEST_TERMINATE, /** Initial stages of shutdown. */
+ EVT_HANDLER_TERMINATING, /** The ring-buffer is being depleted. */
+ EVT_HANDLER_TERMINATED, /** The library is exited. */
+ EVT_HANDLER_MAX_STATES /** Maximum number of valid states. */
+} EVT_HANDLER_STATE;
+
+/**************************************************************************//**
+ * Internal event.
+ * Pseudo-event used for routing internal commands.
+ *****************************************************************************/
+typedef struct event_internal {
+ EVENT_HEADER header;
+ EVT_HANDLER_COMMAND command;
+} EVENT_INTERNAL;
+
+/**************************************************************************//**
+ * Suppressed NV pairs list entry.
+ * JSON equivalent field: suppressedNvPairs
+ *****************************************************************************/
+typedef struct evel_suppressed_nv_pairs {
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /* JSON equivalent field: nvPairFieldName */
+ /***************************************************************************/
+ char * nv_pair_field_name;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /* JSON equivalent field: suppressedNvPairNames */
+ /* Type of each list entry: char * */
+ /***************************************************************************/
+ DLIST suppressed_nv_pair_names;
+
+ /***************************************************************************/
+ /* Hash table containing suppressed_nv_pair_names as keys. */
+ /***************************************************************************/
+ struct hsearch_data * hash_nv_pair_names;
+
+} EVEL_SUPPRESSED_NV_PAIRS;
+
+/**************************************************************************//**
+ * Event Throttling Specification for a domain which is in a throttled state.
+ * JSON equivalent object: eventThrottlingState
+ *****************************************************************************/
+typedef struct evel_throttle_spec {
+
+ /***************************************************************************/
+ /* List of field names to be suppressed. */
+ /* JSON equivalent field: suppressedFieldNames */
+ /* Type of each list entry: char * */
+ /***************************************************************************/
+ DLIST suppressed_field_names;
+
+ /***************************************************************************/
+ /* List of name-value pairs to be suppressed. */
+ /* JSON equivalent field: suppressedNvPairsList */
+ /* Type of each list entry: EVEL_SUPPRESSED_NV_PAIRS * */
+ /***************************************************************************/
+ DLIST suppressed_nv_pairs_list;
+
+ /***************************************************************************/
+ /* Hash table containing suppressed_nv_pair_names as keys. */
+ /***************************************************************************/
+ struct hsearch_data * hash_field_names;
+
+ /***************************************************************************/
+ /* Hash table containing nv_pair_field_name as keys, and */
+ /* suppressed_nv_pairs_list as values. */
+ /***************************************************************************/
+ struct hsearch_data * hash_nv_pairs_list;
+
+} EVEL_THROTTLE_SPEC;
+
+/*****************************************************************************/
+/* RFC2822 format string for strftime. */
+/*****************************************************************************/
+#define EVEL_RFC2822_STRFTIME_FORMAT "%a, %d %b %Y %T %z"
+
+/*****************************************************************************/
+/* EVEL_JSON_BUFFER depth at which we throttle fields. */
+/*****************************************************************************/
+#define EVEL_THROTTLE_FIELD_DEPTH 3
+
+/**************************************************************************//**
+ * Initialize the event handler.
+ *
+ * Primarily responsible for getting cURL ready for use.
+ *
+ * @param[in] event_api_url
+ * The URL where the Vendor Event Listener API is expected
+ * to be.
+ * @param[in] throt_api_url
+ * The URL where the Throttling API is expected to be.
+ * @param[in] username The username for the Basic Authentication of requests.
+ * @param[in] password The password for the Basic Authentication of requests.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url,
+ const char * const throt_api_url,
+ const char * const username,
+ const char * const password,
+ int verbosity);
+
+/**************************************************************************//**
+ * Terminate the event handler.
+ *
+ * Shuts down the event handler thread in as clean a way as possible. Sets the
+ * global exit flag and then signals the thread to interrupt it since it's
+ * most likely waiting on the ring-buffer.
+ *
+ * Having achieved an orderly shutdown of the event handler thread, clean up
+ * the cURL library's resources cleanly.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_terminate();
+
+/**************************************************************************//**
+ * Run the event handler.
+ *
+ * Spawns the thread responsible for handling events and sending them to the
+ * API.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_run();
+
+/**************************************************************************//**
+ * Create a new internal event.
+ *
+ * @note The mandatory fields on the Fault must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Fault has immutable properties.
+ * @param command The condition indicated by the event.
+ * @returns pointer to the newly manufactured ::EVENT_INTERNAL. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_INTERNAL * evel_new_internal_event(EVT_HANDLER_COMMAND command);
+
+/**************************************************************************//**
+ * Free an internal event.
+ *
+ * Free off the event supplied. Will free all the contained* allocated memory.
+ *
+ * @note It does not free the internal event itself, since that may be part of
+ * a larger structure.
+ *****************************************************************************/
+void evel_free_internal_event(EVENT_INTERNAL * event);
+
+/**************************************************************************//**
+ * Initialize an event instance id, typically embedded in an event.
+ *
+ * @param instance_id Pointer to the event instance id being initialized.
+ * @param vendor_id The vendor id to encode in the event instance id.
+ * @param event_id The event id to encode in the event instance id.
+ *****************************************************************************/
+void evel_init_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id,
+ const char * const vendor_id,
+ const char * const event_id);
+
+/**************************************************************************//**
+ * Free an event instance id.
+ *
+ * @param instance_id Pointer to the event instance id being initialized.
+ *****************************************************************************/
+void evel_free_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id);
+
+/*****************************************************************************/
+/* Structure to hold JSON buffer and associated tracking, as it is written. */
+/*****************************************************************************/
+typedef struct evel_json_buffer
+{
+ char * json;
+ int offset;
+ int max_size;
+
+ /***************************************************************************/
+ /* The working throttle specification, which can be NULL. */
+ /***************************************************************************/
+ EVEL_THROTTLE_SPEC * throttle_spec;
+
+ /***************************************************************************/
+ /* Current object/list nesting depth. */
+ /***************************************************************************/
+ int depth;
+
+ /***************************************************************************/
+ /* The checkpoint. */
+ /***************************************************************************/
+ int checkpoint;
+
+} EVEL_JSON_BUFFER;
+
+/**************************************************************************//**
+ * Encode the event as a JSON event object according to AT&T's schema.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf,
+ EVENT_HEADER * event);
+
+/**************************************************************************//**
+ * Encode the instance id as a JSON object according to AT&T's schema.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param instance_id Pointer to the ::EVEL_EVENT_INSTANCE_ID to encode.
+ *****************************************************************************/
+void evel_json_encode_instance_id(EVEL_JSON_BUFFER * jbuf,
+ EVEL_EVENT_INSTANCE_ID * instance_id);
+
+/**************************************************************************//**
+ * Encode the fault in JSON according to AT&T's schema for the fault type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_fault(EVEL_JSON_BUFFER * jbuf,
+ EVENT_FAULT * event);
+
+/**************************************************************************//**
+ * Encode the measurement as a JSON measurement.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_measurement(EVEL_JSON_BUFFER * jbuf,
+ EVENT_MEASUREMENT * event);
+
+/**************************************************************************//**
+ * Encode the Mobile Flow in JSON according to AT&T's schema for the event
+ * type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_mobile_flow(EVEL_JSON_BUFFER * jbuf,
+ EVENT_MOBILE_FLOW * event);
+
+/**************************************************************************//**
+ * Encode the report as a JSON report.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_report(EVEL_JSON_BUFFER * jbuf,
+ EVENT_REPORT * event);
+
+/**************************************************************************//**
+ * Encode the Service Event in JSON according to AT&T's schema for the event
+ * type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_service(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_SERVICE * const event);
+
+/**************************************************************************//**
+ * Encode the Signaling in JSON according to AT&T's schema for the event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_signaling(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_SIGNALING * const event);
+
+/**************************************************************************//**
+ * Encode the state change as a JSON state change.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE to encode.
+ *****************************************************************************/
+void evel_json_encode_state_change(EVEL_JSON_BUFFER * jbuf,
+ EVENT_STATE_CHANGE * state_change);
+
+/**************************************************************************//**
+ * Encode the Syslog in JSON according to AT&T's schema for the event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_syslog(EVEL_JSON_BUFFER * jbuf,
+ EVENT_SYSLOG * event);
+
+/**************************************************************************//**
+ * Encode the Other in JSON according to AT&T's schema for the event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf,
+ EVENT_OTHER * event);
+
+/**************************************************************************//**
+ * Set the next event_sequence to use.
+ *
+ * @param sequence The next sequence number to use.
+ *****************************************************************************/
+void evel_set_next_event_sequence(const int sequence);
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, contained in a ::MEMORY_CHUNK.
+ *
+ * Tokenize the response, and decode any tokens found.
+ *
+ * @param chunk The memory chunk containing the response.
+ * @param post The memory chunk in which to place any resulting POST.
+ *****************************************************************************/
+void evel_handle_event_response(const MEMORY_CHUNK * const chunk,
+ MEMORY_CHUNK * const post);
+
+/**************************************************************************//**
+ * Initialize a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise.
+ * @param json Pointer to the underlying working buffer to use.
+ * @param max_size Size of storage available in the JSON buffer.
+ * @param throttle_spec Pointer to throttle specification. Can be NULL.
+ *****************************************************************************/
+void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
+ char * const json,
+ const int max_size,
+ EVEL_THROTTLE_SPEC * throttle_spec);
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_STRING * const option);
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value Pointer to the corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const char * const value);
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_INT * const option);
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int value);
+
+/**************************************************************************//**
+ * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_double(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_DOUBLE * const option);
+
+/**************************************************************************//**
+ * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const double value);
+
+/**************************************************************************//**
+ * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_ull(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_ULL * const option);
+
+/**************************************************************************//**
+ * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const unsigned long long value);
+
+/**************************************************************************//**
+ * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_time(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_TIME * const option);
+
+/**************************************************************************//**
+ * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param time Pointer to the time to encode.
+ *****************************************************************************/
+void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const time_t * time);
+
+/**************************************************************************//**
+ * Encode a key and version.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param major_version The major version to encode.
+ * @param minor_version The minor version to encode.
+ *****************************************************************************/
+void evel_enc_version(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int major_version,
+ const int minor_version);
+
+/**************************************************************************//**
+ * Add the key and opening bracket of an optional named list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @return true if the list was opened, false if it was suppressed.
+ *****************************************************************************/
+bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf,
+ const char * const key);
+
+/**************************************************************************//**
+ * Add the key and opening bracket of a named list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ *****************************************************************************/
+void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
+ const char * const key);
+
+/**************************************************************************//**
+ * Add the closing bracket of a list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_list(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param ... Variable parameters for format string.
+ *****************************************************************************/
+void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
+ const char * const format,
+ ...);
+
+/**************************************************************************//**
+ * Add the opening bracket of an optional named object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ *****************************************************************************/
+bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key);
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @return true if the object was opened, false if it was suppressed.
+ *****************************************************************************/
+void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key);
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_open_object(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Add the closing bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_object(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Add a checkpoint - a stake in the ground to which we can rewind.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Rewind to the latest checkoint.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_rewind(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Free the underlying resources of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ *****************************************************************************/
+void evel_free_option_string(EVEL_OPTION_STRING * const option);
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_STRING to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ *****************************************************************************/
+void evel_init_option_string(EVEL_OPTION_STRING * const option);
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_string(EVEL_OPTION_STRING * const option,
+ const char * const value,
+ const char * const description);
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_string(EVEL_OPTION_STRING * const option,
+ const char * const value);
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_INT to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ *****************************************************************************/
+void evel_init_option_int(EVEL_OPTION_INT * const option);
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_INT.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_int(EVEL_OPTION_INT * const option,
+ const int value);
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_INT.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_int(EVEL_OPTION_INT * const option,
+ const int value,
+ const char * const description);
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_DOUBLE to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ *****************************************************************************/
+void evel_init_option_double(EVEL_OPTION_DOUBLE * const option);
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_DOUBLE.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_double(EVEL_OPTION_DOUBLE * const option,
+ const double value);
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_DOUBLE.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_double(EVEL_OPTION_DOUBLE * const option,
+ const double value,
+ const char * const description);
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_ULL to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ *****************************************************************************/
+void evel_init_option_ull(EVEL_OPTION_ULL * const option);
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_ULL.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_ull(EVEL_OPTION_ULL * const option,
+ const unsigned long long value);
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_ULL.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_ull(EVEL_OPTION_ULL * const option,
+ const unsigned long long value,
+ const char * const description);
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_TIME to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_TIME.
+ *****************************************************************************/
+void evel_init_option_time(EVEL_OPTION_TIME * const option);
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_TIME.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_TIME.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_time(EVEL_OPTION_TIME * const option,
+ const time_t value);
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_TIME.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_TIME.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_time(EVEL_OPTION_TIME * const option,
+ const time_t value,
+ const char * const description);
+
+/**************************************************************************//**
+ * Map an ::EVEL_COUNTER_CRITICALITIES enum value to the equivalent string.
+ *
+ * @param criticality The criticality to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_criticality(const EVEL_COUNTER_CRITICALITIES criticality);
+
+/**************************************************************************//**
+ * Map an ::EVEL_SEVERITIES enum value to the equivalent string.
+ *
+ * @param severity The severity to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_severity(const EVEL_SEVERITIES severity);
+
+/**************************************************************************//**
+ * Map an ::EVEL_ALERT_ACTIONS enum value to the equivalent string.
+ *
+ * @param alert_action The alert_action to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_alert_action(const EVEL_ALERT_ACTIONS alert_action);
+
+/**************************************************************************//**
+ * Map an ::EVEL_ALERT_TYPES enum value to the equivalent string.
+ *
+ * @param alert_type The alert_type to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_alert_type(const EVEL_ALERT_TYPES alert_type);
+
+/**************************************************************************//**
+ * Map an ::EVEL_EVENT_DOMAINS enum value to the equivalent string.
+ *
+ * @param domain The domain to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_event_domain(const EVEL_EVENT_DOMAINS domain);
+
+/**************************************************************************//**
+ * Map an ::EVEL_EVENT_PRIORITIES enum value to the equivalent string.
+ *
+ * @param priority The priority to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_event_priority(const EVEL_EVENT_PRIORITIES priority);
+
+/**************************************************************************//**
+ * Map an ::EVEL_SOURCE_TYPES enum value to the equivalent string.
+ *
+ * @param source_type The source type to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_source_type(const EVEL_SOURCE_TYPES source_type);
+
+/**************************************************************************//**
+ * Map an ::EVEL_VF_STATUSES enum value to the equivalent string.
+ *
+ * @param vf_status The vf_status to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_vf_status(const EVEL_VF_STATUSES vf_status);
+
+/**************************************************************************//**
+ * Convert a ::EVEL_ENTITY_STATE to it's string form for JSON encoding.
+ *
+ * @param state The entity state to encode.
+ *
+ * @returns the corresponding string
+ *****************************************************************************/
+char * evel_entity_state(const EVEL_ENTITY_STATE state);
+
+/**************************************************************************//**
+ * Convert a ::EVEL_SERVICE_ENDPOINT_DESC to string form for JSON encoding.
+ *
+ * @param endpoint_desc endpoint description to encode.
+ *
+ * @returns the corresponding string
+ *****************************************************************************/
+char * evel_service_endpoint_desc(const EVEL_ENTITY_STATE endpoint_desc);
+
+#endif
diff --git a/vnfs/VES/code/evel_library/evel_internal_event.c b/vnfs/VES/code/evel_library/evel_internal_event.c
new file mode 100644
index 00000000..03a3d14d
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_internal_event.c
@@ -0,0 +1,124 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the internal events.
+ *
+ * Internal events are never expected to be sent to the JSON API but comply
+ * with interfaces for regular event types. The primary use-case is to enable
+ * the foreground processing to communicate with the background event handling
+ * processing in an orderly fashion. At present the only use is to initiate an
+ * orderly shutdown of the Event Handler thread.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+
+/**************************************************************************//**
+ * Create a new internal event.
+ *
+ * @note The mandatory fields on the Fault must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Fault has immutable properties.
+ * @param command The condition indicated by the event.
+ * @returns pointer to the newly manufactured ::EVENT_INTERNAL. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_INTERNAL * evel_new_internal_event(EVT_HANDLER_COMMAND command)
+{
+ EVENT_INTERNAL * event = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(command < EVT_CMD_MAX_COMMANDS);
+
+ /***************************************************************************/
+ /* Allocate the fault. */
+ /***************************************************************************/
+ event = malloc(sizeof(EVENT_INTERNAL));
+ if (event == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(event, 0, sizeof(EVENT_INTERNAL));
+ EVEL_DEBUG("New internal event is at %lp", event);
+
+ /***************************************************************************/
+ /* Initialize the header & the event fields. */
+ /***************************************************************************/
+ evel_init_header(&event->header);
+ event->header.event_domain = EVEL_DOMAIN_INTERNAL;
+ event->command = command;
+
+exit_label:
+ EVEL_EXIT();
+ return event;
+}
+
+/**************************************************************************//**
+ * Free an internal event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the internal event itself, since that may be part of
+ * a larger structure.
+ *****************************************************************************/
+void evel_free_internal_event(EVENT_INTERNAL * event)
+{
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_INTERNAL);
+
+ /***************************************************************************/
+ /* Free the header itself. */
+ /***************************************************************************/
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+} \ No newline at end of file
diff --git a/vnfs/VES/code/evel_library/evel_json_buffer.c b/vnfs/VES/code/evel_library/evel_json_buffer.c
new file mode 100644
index 00000000..7ae3453b
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_json_buffer.c
@@ -0,0 +1,853 @@
+/**************************************************************************//**
+ * @file
+ * Source module relating to internal EVEL_JSON_BUFFER manipulation functions.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "evel_throttle.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Initialize a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise.
+ * @param json Pointer to the underlying working buffer to use.
+ * @param max_size Size of storage available in the JSON buffer.
+ * @param throttle_spec Pointer to throttle specification. Can be NULL.
+ *****************************************************************************/
+void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
+ char * const json,
+ const int max_size,
+ EVEL_THROTTLE_SPEC * throttle_spec)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+ assert(json != NULL);
+ jbuf->json = json;
+ jbuf->max_size = max_size;
+ jbuf->offset = 0;
+ jbuf->throttle_spec = throttle_spec;
+ jbuf->depth = 0;
+ jbuf->checkpoint = -1;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode an integer value to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param value The integer to add to it.
+ *****************************************************************************/
+void evel_enc_int(EVEL_JSON_BUFFER * jbuf,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%d", value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_STRING * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %s", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %s", key, option->value);
+ evel_enc_kv_string(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value Pointer to the corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const char * const value)
+{
+ int index;
+ int length;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
+
+ /***************************************************************************/
+ /* We need to escape quotation marks and backslashes in the value. */
+ /***************************************************************************/
+ length = strlen(value);
+
+ for (index = 0; index < length; index++)
+ {
+ /*************************************************************************/
+ /* Drop out if no more space. */
+ /*************************************************************************/
+ if (jbuf->max_size - jbuf->offset < 2)
+ {
+ break;
+ }
+
+ /*************************************************************************/
+ /* Add an escape character if necessary, then write the character */
+ /* itself. */
+ /*************************************************************************/
+ if ((value[index] == '\"') || (value[index] == '\\'))
+ {
+ jbuf->json[jbuf->offset] = '\\';
+ jbuf->offset++;
+ }
+
+ jbuf->json[jbuf->offset] = value[index];
+ jbuf->offset++;
+ }
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "\"");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_INT * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %d", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %d", key, option->value);
+ evel_enc_kv_int(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %d",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_double(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_DOUBLE * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %1f", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %1f", key, option->value);
+ evel_enc_kv_double(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const double value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %1f",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_ull(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_ULL * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %1lu", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %1lu", key, option->value);
+ evel_enc_kv_ull(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const unsigned long long value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %llu",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_time(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_TIME * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed time: %s", key);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded time: %s", key);
+ evel_enc_kv_time(jbuf, key, &option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param time Pointer to the time to encode.
+ *****************************************************************************/
+void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const time_t * time)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+ assert(time != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
+ jbuf->offset += strftime(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ EVEL_RFC2822_STRFTIME_FORMAT,
+ localtime(time));
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "\"");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a key and version.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param major_version The major version to encode.
+ * @param minor_version The minor version to encode.
+ *****************************************************************************/
+void evel_enc_version(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int major_version,
+ const int minor_version)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ evel_enc_kv_int(jbuf, key, major_version);
+ if (minor_version != 0)
+ {
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ ".%d",
+ minor_version);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the key and opening bracket of an optional named list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @return true if the list was opened, false if it was suppressed.
+ *****************************************************************************/
+bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ bool opened = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s", key);
+ opened = false;
+ }
+ else
+ {
+ evel_json_open_named_list(jbuf, key);
+ opened = true;
+ }
+
+ EVEL_EXIT();
+
+ return opened;
+}
+
+/**************************************************************************//**
+ * Add the key and opening bracket of a named list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ *****************************************************************************/
+void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": [",
+ evel_json_kv_comma(jbuf),
+ key);
+ jbuf->depth++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the closing bracket of a list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "]");
+ jbuf->depth--;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param ... Variable parameters for format string.
+ *****************************************************************************/
+void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
+ const char * const format,
+ ...)
+{
+ va_list largs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(format != NULL);
+
+ /***************************************************************************/
+ /* Add a comma unless we're at the start of the list. */
+ /***************************************************************************/
+ if (jbuf->json[jbuf->offset - 1] != '[')
+ {
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ ", ");
+ }
+
+ va_start(largs, format);
+ jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ format,
+ largs);
+ va_end(largs);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an optional named object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ *****************************************************************************/
+bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ bool opened = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s", key);
+ opened = false;
+ }
+ else
+ {
+ evel_json_open_named_object(jbuf, key);
+ opened = true;
+ }
+
+ EVEL_EXIT();
+
+ return opened;
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @return true if the object was opened, false if it was suppressed.
+ *****************************************************************************/
+void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": {",
+ evel_json_kv_comma(jbuf),
+ key);
+ jbuf->depth++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
+{
+ char * comma;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}'))
+ {
+ comma = ", ";
+ }
+ else
+ {
+ comma = "";
+ }
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s{",
+ comma);
+ jbuf->depth++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the closing bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "}");
+ jbuf->depth--;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Determine whether to add a comma when adding a key-value pair.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @returns A string containing the comma if it is required.
+ *****************************************************************************/
+char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ if ((jbuf->offset == 0) ||
+ (jbuf->json[jbuf->offset-1] == '{') ||
+ (jbuf->json[jbuf->offset-1] == '['))
+ {
+ result = "";
+ }
+ else
+ {
+ result = ", ";
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Add a checkpoint - a stake in the ground to which we can rewind.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ /***************************************************************************/
+ /* Store the current offset. */
+ /***************************************************************************/
+ jbuf->checkpoint = jbuf->offset;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Rewind to the latest checkoint.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_rewind(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(jbuf->checkpoint >= 0);
+ assert(jbuf->checkpoint <= jbuf->offset);
+
+ /***************************************************************************/
+ /* Reinstate the offset from the last checkpoint. */
+ /***************************************************************************/
+ jbuf->offset = jbuf->checkpoint;
+ jbuf->checkpoint = -1;
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_logging.c b/vnfs/VES/code/evel_library/evel_logging.c
new file mode 100644
index 00000000..6dabc638
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_logging.c
@@ -0,0 +1,181 @@
+/**************************************************************************//**
+ * @file
+ * Wrapper for event logging built on syslog.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <curl/curl.h>
+
+#include "evel.h"
+
+
+/*****************************************************************************/
+/* Debug settings. Logging is done through macros so these need to be */
+/* externally visible. */
+/*****************************************************************************/
+EVEL_LOG_LEVELS debug_level = EVEL_LOG_DEBUG;
+//static char *syslog_ident = "evel";
+int debug_indent = 0;
+
+/*****************************************************************************/
+/* Buffers for error strings from this library. */
+/*****************************************************************************/
+static char evel_err_string[EVEL_MAX_ERROR_STRING_LEN] = "<NULL>";
+
+
+/**************************************************************************//**
+ * Initialize logging
+ *
+ * @param[in] level The debugging level - one of ::EVEL_LOG_LEVELS.
+ * @param[in] ident The identifier for our logs.
+ *****************************************************************************/
+void log_initialize(EVEL_LOG_LEVELS level, const char * ident)
+{
+ assert(level < EVEL_LOG_MAX);
+ assert(ident != NULL);
+
+ debug_level = level;
+ openlog(ident, LOG_PID, LOG_USER);
+}
+
+/**************************************************************************//**
+ * Descriptive text for library errors.
+ *
+ * Return a text error string that relates to the last failure. May be
+ * "<null>" but will never be NULL.
+ *
+ * @returns Text error string.
+ *
+ * @note Must not be freed!
+ *****************************************************************************/
+const char * evel_error_string(void)
+{
+ return(evel_err_string);
+}
+
+/***************************************************************************//*
+ * Store the formatted string into the static error string and log the error.
+ *
+ * @param format Error string in standard printf format.
+ * @param ... Variable parameters to be substituted into the format string.
+ *****************************************************************************/
+void log_error_state(char * format, ...)
+{
+ va_list largs;
+
+ assert(format != NULL);
+ va_start(largs, format);
+ vsnprintf(evel_err_string, EVEL_MAX_ERROR_STRING_LEN, format, largs);
+ va_end(largs);
+ EVEL_ERROR("%s", evel_err_string);
+}
+
+
+/**************************************************************************//**
+ * Generate a debug log.
+ *
+ * Provides an interface to syslog with formatting of the nesting level
+ * so that it's easier to see function entry/exit.
+ *
+ * @param[in] level The debug level - see ::EVEL_LOG_LEVELS.
+ * @param[in] format The output formatting in printf style.
+ * @param[in] ... Variable arguments as specified in the format string.
+ *****************************************************************************/
+void log_debug(EVEL_LOG_LEVELS level, char * format, ...)
+{
+ va_list largs;
+ int priority;
+ char indent_fmt[1024];
+ char *syslog_fmt = NULL;
+
+ /***************************************************************************/
+ /* Test assumptions. */
+ /***************************************************************************/
+ assert(format != NULL);
+ assert(level <= EVEL_LOG_MAX);
+
+ if (level >= debug_level)
+ {
+ if ((debug_level == EVEL_LOG_INFO) || (debug_indent == 0))
+ {
+ /***********************************************************************/
+ /* Just use the format as is. */
+ /***********************************************************************/
+ syslog_fmt = format;
+ }
+ else
+ {
+ /***********************************************************************/
+ /* Combine the format with a preceding number of indent markers. */
+ /***********************************************************************/
+ sprintf(indent_fmt, "%.*s%s",
+ debug_indent,
+ INDENT_SEPARATORS,
+ format);
+ syslog_fmt = indent_fmt;
+ }
+
+ /*************************************************************************/
+ /* Work out the syslog priority value. */
+ /*************************************************************************/
+ switch (level)
+ {
+ case EVEL_LOG_ERROR:
+ priority = LOG_ERR;
+ break;
+
+ case EVEL_LOG_INFO:
+ priority = LOG_INFO;
+ break;
+
+ case EVEL_LOG_DEBUG:
+ case EVEL_LOG_SPAMMY:
+ default:
+ priority = LOG_DEBUG;
+ break;
+ }
+
+ /*************************************************************************/
+ /* Write the log to the file next, which requires the var args list. */
+ /*************************************************************************/
+ va_start(largs, format);
+ vsyslog(priority, syslog_fmt, largs);
+ va_end(largs);
+ }
+} \ No newline at end of file
diff --git a/vnfs/VES/code/evel_library/evel_mobile_flow.c b/vnfs/VES/code/evel_library/evel_mobile_flow.c
new file mode 100644
index 00000000..45f22ea7
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_mobile_flow.c
@@ -0,0 +1,2036 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Mobile Flow.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+/*****************************************************************************/
+/* Array of strings to use when encoding TCP flags. */
+/*****************************************************************************/
+static char * evel_tcp_flag_strings[EVEL_MAX_TCP_FLAGS] = {
+ "NS",
+ "CWR",
+ "ECE",
+ "URG",
+ "ACK",
+ "PSH",
+ "RST",
+ "SYN",
+ "FIN"
+};
+
+/*****************************************************************************/
+/* Array of strings to use when encoding QCI COS. */
+/*****************************************************************************/
+static char * evel_qci_cos_strings[EVEL_MAX_QCI_COS_TYPES] = {
+ "conversational",
+ "streaming",
+ "interactive",
+ "background",
+ "1",
+ "2",
+ "3",
+ "4",
+ "65",
+ "66",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "69",
+ "70"
+};
+
+/*****************************************************************************/
+/* Local prototypes */
+/*****************************************************************************/
+void evel_json_encode_mobile_flow_gtp_flow_metrics(
+ EVEL_JSON_BUFFER * jbuf,
+ MOBILE_GTP_PER_FLOW_METRICS * metrics);
+
+/**************************************************************************//**
+ * Create a new Mobile Flow event.
+ *
+ * @note The mandatory fields on the Mobile Flow must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Mobile Flow has immutable properties.
+ * @param flow_direction Flow direction.
+ * @param gtp_per_flow_metrics GTP per-flow metrics.
+ * @param ip_protocol_type IP protocol type.
+ * @param ip_version IP protocol version.
+ * @param other_endpoint_ip_address IP address of the other endpoint.
+ * @param other_endpoint_port IP port of the other endpoint.
+ * @param reporting_endpoint_ip_addr IP address of the reporting endpoint.
+ * @param reporting_endpoint_port IP port of the reporting endpoint.
+ * @returns pointer to the newly manufactured ::EVENT_MOBILE_FLOW. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_mobile_flow.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MOBILE_FLOW * evel_new_mobile_flow(
+ const char * const flow_direction,
+ MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics,
+ const char * const ip_protocol_type,
+ const char * const ip_version,
+ const char * const other_endpoint_ip_address,
+ int other_endpoint_port,
+ const char * const reporting_endpoint_ip_addr,
+ int reporting_endpoint_port)
+{
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(flow_direction != NULL);
+ assert(gtp_per_flow_metrics != NULL);
+ assert(ip_protocol_type != NULL);
+ assert(ip_version != NULL);
+ assert(other_endpoint_ip_address != NULL);
+ assert(other_endpoint_port > 0);
+ assert(reporting_endpoint_ip_addr != NULL);
+ assert(reporting_endpoint_port > 0);
+
+ /***************************************************************************/
+ /* Allocate the Mobile Flow. */
+ /***************************************************************************/
+ mobile_flow = malloc(sizeof(EVENT_MOBILE_FLOW));
+ if (mobile_flow == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(mobile_flow, 0, sizeof(EVENT_MOBILE_FLOW));
+ EVEL_DEBUG("New Mobile Flow is at %lp", mobile_flow);
+
+ /***************************************************************************/
+ /* Initialize the header & the Mobile Flow fields. Optional string values */
+ /* are uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&mobile_flow->header);
+ mobile_flow->header.event_domain = EVEL_DOMAIN_MOBILE_FLOW;
+ mobile_flow->major_version = EVEL_MOBILE_FLOW_MAJOR_VERSION;
+ mobile_flow->minor_version = EVEL_MOBILE_FLOW_MINOR_VERSION;
+ mobile_flow->flow_direction = strdup(flow_direction);
+ mobile_flow->gtp_per_flow_metrics = gtp_per_flow_metrics;
+ mobile_flow->ip_protocol_type = strdup(ip_protocol_type);
+ mobile_flow->ip_version = strdup(ip_version);
+ mobile_flow->other_endpoint_ip_address = strdup(other_endpoint_ip_address);
+ mobile_flow->other_endpoint_port = other_endpoint_port;
+ mobile_flow->reporting_endpoint_ip_addr = strdup(reporting_endpoint_ip_addr);
+ mobile_flow->reporting_endpoint_port = reporting_endpoint_port;
+ evel_init_option_string(&mobile_flow->application_type);
+ evel_init_option_string(&mobile_flow->app_protocol_type);
+ evel_init_option_string(&mobile_flow->app_protocol_version);
+ evel_init_option_string(&mobile_flow->cid);
+ evel_init_option_string(&mobile_flow->connection_type);
+ evel_init_option_string(&mobile_flow->ecgi);
+ evel_init_option_string(&mobile_flow->gtp_protocol_type);
+ evel_init_option_string(&mobile_flow->gtp_version);
+ evel_init_option_string(&mobile_flow->http_header);
+ evel_init_option_string(&mobile_flow->imei);
+ evel_init_option_string(&mobile_flow->imsi);
+ evel_init_option_string(&mobile_flow->lac);
+ evel_init_option_string(&mobile_flow->mcc);
+ evel_init_option_string(&mobile_flow->mnc);
+ evel_init_option_string(&mobile_flow->msisdn);
+ evel_init_option_string(&mobile_flow->other_functional_role);
+ evel_init_option_string(&mobile_flow->rac);
+ evel_init_option_string(&mobile_flow->radio_access_technology);
+ evel_init_option_string(&mobile_flow->sac);
+ evel_init_option_int(&mobile_flow->sampling_algorithm);
+ evel_init_option_string(&mobile_flow->tac);
+ evel_init_option_string(&mobile_flow->tunnel_id);
+ evel_init_option_string(&mobile_flow->vlan_id);
+
+exit_label:
+ EVEL_EXIT();
+ return mobile_flow;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ evel_header_type_set(&mobile_flow->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Application Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Application Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(type != NULL);
+
+ evel_set_option_string(&mobile_flow->application_type,
+ type,
+ "Application Type");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Application Protocol Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Application Protocol Type to be set. ASCIIZ string.
+ * The caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(type != NULL);
+
+ evel_set_option_string(&mobile_flow->app_protocol_type,
+ type,
+ "Application Protocol Type");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Application Protocol Version property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param version The Application Protocol Version to be set. ASCIIZ
+ * string. The caller does not need to preserve the value
+ * once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const version)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(version != NULL);
+
+ evel_set_option_string(&mobile_flow->app_protocol_version,
+ version,
+ "Application Protocol Version");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the CID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param cid The CID to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_cid_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const cid)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(cid != NULL);
+
+ evel_set_option_string(&mobile_flow->cid,
+ cid,
+ "CID");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Connection Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Connection Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_con_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(type != NULL);
+
+ evel_set_option_string(&mobile_flow->connection_type,
+ type,
+ "Connection Type");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the ECGI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param ecgi The ECGI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_ecgi_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const ecgi)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(ecgi != NULL);
+
+ evel_set_option_string(&mobile_flow->ecgi,
+ ecgi,
+ "ECGI");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the GTP Protocol Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The GTP Protocol Type to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_gtp_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(type != NULL);
+
+ evel_set_option_string(&mobile_flow->gtp_protocol_type,
+ type,
+ "GTP Protocol Type");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the GTP Protocol Version property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param version The GTP Protocol Version to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_gtp_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const version)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(version != NULL);
+
+ evel_set_option_string(&mobile_flow->gtp_version,
+ version,
+ "GTP Protocol Version");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the HTTP Header property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param header The HTTP header to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_http_header_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const header)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(header != NULL);
+
+ evel_set_option_string(&mobile_flow->http_header,
+ header,
+ "HTTP Header");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the IMEI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param imei The IMEI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_imei_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const imei)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(imei != NULL);
+
+ evel_set_option_string(&mobile_flow->imei,
+ imei,
+ "IMEI");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the IMSI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param imsi The IMSI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_imsi_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const imsi)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(imsi != NULL);
+
+ evel_set_option_string(&mobile_flow->imsi,
+ imsi,
+ "IMSI");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the LAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param lac The LAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_lac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const lac)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(lac != NULL);
+
+ evel_set_option_string(&mobile_flow->lac,
+ lac,
+ "LAC");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the MCC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param mcc The MCC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_mcc_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const mcc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(mcc != NULL);
+
+ evel_set_option_string(&mobile_flow->mcc,
+ mcc,
+ "MCC");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the MNC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param mnc The MNC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_mnc_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const mnc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(mnc != NULL);
+
+ evel_set_option_string(&mobile_flow->mnc,
+ mnc,
+ "MNC");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the MSISDN property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param msisdn The MSISDN to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_msisdn_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const msisdn)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(msisdn != NULL);
+
+ evel_set_option_string(&mobile_flow->msisdn,
+ msisdn,
+ "MSISDN");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Other Functional Role property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param role The Other Functional Role to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_other_func_role_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const role)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(role != NULL);
+
+ evel_set_option_string(&mobile_flow->other_functional_role,
+ role,
+ "Other Functional Role");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the RAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param rac The RAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_rac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const rac)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(rac != NULL);
+
+ evel_set_option_string(&mobile_flow->rac,
+ rac,
+ "RAC");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Radio Access Technology property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tech The Radio Access Technology to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_radio_acc_tech_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tech)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(tech != NULL);
+
+ evel_set_option_string(&mobile_flow->radio_access_technology,
+ tech,
+ "Radio Access Technology");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the SAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param sac The SAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_sac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const sac)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(sac != NULL);
+
+ evel_set_option_string(&mobile_flow->sac,
+ sac,
+ "SAC");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Sampling Algorithm property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param algorithm The Sampling Algorithm to be set.
+ *****************************************************************************/
+void evel_mobile_flow_samp_alg_set(EVENT_MOBILE_FLOW * mobile_flow,
+ int algorithm)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(algorithm >= 0);
+
+ evel_set_option_int(&mobile_flow->sampling_algorithm,
+ algorithm,
+ "Sampling Algorithm");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the TAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tac The TAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_tac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tac)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(tac != NULL);
+
+ evel_set_option_string(&mobile_flow->tac,
+ tac,
+ "TAC");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Tunnel ID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tunnel_id The Tunnel ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_tunnel_id_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tunnel_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(tunnel_id != NULL);
+
+ evel_set_option_string(&mobile_flow->tunnel_id,
+ tunnel_id,
+ "Tunnel ID");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the VLAN ID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param vlan_id The VLAN ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_vlan_id_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const vlan_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(mobile_flow != NULL);
+ assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ assert(vlan_id != NULL);
+
+ evel_set_option_string(&mobile_flow->vlan_id,
+ vlan_id,
+ "VLAN ID");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Mobile Flow in JSON according to AT&T's schema for the event
+ * type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_mobile_flow(EVEL_JSON_BUFFER * jbuf,
+ EVENT_MOBILE_FLOW * event)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "mobileFlowFields");
+
+ /***************************************************************************/
+ /* Mandatory parameters. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "flowDirection", event->flow_direction);
+ evel_json_encode_mobile_flow_gtp_flow_metrics(
+ jbuf, event->gtp_per_flow_metrics);
+ evel_enc_kv_string(jbuf, "ipProtocolType", event->ip_protocol_type);
+ evel_enc_kv_string(jbuf, "ipVersion", event->ip_version);
+ evel_enc_kv_string(
+ jbuf, "otherEndpointIpAddress", event->other_endpoint_ip_address);
+ evel_enc_kv_int(jbuf, "otherEndpointPort", event->other_endpoint_port);
+ evel_enc_kv_string(
+ jbuf, "reportingEndpointIpAddr", event->reporting_endpoint_ip_addr);
+ evel_enc_kv_int(
+ jbuf, "reportingEndpointPort", event->reporting_endpoint_port);
+
+ /***************************************************************************/
+ /* Optional parameters. */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "applicationType", &event->application_type);
+ evel_enc_kv_opt_string(jbuf, "appProtocolType", &event->app_protocol_type);
+ evel_enc_kv_opt_string(
+ jbuf, "appProtocolVersion", &event->app_protocol_version);
+ evel_enc_kv_opt_string(jbuf, "cid", &event->cid);
+ evel_enc_kv_opt_string(jbuf, "connectionType", &event->connection_type);
+ evel_enc_kv_opt_string(jbuf, "ecgi", &event->ecgi);
+ evel_enc_kv_opt_string(jbuf, "gtpProtocolType", &event->gtp_protocol_type);
+ evel_enc_kv_opt_string(jbuf, "gtpVersion", &event->gtp_version);
+ evel_enc_kv_opt_string(jbuf, "httpHeader", &event->http_header);
+ evel_enc_kv_opt_string(jbuf, "imei", &event->imei);
+ evel_enc_kv_opt_string(jbuf, "imsi", &event->imsi);
+ evel_enc_kv_opt_string(jbuf, "lac", &event->lac);
+ evel_enc_kv_opt_string(jbuf, "mcc", &event->mcc);
+ evel_enc_kv_opt_string(jbuf, "mnc", &event->mnc);
+ evel_enc_kv_opt_string(jbuf, "msisdn", &event->msisdn);
+ evel_enc_kv_opt_string(
+ jbuf, "otherFunctionalRole", &event->other_functional_role);
+ evel_enc_kv_opt_string(jbuf, "rac", &event->rac);
+ evel_enc_kv_opt_string(
+ jbuf, "radioAccessTechnology", &event->radio_access_technology);
+ evel_enc_kv_opt_string(jbuf, "sac", &event->sac);
+ evel_enc_kv_opt_int(jbuf, "samplingAlgorithm", &event->sampling_algorithm);
+ evel_enc_kv_opt_string(jbuf, "tac", &event->tac);
+ evel_enc_kv_opt_string(jbuf, "tunnelId", &event->tunnel_id);
+ evel_enc_kv_opt_string(jbuf, "vlanId", &event->vlan_id);
+#if 0
+ /***************************************************************************/
+ /* Not in schema. */
+ /***************************************************************************/
+ evel_enc_version(jbuf,
+ "mobileFlowFieldsVersion",
+ event->major_version,
+ event->minor_version);
+#endif
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Mobile Flow.
+ *
+ * Free off the Mobile Flow supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Mobile Flow itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_mobile_flow(EVENT_MOBILE_FLOW * event)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ free(event->flow_direction);
+
+ evel_free_mobile_gtp_flow_metrics(event->gtp_per_flow_metrics);
+ free(event->gtp_per_flow_metrics);
+ free(event->ip_protocol_type);
+ free(event->ip_version);
+ free(event->other_endpoint_ip_address);
+ free(event->reporting_endpoint_ip_addr);
+ evel_free_option_string(&event->application_type);
+ evel_free_option_string(&event->app_protocol_type);
+ evel_free_option_string(&event->app_protocol_version);
+ evel_free_option_string(&event->cid);
+ evel_free_option_string(&event->connection_type);
+ evel_free_option_string(&event->ecgi);
+ evel_free_option_string(&event->gtp_protocol_type);
+ evel_free_option_string(&event->gtp_version);
+ evel_free_option_string(&event->http_header);
+ evel_free_option_string(&event->imei);
+ evel_free_option_string(&event->imsi);
+ evel_free_option_string(&event->lac);
+ evel_free_option_string(&event->mcc);
+ evel_free_option_string(&event->mnc);
+ evel_free_option_string(&event->msisdn);
+ evel_free_option_string(&event->other_functional_role);
+ evel_free_option_string(&event->rac);
+ evel_free_option_string(&event->radio_access_technology);
+ evel_free_option_string(&event->sac);
+ evel_free_option_string(&event->tac);
+ evel_free_option_string(&event->tunnel_id);
+ evel_free_option_string(&event->vlan_id);
+
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new Mobile GTP Per Flow Metrics.
+ *
+ * @note The mandatory fields on the Mobile GTP Per Flow Metrics must be
+ * supplied to this factory function and are immutable once set.
+ * Optional fields have explicit setter functions, but again values
+ * may only be set once so that the Mobile GTP Per Flow Metrics has
+ * immutable properties.
+ *
+ * @param avg_bit_error_rate Average bit error rate.
+ * @param avg_packet_delay_variation Average delay or jitter in ms.
+ * @param avg_packet_latency Average delivery latency.
+ * @param avg_receive_throughput Average receive throughput.
+ * @param avg_transmit_throughput Average transmit throughput.
+ * @param flow_activation_epoch Time the connection is activated.
+ * @param flow_activation_microsec Microseconds for the start of the flow
+ * connection.
+ * @param flow_deactivation_epoch Time for the end of the connection.
+ * @param flow_deactivation_microsec Microseconds for the end of the flow
+ * connection.
+ * @param flow_deactivation_time Transmission time of the first packet.
+ * @param flow_status Connection status.
+ * @param max_packet_delay_variation Maximum packet delay or jitter in ms.
+ * @param num_activation_failures Number of failed activation requests.
+ * @param num_bit_errors Number of errored bits.
+ * @param num_bytes_received Number of bytes received.
+ * @param num_bytes_transmitted Number of bytes transmitted.
+ * @param num_dropped_packets Number of received packets dropped.
+ * @param num_l7_bytes_received Number of tunneled Layer 7 bytes
+ * received.
+ * @param num_l7_bytes_transmitted Number of tunneled Layer 7 bytes
+ * transmitted.
+ * @param num_lost_packets Number of lost packets.
+ * @param num_out_of_order_packets Number of out-of-order packets.
+ * @param num_packet_errors Number of errored packets.
+ * @param num_packets_received_excl_retrans Number of packets received,
+ * excluding retransmits.
+ * @param num_packets_received_incl_retrans Number of packets received.
+ * @param num_packets_transmitted_incl_retrans Number of packets
+ * transmitted.
+ * @param num_retries Number of packet retries.
+ * @param num_timeouts Number of packet timeouts.
+ * @param num_tunneled_l7_bytes_received Number of tunneled Layer 7 bytes
+ * received, excluding retransmits.
+ * @param round_trip_time Round trip time.
+ * @param time_to_first_byte Time in ms between connection
+ * activation and first byte received.
+ *
+ * @returns pointer to the newly manufactured ::MOBILE_GTP_PER_FLOW_METRICS.
+ * If the structure is not used it must be released using
+ * ::evel_free_mobile_gtp_flow_metrics.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+MOBILE_GTP_PER_FLOW_METRICS * evel_new_mobile_gtp_flow_metrics(
+ double avg_bit_error_rate,
+ double avg_packet_delay_variation,
+ int avg_packet_latency,
+ int avg_receive_throughput,
+ int avg_transmit_throughput,
+ int flow_activation_epoch,
+ int flow_activation_microsec,
+ int flow_deactivation_epoch,
+ int flow_deactivation_microsec,
+ time_t flow_deactivation_time,
+ const char * const flow_status,
+ int max_packet_delay_variation,
+ int num_activation_failures,
+ int num_bit_errors,
+ int num_bytes_received,
+ int num_bytes_transmitted,
+ int num_dropped_packets,
+ int num_l7_bytes_received,
+ int num_l7_bytes_transmitted,
+ int num_lost_packets,
+ int num_out_of_order_packets,
+ int num_packet_errors,
+ int num_packets_received_excl_retrans,
+ int num_packets_received_incl_retrans,
+ int num_packets_transmitted_incl_retrans,
+ int num_retries,
+ int num_timeouts,
+ int num_tunneled_l7_bytes_received,
+ int round_trip_time,
+ int time_to_first_byte)
+{
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ int ii;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(avg_bit_error_rate >= 0.0);
+ assert(avg_packet_delay_variation >= 0.0);
+ assert(avg_packet_latency >= 0);
+ assert(avg_receive_throughput >= 0);
+ assert(avg_transmit_throughput >= 0);
+ assert(flow_activation_epoch > 0);
+ assert(flow_activation_microsec >= 0);
+ assert(flow_deactivation_epoch > 0);
+ assert(flow_deactivation_microsec >= 0);
+ assert(flow_status != NULL);
+ assert(max_packet_delay_variation >= 0);
+ assert(num_activation_failures >= 0);
+ assert(num_bit_errors >= 0);
+ assert(num_bytes_received >= 0);
+ assert(num_bytes_transmitted >= 0);
+ assert(num_dropped_packets >= 0);
+ assert(num_l7_bytes_received >= 0);
+ assert(num_l7_bytes_transmitted >= 0);
+ assert(num_lost_packets >= 0);
+ assert(num_out_of_order_packets >= 0);
+ assert(num_packet_errors >= 0);
+ assert(num_packets_received_excl_retrans >= 0);
+ assert(num_packets_received_incl_retrans >= 0);
+ assert(num_packets_transmitted_incl_retrans >= 0);
+ assert(num_retries >= 0);
+ assert(num_timeouts >= 0);
+ assert(num_tunneled_l7_bytes_received >= 0);
+ assert(round_trip_time >= 0);
+ assert(time_to_first_byte >= 0);
+
+ /***************************************************************************/
+ /* Allocate the Mobile Flow GTP Per Flow Metrics. */
+ /***************************************************************************/
+ metrics = malloc(sizeof(MOBILE_GTP_PER_FLOW_METRICS));
+ if (metrics == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(metrics, 0, sizeof(MOBILE_GTP_PER_FLOW_METRICS));
+ EVEL_DEBUG("New Mobile Flow GTP Per Flow Metrics is at %lp", metrics);
+
+ /***************************************************************************/
+ /* Initialize the Mobile Flow GTP Per Flow Metrics fields. Optional */
+ /* string values are uninitialized (NULL). */
+ /***************************************************************************/
+ metrics->avg_bit_error_rate = avg_bit_error_rate;
+ metrics->avg_packet_delay_variation = avg_packet_delay_variation;
+ metrics->avg_packet_latency = avg_packet_latency;
+ metrics->avg_receive_throughput = avg_receive_throughput;
+ metrics->avg_transmit_throughput = avg_transmit_throughput;
+ metrics->flow_activation_epoch = flow_activation_epoch;
+ metrics->flow_activation_microsec = flow_activation_microsec;
+ metrics->flow_deactivation_epoch = flow_deactivation_epoch;
+ metrics->flow_deactivation_microsec = flow_deactivation_microsec;
+ metrics->flow_deactivation_time = flow_deactivation_time;
+ metrics->flow_status = strdup(flow_status);
+ metrics->max_packet_delay_variation = max_packet_delay_variation;
+ metrics->num_activation_failures = num_activation_failures;
+ metrics->num_bit_errors = num_bit_errors;
+ metrics->num_bytes_received = num_bytes_received;
+ metrics->num_bytes_transmitted = num_bytes_transmitted;
+ metrics->num_dropped_packets = num_dropped_packets;
+ metrics->num_l7_bytes_received = num_l7_bytes_received;
+ metrics->num_l7_bytes_transmitted = num_l7_bytes_transmitted;
+ metrics->num_lost_packets = num_lost_packets;
+ metrics->num_out_of_order_packets = num_out_of_order_packets;
+ metrics->num_packet_errors = num_packet_errors;
+ metrics->num_packets_received_excl_retrans =
+ num_packets_received_excl_retrans;
+ metrics->num_packets_received_incl_retrans =
+ num_packets_received_incl_retrans;
+ metrics->num_packets_transmitted_incl_retrans =
+ num_packets_transmitted_incl_retrans;
+ metrics->num_retries = num_retries;
+ metrics->num_timeouts = num_timeouts;
+ metrics->num_tunneled_l7_bytes_received = num_tunneled_l7_bytes_received;
+ metrics->round_trip_time = round_trip_time;
+ metrics->time_to_first_byte = time_to_first_byte;
+ for (ii = 0; ii < EVEL_TOS_SUPPORTED; ii++)
+ {
+ evel_init_option_int(&metrics->ip_tos_counts[ii]);
+ }
+ for (ii = 0; ii < EVEL_MAX_TCP_FLAGS; ii++)
+ {
+ evel_init_option_int(&metrics->tcp_flag_counts[ii]);
+ }
+ for (ii = 0; ii < EVEL_MAX_QCI_COS_TYPES; ii++)
+ {
+ evel_init_option_int(&metrics->qci_cos_counts[ii]);
+ }
+ evel_init_option_int(&metrics->dur_connection_failed_status);
+ evel_init_option_int(&metrics->dur_tunnel_failed_status);
+ evel_init_option_string(&metrics->flow_activated_by);
+ evel_init_option_time(&metrics->flow_activation_time);
+ evel_init_option_string(&metrics->flow_deactivated_by);
+ evel_init_option_string(&metrics->gtp_connection_status);
+ evel_init_option_string(&metrics->gtp_tunnel_status);
+ evel_init_option_int(&metrics->large_packet_rtt);
+ evel_init_option_double(&metrics->large_packet_threshold);
+ evel_init_option_int(&metrics->max_receive_bit_rate);
+ evel_init_option_int(&metrics->max_transmit_bit_rate);
+ evel_init_option_int(&metrics->num_gtp_echo_failures);
+ evel_init_option_int(&metrics->num_gtp_tunnel_errors);
+ evel_init_option_int(&metrics->num_http_errors);
+
+exit_label:
+ EVEL_EXIT();
+ return metrics;
+}
+
+/**************************************************************************//**
+ * Set the Duration of Connection Failed Status property of the Mobile GTP Per
+ * Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param duration The Duration of Connection Failed Status to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_dur_con_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int duration)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(duration >= 0);
+
+ evel_set_option_int(&metrics->dur_connection_failed_status,
+ duration,
+ "Duration of Connection Failed Status");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Duration of Tunnel Failed Status property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param duration The Duration of Tunnel Failed Status to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_dur_tun_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int duration)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(duration >= 0);
+
+ evel_set_option_int(&metrics->dur_tunnel_failed_status,
+ duration,
+ "Duration of Tunnel Failed Status");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Activated By property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param act_by The Activated By to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_act_by_set(MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const act_by)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(act_by != NULL);
+
+ evel_set_option_string(&metrics->flow_activated_by,
+ act_by,
+ "Activated By");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Activation Time property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param act_time The Activation Time to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_act_time_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ time_t act_time)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(act_time > 0);
+
+ evel_set_option_time(&metrics->flow_activation_time,
+ act_time,
+ "Activation Time");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Deactivated By property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param deact_by The Deactivated By to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_deact_by_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const deact_by)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(deact_by != NULL);
+
+ evel_set_option_string(&metrics->flow_deactivated_by,
+ deact_by,
+ "Deactivated By");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the GTP Connection Status property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param status The GTP Connection Status to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_con_status_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const status)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(status != NULL);
+
+ evel_set_option_string(&metrics->gtp_connection_status,
+ status,
+ "GTP Connection Status");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the GTP Tunnel Status property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param status The GTP Tunnel Status to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_tun_status_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const status)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(status != NULL);
+
+ evel_set_option_string(&metrics->gtp_tunnel_status,
+ status,
+ "GTP Tunnel Status");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set an IP Type-of-Service count property of the Mobile GTP Per Flow metrics.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param index The index of the IP Type-of-Service.
+ * @param count The count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_iptos_set(MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int index,
+ int count)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(index >= 0);
+ assert(index < EVEL_TOS_SUPPORTED);
+ assert(count >= 0);
+ assert(count <= 255);
+
+ EVEL_DEBUG("IP Type-of-Service %d", index);
+ evel_set_option_int(&metrics->ip_tos_counts[index],
+ count,
+ "IP Type-of-Service");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Large Packet Round-Trip Time property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rtt The Large Packet Round-Trip Time to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_large_pkt_rtt_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rtt)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(rtt >= 0);
+
+ evel_set_option_int(&metrics->large_packet_rtt,
+ rtt,
+ "Large Packet Round-Trip Time");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Large Packet Threshold property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param threshold The Large Packet Threshold to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_large_pkt_thresh_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ double threshold)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(threshold >= 0.0);
+
+ evel_set_option_double(&metrics->large_packet_threshold,
+ threshold,
+ "Large Packet Threshold");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Max Receive Bit Rate property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rate The Max Receive Bit Rate to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_max_rcv_bit_rate_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rate)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(rate >= 0);
+
+ evel_set_option_int(&metrics->max_receive_bit_rate,
+ rate,
+ "Max Receive Bit Rate");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Max Transmit Bit Rate property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rate The Max Transmit Bit Rate to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_max_trx_bit_rate_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rate)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(rate >= 0);
+
+ evel_set_option_int(&metrics->max_transmit_bit_rate,
+ rate,
+ "Max Transmit Bit Rate");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Number of GTP Echo Failures property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of GTP Echo Failures to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_echo_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(num >= 0);
+
+ evel_set_option_int(&metrics->num_gtp_echo_failures,
+ num,
+ "Number of GTP Echo Failures");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Number of GTP Tunnel Errors property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of GTP Tunnel Errors to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_tun_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(num >= 0);
+
+ evel_set_option_int(&metrics->num_gtp_tunnel_errors,
+ num,
+ "Number of GTP Tunnel Errors");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Number of HTTP Errors property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of HTTP Errors to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_http_errors_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(num >= 0);
+
+ evel_set_option_int(&metrics->num_http_errors,
+ num,
+ "Number of HTTP Errors");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a TCP flag count to the metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param tcp_flag The TCP flag to be updated.
+ * @param count The associated flag count, which must be nonzero.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_tcp_flag_count_add(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const EVEL_TCP_FLAGS tcp_flag,
+ const int count)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(tcp_flag >= 0);
+ assert(tcp_flag < EVEL_MAX_TCP_FLAGS);
+ assert(count >= 0);
+
+ EVEL_DEBUG("TCP Flag: %d", tcp_flag);
+ evel_set_option_int(&metrics->tcp_flag_counts[tcp_flag],
+ count,
+ "TCP flag");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a QCI COS count to the metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param qci_cos The QCI COS count to be updated.
+ * @param count The associated QCI COS count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_qci_cos_count_add(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const EVEL_QCI_COS_TYPES qci_cos,
+ const int count)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+ assert(qci_cos >= 0);
+ assert(qci_cos < EVEL_MAX_QCI_COS_TYPES);
+ assert(count >= 0);
+
+ EVEL_DEBUG("QCI COS: %d", qci_cos);
+ evel_set_option_int(&metrics->qci_cos_counts[qci_cos],
+ count,
+ "QCI COS");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Mobile Flow GTP Per Flow Metrics as a JSON object.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param metrics Pointer to the ::EVENT_MOBILE_FLOW to encode.
+ * @returns Number of bytes actually written.
+ *****************************************************************************/
+void evel_json_encode_mobile_flow_gtp_flow_metrics(
+ EVEL_JSON_BUFFER * jbuf,
+ MOBILE_GTP_PER_FLOW_METRICS * metrics)
+{
+ int index;
+ bool found_ip_tos;
+ bool found_tcp_flag;
+ bool found_qci_cos;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(metrics != NULL);
+
+ evel_json_open_named_object(jbuf, "gtpPerFlowMetrics");
+
+ /***************************************************************************/
+ /* Mandatory parameters. */
+ /***************************************************************************/
+ evel_enc_kv_double(jbuf, "avgBitErrorRate", metrics->avg_bit_error_rate);
+ evel_enc_kv_double(
+ jbuf, "avgPacketDelayVariation", metrics->avg_packet_delay_variation);
+ evel_enc_kv_int(jbuf, "avgPacketLatency", metrics->avg_packet_latency);
+ evel_enc_kv_int(
+ jbuf, "avgReceiveThroughput", metrics->avg_receive_throughput);
+ evel_enc_kv_int(
+ jbuf, "avgTransmitThroughput", metrics->avg_transmit_throughput);
+ evel_enc_kv_int(jbuf, "flowActivationEpoch", metrics->flow_activation_epoch);
+ evel_enc_kv_int(
+ jbuf, "flowActivationMicrosec", metrics->flow_activation_microsec);
+ evel_enc_kv_int(
+ jbuf, "flowDeactivationEpoch", metrics->flow_deactivation_epoch);
+ evel_enc_kv_int(
+ jbuf, "flowDeactivationMicrosec", metrics->flow_deactivation_microsec);
+ evel_enc_kv_time(
+ jbuf, "flowDeactivationTime", &metrics->flow_deactivation_time);
+ evel_enc_kv_string(jbuf, "flowStatus", metrics->flow_status);
+ evel_enc_kv_int(
+ jbuf, "maxPacketDelayVariation", metrics->max_packet_delay_variation);
+ evel_enc_kv_int(
+ jbuf, "numActivationFailures", metrics->num_activation_failures);
+ evel_enc_kv_int(jbuf, "numBitErrors", metrics->num_bit_errors);
+ evel_enc_kv_int(jbuf, "numBytesReceived", metrics->num_bytes_received);
+ evel_enc_kv_int(jbuf, "numBytesTransmitted", metrics->num_bytes_transmitted);
+ evel_enc_kv_int(jbuf, "numDroppedPackets", metrics->num_dropped_packets);
+ evel_enc_kv_int(jbuf, "numL7BytesReceived", metrics->num_l7_bytes_received);
+ evel_enc_kv_int(
+ jbuf, "numL7BytesTransmitted", metrics->num_l7_bytes_transmitted);
+ evel_enc_kv_int(jbuf, "numLostPackets", metrics->num_lost_packets);
+ evel_enc_kv_int(
+ jbuf, "numOutOfOrderPackets", metrics->num_out_of_order_packets);
+ evel_enc_kv_int(jbuf, "numPacketErrors", metrics->num_packet_errors);
+ evel_enc_kv_int(jbuf,
+ "numPacketsReceivedExclRetrans",
+ metrics->num_packets_received_excl_retrans);
+ evel_enc_kv_int(jbuf,
+ "numPacketsReceivedInclRetrans",
+ metrics->num_packets_received_incl_retrans);
+ evel_enc_kv_int(jbuf,
+ "numPacketsTransmittedInclRetrans",
+ metrics->num_packets_transmitted_incl_retrans);
+ evel_enc_kv_int(jbuf, "numRetries", metrics->num_retries);
+ evel_enc_kv_int(jbuf, "numTimeouts", metrics->num_timeouts);
+ evel_enc_kv_int(jbuf,
+ "numTunneledL7BytesReceived",
+ metrics->num_tunneled_l7_bytes_received);
+ evel_enc_kv_int(jbuf, "roundTripTime", metrics->round_trip_time);
+ evel_enc_kv_int(jbuf, "timeToFirstByte", metrics->time_to_first_byte);
+
+ /***************************************************************************/
+ /* Optional parameters. */
+ /***************************************************************************/
+ found_ip_tos = false;
+ for (index = 0; index < EVEL_TOS_SUPPORTED; index++)
+ {
+ if (metrics->ip_tos_counts[index].is_set)
+ {
+ found_ip_tos = true;
+ break;
+ }
+ }
+
+ if (found_ip_tos)
+ {
+ evel_json_open_named_list(jbuf, "ipTosCountList");
+ for (index = 0; index < EVEL_TOS_SUPPORTED; index++)
+ {
+ if (metrics->ip_tos_counts[index].is_set)
+ {
+ evel_enc_list_item(jbuf,
+ "[\"%d\", %d]",
+ index,
+ metrics->ip_tos_counts[index].value);
+ }
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ if (found_ip_tos)
+ {
+ evel_json_open_named_list(jbuf, "ipTosList");
+ for (index = 0; index < EVEL_TOS_SUPPORTED; index++)
+ {
+ if (metrics->ip_tos_counts[index].is_set)
+ {
+ evel_enc_list_item(jbuf, "\"%d\"", index);
+ }
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ /***************************************************************************/
+ /* Make some compile-time assertions about EVEL_TCP_FLAGS. If you update */
+ /* these, make sure you update evel_tcp_flag_strings to match the enum. */
+ /***************************************************************************/
+ EVEL_CT_ASSERT(EVEL_TCP_NS == 0);
+ EVEL_CT_ASSERT(EVEL_TCP_CWR == 1);
+ EVEL_CT_ASSERT(EVEL_TCP_ECE == 2);
+ EVEL_CT_ASSERT(EVEL_TCP_URG == 3);
+ EVEL_CT_ASSERT(EVEL_TCP_ACK == 4);
+ EVEL_CT_ASSERT(EVEL_TCP_PSH == 5);
+ EVEL_CT_ASSERT(EVEL_TCP_RST == 6);
+ EVEL_CT_ASSERT(EVEL_TCP_SYN == 7);
+ EVEL_CT_ASSERT(EVEL_TCP_FIN == 8);
+ EVEL_CT_ASSERT(EVEL_MAX_TCP_FLAGS == 9);
+
+ found_tcp_flag = false;
+ for (index = 0; index < EVEL_MAX_TCP_FLAGS; index++)
+ {
+ if (metrics->tcp_flag_counts[index].is_set)
+ {
+ found_tcp_flag = true;
+ break;
+ }
+ }
+
+ if (found_tcp_flag)
+ {
+ evel_json_open_named_list(jbuf, "tcpFlagList");
+ for (index = 0; index < EVEL_MAX_TCP_FLAGS; index++)
+ {
+ if (metrics->tcp_flag_counts[index].is_set)
+ {
+ evel_enc_list_item(jbuf,
+ "\"%s\"",
+ evel_tcp_flag_strings[index]);
+ }
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ if (found_tcp_flag)
+ {
+ evel_json_open_named_list(jbuf, "tcpFlagCountList");
+ for (index = 0; index < EVEL_MAX_TCP_FLAGS; index++)
+ {
+ if (metrics->tcp_flag_counts[index].is_set)
+ {
+ evel_enc_list_item(jbuf,
+ "[\"%s\", %d]",
+ evel_tcp_flag_strings[index],
+ metrics->tcp_flag_counts[index].value);
+ }
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ /***************************************************************************/
+ /* Make some compile-time assertions about EVEL_QCI_COS_TYPES. If you */
+ /* update these, make sure you update evel_qci_cos_strings to match the */
+ /* enum. */
+ /***************************************************************************/
+ EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_CONVERSATIONAL ==0);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_STREAMING == 1);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_INTERACTIVE == 2);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_BACKGROUND == 3);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_1 == 4);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_2 == 5);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_3 == 6);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_4 == 7);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_65 == 8);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_66 == 9);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_5 == 10);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_6 == 11);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_7 == 12);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_8 == 13);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_9 == 14);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_69 == 15);
+ EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_70 == 16);
+ EVEL_CT_ASSERT(EVEL_MAX_QCI_COS_TYPES == 17);
+
+ found_qci_cos = false;
+ for (index = 0; index < EVEL_MAX_QCI_COS_TYPES; index++)
+ {
+ if (metrics->qci_cos_counts[index].is_set)
+ {
+ found_qci_cos = true;
+ break;
+ }
+ }
+
+ if (found_qci_cos)
+ {
+ evel_json_open_named_list(jbuf, "mobileQciCosList");
+ for (index = 0; index < EVEL_MAX_QCI_COS_TYPES; index++)
+ {
+ if (metrics->qci_cos_counts[index].is_set)
+ {
+ evel_enc_list_item(jbuf,
+ "\"%s\"",
+ evel_qci_cos_strings[index]);
+ }
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ if (found_qci_cos)
+ {
+ evel_json_open_named_list(jbuf, "mobileQciCosCountList");
+ for (index = 0; index < EVEL_MAX_QCI_COS_TYPES; index++)
+ {
+ if (metrics->qci_cos_counts[index].is_set)
+ {
+ evel_enc_list_item(jbuf,
+ "[\"%s\", %d]",
+ evel_qci_cos_strings[index],
+ metrics->qci_cos_counts[index].value);
+ }
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ evel_enc_kv_opt_int(
+ jbuf, "durConnectionFailedStatus", &metrics->dur_connection_failed_status);
+ evel_enc_kv_opt_int(
+ jbuf, "durTunnelFailedStatus", &metrics->dur_tunnel_failed_status);
+ evel_enc_kv_opt_string(jbuf, "flowActivatedBy", &metrics->flow_activated_by);
+ evel_enc_kv_opt_time(
+ jbuf, "flowActivationTime", &metrics->flow_activation_time);
+ evel_enc_kv_opt_string(
+ jbuf, "flowDeactivatedBy", &metrics->flow_deactivated_by);
+ evel_enc_kv_opt_string(
+ jbuf, "gtpConnectionStatus", &metrics->gtp_connection_status);
+ evel_enc_kv_opt_string(jbuf, "gtpTunnelStatus", &metrics->gtp_tunnel_status);
+ evel_enc_kv_opt_int(jbuf, "largePacketRtt", &metrics->large_packet_rtt);
+ evel_enc_kv_opt_double(
+ jbuf, "largePacketThreshold", &metrics->large_packet_threshold);
+ evel_enc_kv_opt_int(
+ jbuf, "maxReceiveBitRate", &metrics->max_receive_bit_rate);
+ evel_enc_kv_opt_int(
+ jbuf, "maxTransmitBitRate", &metrics->max_transmit_bit_rate);
+ evel_enc_kv_opt_int(
+ jbuf, "numGtpEchoFailures", &metrics->num_gtp_echo_failures);
+ evel_enc_kv_opt_int(
+ jbuf, "numGtpTunnelErrors", &metrics->num_gtp_tunnel_errors);
+ evel_enc_kv_opt_int(jbuf, "numHttpErrors", &metrics->num_http_errors);
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Mobile GTP Per Flow Metrics.
+ *
+ * Free off the Mobile GTP Per Flow Metrics supplied. Will free all the
+ * contained allocated memory.
+ *
+ * @note It does not free the Mobile GTP Per Flow Metrics itself, since that
+ * may be part of a larger structure.
+ *****************************************************************************/
+void evel_free_mobile_gtp_flow_metrics(MOBILE_GTP_PER_FLOW_METRICS * metrics)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(metrics != NULL);
+
+ /***************************************************************************/
+ /* Free all internal strings. */
+ /***************************************************************************/
+ free(metrics->flow_status);
+
+ evel_free_option_string(&metrics->flow_activated_by);
+ evel_free_option_string(&metrics->flow_deactivated_by);
+ evel_free_option_string(&metrics->gtp_connection_status);
+ evel_free_option_string(&metrics->gtp_tunnel_status);
+
+ EVEL_EXIT();
+} \ No newline at end of file
diff --git a/vnfs/VES/code/evel_library/evel_option.c b/vnfs/VES/code/evel_library/evel_option.c
new file mode 100644
index 00000000..fe714b53
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_option.c
@@ -0,0 +1,442 @@
+/**************************************************************************//**
+ * @file
+ * Source module relating to EVEL_OPTION_ types.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Free the underlying resources of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ *****************************************************************************/
+void evel_free_option_string(EVEL_OPTION_STRING * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ free(option->value);
+ option->value = NULL;
+ option->is_set = EVEL_FALSE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_STRING to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ *****************************************************************************/
+void evel_init_option_string(EVEL_OPTION_STRING * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = NULL;
+ option->is_set = EVEL_FALSE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_string(EVEL_OPTION_STRING * const option,
+ const char * const value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(value != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %s. %s already set to %s",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %s", description, value);
+ option->value = strdup(value);
+ option->is_set = EVEL_TRUE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_string(EVEL_OPTION_STRING * const option,
+ const char * const value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(option->is_set == EVEL_FALSE);
+ assert(option->value == NULL);
+
+ option->value = strdup(value);
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_INT to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ *****************************************************************************/
+void evel_init_option_int(EVEL_OPTION_INT * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = 0;
+ option->is_set = EVEL_FALSE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_INT.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_int(EVEL_OPTION_INT * const option,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_INT.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_int(EVEL_OPTION_INT * const option,
+ const int value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %d. %s already set to %d",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %d", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_DOUBLE to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ *****************************************************************************/
+void evel_init_option_double(EVEL_OPTION_DOUBLE * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = 0.0;
+ option->is_set = EVEL_FALSE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_DOUBLE.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_double(EVEL_OPTION_DOUBLE * const option,
+ const double value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_DOUBLE.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_double(EVEL_OPTION_DOUBLE * const option,
+ const double value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %lf. %s already set to %lf",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %lf", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_ULL to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ *****************************************************************************/
+void evel_init_option_ull(EVEL_OPTION_ULL * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ option->value = 0;
+ option->is_set = EVEL_FALSE;
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_ULL.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_ull(EVEL_OPTION_ULL * const option,
+ const unsigned long long value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_ULL.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_ull(EVEL_OPTION_ULL * const option,
+ const unsigned long long value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %llu. %s already set to %llu",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %llu", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_TIME to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_TIME.
+ *****************************************************************************/
+void evel_init_option_time(EVEL_OPTION_TIME * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ option->value = 0;
+ option->is_set = EVEL_FALSE;
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_TIME.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_TIME.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_time(EVEL_OPTION_TIME * const option,
+ const time_t value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_TIME.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_TIME.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_time(EVEL_OPTION_TIME * const option,
+ const time_t value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %d. %s already set to %d",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %d", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_other.c b/vnfs/VES/code/evel_library/evel_other.c
new file mode 100644
index 00000000..f63a091a
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_other.c
@@ -0,0 +1,231 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Other.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Create a new Other event.
+ *
+ * @note The mandatory fields on the Other must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Other has immutable properties.
+ * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is
+ * not used (i.e. posted) it must be released using ::evel_free_other.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_OTHER * evel_new_other()
+{
+ EVENT_OTHER * other = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+
+ /***************************************************************************/
+ /* Allocate the Other. */
+ /***************************************************************************/
+ other = malloc(sizeof(EVENT_OTHER));
+ if (other == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(other, 0, sizeof(EVENT_OTHER));
+ EVEL_DEBUG("New Other is at %lp", other);
+
+ /***************************************************************************/
+ /* Initialize the header & the Other fields. Optional string values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&other->header);
+ other->header.event_domain = EVEL_DOMAIN_OTHER;
+ dlist_initialize(&other->other_fields);
+
+exit_label:
+ EVEL_EXIT();
+ return other;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Other.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param other Pointer to the Other.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_other_type_set(EVENT_OTHER * other,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(other != NULL);
+ assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
+ evel_header_type_set(&other->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a field name/value pair to the Other.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param other Pointer to the Other.
+ * @param name ASCIIZ string with the field's name. The caller does not
+ * need to preserve the value once the function returns.
+ * @param value ASCIIZ string with the field's value. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_other_field_add(EVENT_OTHER * other, char * name, char * value)
+{
+ OTHER_FIELD * other_field = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(other != NULL);
+ assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ other_field = malloc(sizeof(OTHER_FIELD));
+ assert(other_field != NULL);
+ memset(other_field, 0, sizeof(OTHER_FIELD));
+ other_field->name = strdup(name);
+ other_field->value = strdup(value);
+ assert(other_field->name != NULL);
+ assert(other_field->value != NULL);
+
+ dlist_push_last(&other->other_fields, other_field);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Other in JSON according to AT&T's schema for the event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf,
+ EVENT_OTHER * event)
+{
+ OTHER_FIELD * other_field = NULL;
+ DLIST_ITEM * other_field_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_list(jbuf, "otherFields");
+ other_field_item = dlist_get_first(&event->other_fields);
+ while (other_field_item != NULL)
+ {
+ other_field = (OTHER_FIELD *) other_field_item->item;
+ assert(other_field != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", other_field->name);
+ evel_enc_kv_string(jbuf, "value", other_field->value);
+ evel_json_close_object(jbuf);
+ other_field_item = dlist_get_next(other_field_item);
+ }
+ evel_json_close_list(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free an Other.
+ *
+ * Free off the Other supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Other itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_other(EVENT_OTHER * event)
+{
+ OTHER_FIELD * other_field = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ other_field = dlist_pop_last(&event->other_fields);
+ while (other_field != NULL)
+ {
+ EVEL_DEBUG("Freeing Other Field (%s, %s)",
+ other_field->name,
+ other_field->value);
+ free(other_field->name);
+ free(other_field->value);
+ free(other_field);
+ other_field = dlist_pop_last(&event->other_fields);
+ }
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+} \ No newline at end of file
diff --git a/vnfs/VES/code/evel_library/evel_reporting_measurement.c b/vnfs/VES/code/evel_library/evel_reporting_measurement.c
new file mode 100644
index 00000000..84552934
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_reporting_measurement.c
@@ -0,0 +1,450 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Measurement for VF
+ * Reporting event.
+ *
+ * @note This is an experimental event tytpe and does not form part of the
+ * currently approved AT&T event schema. It is intended to allow a
+ * less-onerous event reporting mechanism because it avoids having to
+ * return all the platform statistics which are mandatory in the
+ * **measurementsForVfScaling** event.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Report event.
+ *
+ * @note The mandatory fields on the Report must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Report has immutable properties.
+ *
+ * @param measurement_interval
+
+ * @returns pointer to the newly manufactured ::EVENT_REPORT. If the event is
+ * not used (i.e. posted) it must be released using ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_REPORT * evel_new_report(double measurement_interval)
+{
+ EVENT_REPORT * report = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement_interval >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate the report. */
+ /***************************************************************************/
+ report = malloc(sizeof(EVENT_REPORT));
+ if (report == NULL)
+ {
+ log_error_state("Out of memory for Report");
+ goto exit_label;
+ }
+ memset(report, 0, sizeof(EVENT_REPORT));
+ EVEL_DEBUG("New report is at %lp", report);
+
+ /***************************************************************************/
+ /* Initialize the header & the report fields. */
+ /***************************************************************************/
+ evel_init_header(&report->header);
+ report->header.event_domain = EVEL_DOMAIN_REPORT;
+ report->measurement_interval = measurement_interval;
+
+ dlist_initialize(&report->feature_usage);
+ dlist_initialize(&report->measurement_groups);
+ report->major_version = EVEL_REPORT_MAJOR_VERSION;
+ report->minor_version = EVEL_REPORT_MINOR_VERSION;
+
+exit_label:
+ EVEL_EXIT();
+ return report;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Report.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param report Pointer to the Report.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_report_type_set(EVENT_REPORT * report,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(report != NULL);
+ assert(report->header.event_domain == EVEL_DOMAIN_REPORT);
+ evel_header_type_set(&report->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param report Pointer to the report.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_report_feature_use_add(EVENT_REPORT * report,
+ char * feature,
+ int utilization)
+{
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(report != NULL);
+ assert(report->header.event_domain == EVEL_DOMAIN_REPORT);
+ assert(feature != NULL);
+ assert(utilization >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization);
+ feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE));
+ assert(feature_use != NULL);
+ memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE));
+ feature_use->feature_id = strdup(feature);
+ assert(feature_use->feature_id != NULL);
+ feature_use->feature_utilization = utilization;
+
+ dlist_push_last(&report->feature_usage, feature_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param report Pointer to the report.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param value ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_report_custom_measurement_add(EVENT_REPORT * report,
+ const char * const group,
+ const char * const name,
+ const char * const value)
+{
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(report != NULL);
+ assert(report->header.event_domain == EVEL_DOMAIN_REPORT);
+ assert(group != NULL);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ /***************************************************************************/
+ /* Allocate a container for the name/value pair. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s",
+ group, name, value);
+ measurement = malloc(sizeof(CUSTOM_MEASUREMENT));
+ assert(measurement != NULL);
+ memset(measurement, 0, sizeof(CUSTOM_MEASUREMENT));
+ measurement->name = strdup(name);
+ assert(measurement->name != NULL);
+ measurement->value = strdup(value);
+ assert(measurement->value != NULL);
+
+ /***************************************************************************/
+ /* See if we have that group already. */
+ /***************************************************************************/
+ item = dlist_get_first(&report->measurement_groups);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ EVEL_DEBUG("Got measurement group %s", measurement_group->name);
+ if (strcmp(group, measurement_group->name) == 0)
+ {
+ EVEL_DEBUG("Found existing Measurement Group");
+ break;
+ }
+ item = dlist_get_next(item);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ if (item == NULL)
+ {
+ EVEL_DEBUG("Creating new Measurement Group");
+ measurement_group = malloc(sizeof(MEASUREMENT_GROUP));
+ assert(measurement_group != NULL);
+ memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP));
+ measurement_group->name = strdup(group);
+ assert(measurement_group->name != NULL);
+ dlist_initialize(&measurement_group->measurements);
+ dlist_push_last(&report->measurement_groups, measurement_group);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ dlist_push_last(&measurement_group->measurements, measurement);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the report as a JSON report.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_report(EVEL_JSON_BUFFER * jbuf,
+ EVENT_REPORT * event)
+{
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ DLIST_ITEM * nested_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_REPORT);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "measurementsForVfReportingFields");
+ evel_enc_kv_double(jbuf, "measurementInterval", event->measurement_interval);
+
+ /***************************************************************************/
+ /* Feature Utilization list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "featureUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->feature_usage);
+ while (item != NULL)
+ {
+ feature_use = (MEASUREMENT_FEATURE_USE*) item->item;
+ assert(feature_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "featureUsageArray",
+ feature_use->feature_id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "featureIdentifier", feature_use->feature_id);
+ evel_enc_kv_int(
+ jbuf, "featureUtilization", feature_use->feature_utilization);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Additional Measurement Groups list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalMeasurements"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->measurement_groups);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalMeasurements",
+ measurement_group->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", measurement_group->name);
+ evel_json_open_named_list(jbuf, "measurements");
+
+ /*********************************************************************/
+ /* Measurements list. */
+ /*********************************************************************/
+ nested_item = dlist_get_first(&measurement_group->measurements);
+ while (nested_item != NULL)
+ {
+ custom_measurement = (CUSTOM_MEASUREMENT *) nested_item->item;
+ assert(custom_measurement != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", custom_measurement->name);
+ evel_enc_kv_string(jbuf, "value", custom_measurement->value);
+ evel_json_close_object(jbuf);
+ nested_item = dlist_get_next(nested_item);
+ }
+ evel_json_close_list(jbuf);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Although optional, we always generate the version. Note that this */
+ /* closes the object, too. */
+ /***************************************************************************/
+ evel_enc_version(jbuf,
+ "measurementFieldsVersion",
+ event->major_version,
+ event->major_version);
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Report.
+ *
+ * Free off the Report supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Report itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_report(EVENT_REPORT * event)
+{
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_REPORT);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ feature_use = dlist_pop_last(&event->feature_usage);
+ while (feature_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Feature use Info (%s)", feature_use->feature_id);
+ free(feature_use->feature_id);
+ free(feature_use);
+ feature_use = dlist_pop_last(&event->feature_usage);
+ }
+ measurement_group = dlist_pop_last(&event->measurement_groups);
+ while (measurement_group != NULL)
+ {
+ EVEL_DEBUG("Freeing Measurement Group (%s)", measurement_group->name);
+
+ custom_measurement = dlist_pop_last(&measurement_group->measurements);
+ while (custom_measurement != NULL)
+ {
+ EVEL_DEBUG("Freeing mesaurement (%s)", custom_measurement->name);
+
+ free(custom_measurement->name);
+ free(custom_measurement->value);
+ free(custom_measurement);
+ custom_measurement = dlist_pop_last(&measurement_group->measurements);
+ }
+
+ free(measurement_group->name);
+ free(measurement_group);
+ measurement_group = dlist_pop_last(&event->measurement_groups);
+ }
+
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_scaling_measurement.c b/vnfs/VES/code/evel_library/evel_scaling_measurement.c
new file mode 100644
index 00000000..ec8f32a4
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_scaling_measurement.c
@@ -0,0 +1,1711 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Measurement.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Measurement event.
+ *
+ * @note The mandatory fields on the Measurement must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Measurement has immutable properties.
+ *
+ * @param measurement_interval
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval)
+{
+ EVENT_MEASUREMENT * measurement = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement_interval >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate the measurement. */
+ /***************************************************************************/
+ measurement = malloc(sizeof(EVENT_MEASUREMENT));
+ if (measurement == NULL)
+ {
+ log_error_state("Out of memory for Measurement");
+ goto exit_label;
+ }
+ memset(measurement, 0, sizeof(EVENT_MEASUREMENT));
+ EVEL_DEBUG("New measurement is at %lp", measurement);
+
+ /***************************************************************************/
+ /* Initialize the header & the measurement fields. */
+ /***************************************************************************/
+ evel_init_header(&measurement->header);
+ measurement->header.event_domain = EVEL_DOMAIN_MEASUREMENT;
+ measurement->measurement_interval = measurement_interval;
+ dlist_initialize(&measurement->cpu_usage);
+ dlist_initialize(&measurement->filesystem_usage);
+ dlist_initialize(&measurement->latency_distribution);
+ dlist_initialize(&measurement->vnic_usage);
+ dlist_initialize(&measurement->codec_usage);
+ dlist_initialize(&measurement->feature_usage);
+ dlist_initialize(&measurement->additional_measurements);
+ evel_init_option_double(&measurement->aggregate_cpu_usage);
+ evel_init_option_double(&measurement->mean_request_latency);
+ evel_init_option_double(&measurement->memory_configured);
+ evel_init_option_double(&measurement->memory_used);
+ evel_init_option_double(&measurement->vnfc_scaling_metric);
+ evel_init_option_int(&measurement->concurrent_sessions);
+ evel_init_option_int(&measurement->configured_entities);
+ evel_init_option_int(&measurement->media_ports_in_use);
+ evel_init_option_int(&measurement->request_rate);
+ measurement->major_version = EVEL_MEASUREMENT_MAJOR_VERSION;
+ measurement->minor_version = EVEL_MEASUREMENT_MINOR_VERSION;
+
+exit_label:
+ EVEL_EXIT();
+ return measurement;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_measurement_type_set(EVENT_MEASUREMENT * measurement,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ evel_header_type_set(&measurement->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Concurrent Sessions property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param concurrent_sessions The Concurrent Sessions to be set.
+ *****************************************************************************/
+void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement,
+ int concurrent_sessions)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(concurrent_sessions >= 0);
+
+ evel_set_option_int(&measurement->concurrent_sessions,
+ concurrent_sessions,
+ "Concurrent Sessions");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Configured Entities property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param configured_entities The Configured Entities to be set.
+ *****************************************************************************/
+void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement,
+ int configured_entities)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(configured_entities >= 0);
+
+ evel_set_option_int(&measurement->configured_entities,
+ configured_entities,
+ "Configured Entities");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional set of Errors to the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param receive_discards The number of receive discards.
+ * @param receive_errors The number of receive errors.
+ * @param transmit_discards The number of transmit discards.
+ * @param transmit_errors The number of transmit errors.
+ *****************************************************************************/
+void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement,
+ int receive_discards,
+ int receive_errors,
+ int transmit_discards,
+ int transmit_errors)
+{
+ MEASUREMENT_ERRORS * errors = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(receive_discards >= 0);
+ assert(receive_errors >= 0);
+ assert(transmit_discards >= 0);
+ assert(transmit_errors >= 0);
+
+ if (measurement->errors == NULL)
+ {
+ EVEL_DEBUG("Adding Errors: %d, %d; %d, %d",
+ receive_discards,
+ receive_errors,
+ transmit_discards,
+ transmit_errors);
+ errors = malloc(sizeof(MEASUREMENT_ERRORS));
+ assert(errors != NULL);
+ memset(errors, 0, sizeof(MEASUREMENT_ERRORS));
+ errors->receive_discards = receive_discards;
+ errors->receive_errors = receive_errors;
+ errors->transmit_discards = transmit_discards;
+ errors->transmit_errors = transmit_errors;
+ measurement->errors = errors;
+ }
+ else
+ {
+ errors = measurement->errors;
+ EVEL_DEBUG("Ignoring attempt to add Errors: %d, %d; %d, %d\n"
+ "Errors already set: %d, %d; %d, %d",
+ receive_discards,
+ receive_errors,
+ transmit_discards,
+ transmit_errors,
+ errors->receive_discards,
+ errors->receive_errors,
+ errors->transmit_discards,
+ errors->transmit_errors);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Mean Request Latency property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param mean_request_latency The Mean Request Latency to be set.
+ *****************************************************************************/
+void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement,
+ double mean_request_latency)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(mean_request_latency >= 0.0);
+
+ evel_set_option_double(&measurement->mean_request_latency,
+ mean_request_latency,
+ "Mean Request Latency");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Memory Configured property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param memory_configured The Memory Configured to be set.
+ *****************************************************************************/
+void evel_measurement_mem_cfg_set(EVENT_MEASUREMENT * measurement,
+ double memory_configured)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(memory_configured >= 0.0);
+
+ evel_set_option_double(&measurement->memory_configured,
+ memory_configured,
+ "Memory Configured");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Memory Used property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param memory_used The Memory Used to be set.
+ *****************************************************************************/
+void evel_measurement_mem_used_set(EVENT_MEASUREMENT * measurement,
+ double memory_used)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(memory_used >= 0.0);
+
+ evel_set_option_double(&measurement->memory_used,
+ memory_used,
+ "Memory Used");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Request Rate property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param request_rate The Request Rate to be set.
+ *****************************************************************************/
+void evel_measurement_request_rate_set(EVENT_MEASUREMENT * measurement,
+ int request_rate)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(request_rate >= 0);
+
+ evel_set_option_int(&measurement->request_rate,
+ request_rate,
+ "Request Rate");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional CPU usage value name/value pair to the Measurement.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param id ASCIIZ string with the CPU's identifier.
+ * @param usage CPU utilization.
+ *****************************************************************************/
+void evel_measurement_cpu_use_add(EVENT_MEASUREMENT * measurement,
+ char * id, double usage)
+{
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(id != NULL);
+ assert(usage >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding id=%s usage=%lf", id, usage);
+ cpu_use = malloc(sizeof(MEASUREMENT_CPU_USE));
+ assert(cpu_use != NULL);
+ memset(cpu_use, 0, sizeof(MEASUREMENT_CPU_USE));
+ cpu_use->id = strdup(id);
+ cpu_use->usage = usage;
+ assert(cpu_use->id != NULL);
+
+ dlist_push_last(&measurement->cpu_usage, cpu_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional File System usage value name/value pair to the
+ * Measurement.
+ *
+ * The filesystem_name is null delimited ASCII string. The library takes a
+ * copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param filesystem_name ASCIIZ string with the file-system's UUID.
+ * @param block_configured Block storage configured.
+ * @param block_used Block storage in use.
+ * @param block_iops Block storage IOPS.
+ * @param ephemeral_configured Ephemeral storage configured.
+ * @param ephemeral_used Ephemeral storage in use.
+ * @param ephemeral_iops Ephemeral storage IOPS.
+ *****************************************************************************/
+void evel_measurement_fsys_use_add(EVENT_MEASUREMENT * measurement,
+ char * filesystem_name,
+ double block_configured,
+ double block_used,
+ int block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ int ephemeral_iops)
+{
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(filesystem_name != NULL);
+ assert(block_configured >= 0.0);
+ assert(block_used >= 0.0);
+ assert(block_iops >= 0);
+ assert(ephemeral_configured >= 0.0);
+ assert(ephemeral_used >= 0.0);
+ assert(ephemeral_iops >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding filesystem_name=%s", filesystem_name);
+ fsys_use = malloc(sizeof(MEASUREMENT_FSYS_USE));
+ assert(fsys_use != NULL);
+ memset(fsys_use, 0, sizeof(MEASUREMENT_FSYS_USE));
+ fsys_use->filesystem_name = strdup(filesystem_name);
+ fsys_use->block_configured = block_configured;
+ fsys_use->block_used = block_used;
+ fsys_use->block_iops = block_iops;
+ fsys_use->ephemeral_configured = block_configured;
+ fsys_use->ephemeral_used = ephemeral_used;
+ fsys_use->ephemeral_iops = ephemeral_iops;
+
+ dlist_push_last(&measurement->filesystem_usage, fsys_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement,
+ char * feature,
+ int utilization)
+{
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(feature != NULL);
+ assert(utilization >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization);
+ feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE));
+ assert(feature_use != NULL);
+ memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE));
+ feature_use->feature_id = strdup(feature);
+ assert(feature_use->feature_id != NULL);
+ feature_use->feature_utilization = utilization;
+
+ dlist_push_last(&measurement->feature_usage, feature_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the Measaurement.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param value ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement,
+ const char * const group,
+ const char * const name,
+ const char * const value)
+{
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(group != NULL);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ /***************************************************************************/
+ /* Allocate a container for the name/value pair. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s",
+ group, name, value);
+ custom_measurement = malloc(sizeof(CUSTOM_MEASUREMENT));
+ assert(custom_measurement != NULL);
+ memset(custom_measurement, 0, sizeof(CUSTOM_MEASUREMENT));
+ custom_measurement->name = strdup(name);
+ assert(custom_measurement->name != NULL);
+ custom_measurement->value = strdup(value);
+ assert(custom_measurement->value != NULL);
+
+ /***************************************************************************/
+ /* See if we have that group already. */
+ /***************************************************************************/
+ item = dlist_get_first(&measurement->additional_measurements);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ EVEL_DEBUG("Got measurement group %s", measurement_group->name);
+ if (strcmp(group, measurement_group->name) == 0)
+ {
+ EVEL_DEBUG("Found existing Measurement Group");
+ break;
+ }
+ item = dlist_get_next(item);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ if (item == NULL)
+ {
+ EVEL_DEBUG("Creating new Measurement Group");
+ measurement_group = malloc(sizeof(MEASUREMENT_GROUP));
+ assert(measurement_group != NULL);
+ memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP));
+ measurement_group->name = strdup(group);
+ assert(measurement_group->name != NULL);
+ dlist_initialize(&measurement_group->measurements);
+ dlist_push_last(&measurement->additional_measurements, measurement_group);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ dlist_push_last(&measurement_group->measurements, custom_measurement);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Codec usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param codec ASCIIZ string with the codec's name.
+ * @param utilization Number of codecs in use.
+ *****************************************************************************/
+void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement,
+ char * codec,
+ int utilization)
+{
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(codec != NULL);
+ assert(utilization >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Codec=%s Use=%d", codec, utilization);
+ codec_use = malloc(sizeof(MEASUREMENT_CODEC_USE));
+ assert(codec_use != NULL);
+ memset(codec_use, 0, sizeof(MEASUREMENT_CODEC_USE));
+ codec_use->codec_id = strdup(codec);
+ assert(codec_use->codec_id != NULL);
+ codec_use->number_in_use = utilization;
+
+ dlist_push_last(&measurement->codec_usage, codec_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Aggregate CPU Use property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param cpu_use The CPU use to set.
+ *****************************************************************************/
+void evel_measurement_agg_cpu_use_set(EVENT_MEASUREMENT * measurement,
+ double cpu_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(cpu_use >= 0.0);
+
+ evel_set_option_double(&measurement->aggregate_cpu_usage,
+ cpu_use,
+ "CPU Use");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Media Ports in Use property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param media_ports_in_use The media port usage to set.
+ *****************************************************************************/
+void evel_measurement_media_port_use_set(EVENT_MEASUREMENT * measurement,
+ int media_ports_in_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(media_ports_in_use >= 0);
+
+ evel_set_option_int(&measurement->media_ports_in_use,
+ media_ports_in_use,
+ "Media Ports In Use");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the VNFC Scaling Metric property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param scaling_metric The scaling metric to set.
+ *****************************************************************************/
+void evel_measurement_vnfc_scaling_metric_set(EVENT_MEASUREMENT * measurement,
+ double scaling_metric)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(scaling_metric >= 0.0);
+
+ evel_set_option_double(&measurement->vnfc_scaling_metric,
+ scaling_metric,
+ "VNFC Scaling Metric");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new Latency Bucket to be added to a Measurement event.
+ *
+ * @note The mandatory fields on the ::MEASUREMENT_LATENCY_BUCKET must be
+ * supplied to this factory function and are immutable once set.
+ * Optional fields have explicit setter functions, but again values
+ * may only be set once so that the ::MEASUREMENT_LATENCY_BUCKET has
+ * immutable properties.
+ *
+ * @param count Count of events in this bucket.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_LATENCY_BUCKET.
+ * If the structure is not used it must be released using free.
+ * @retval NULL Failed to create the Latency Bucket.
+ *****************************************************************************/
+MEASUREMENT_LATENCY_BUCKET * evel_new_meas_latency_bucket(const int count)
+{
+ MEASUREMENT_LATENCY_BUCKET * bucket;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(count >= 0);
+
+ /***************************************************************************/
+ /* Allocate, then set Mandatory Parameters. */
+ /***************************************************************************/
+ EVEL_DEBUG("Creating bucket, count = %d", count);
+ bucket = malloc(sizeof(MEASUREMENT_LATENCY_BUCKET));
+ assert(bucket != NULL);
+
+ /***************************************************************************/
+ /* Set Mandatory Parameters. */
+ /***************************************************************************/
+ bucket->count = count;
+
+ /***************************************************************************/
+ /* Initialize Optional Parameters. */
+ /***************************************************************************/
+ evel_init_option_double(&bucket->high_end);
+ evel_init_option_double(&bucket->low_end);
+
+ EVEL_EXIT();
+
+ return bucket;
+}
+
+/**************************************************************************//**
+ * Set the High End property of the Measurement Latency Bucket.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param bucket Pointer to the Measurement Latency Bucket.
+ * @param high_end High end of the bucket's range.
+ *****************************************************************************/
+void evel_meas_latency_bucket_high_end_set(
+ MEASUREMENT_LATENCY_BUCKET * const bucket,
+ const double high_end)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(high_end >= 0.0);
+ evel_set_option_double(&bucket->high_end, high_end, "High End");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Low End property of the Measurement Latency Bucket.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param bucket Pointer to the Measurement Latency Bucket.
+ * @param low_end Low end of the bucket's range.
+ *****************************************************************************/
+void evel_meas_latency_bucket_low_end_set(
+ MEASUREMENT_LATENCY_BUCKET * const bucket,
+ const double low_end)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(low_end >= 0.0);
+ evel_set_option_double(&bucket->low_end, low_end, "Low End");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional Measurement Latency Bucket to the specified event.
+ *
+ * @param measurement Pointer to the Measurement event.
+ * @param bucket Pointer to the Measurement Latency Bucket to add.
+ *****************************************************************************/
+void evel_meas_latency_bucket_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_LATENCY_BUCKET * const bucket)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(bucket != NULL);
+ dlist_push_last(&measurement->latency_distribution, bucket);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional Latency Distribution bucket to the Measurement.
+ *
+ * This function implements the previous API, purely for convenience.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param low_end Low end of the bucket's range.
+ * @param high_end High end of the bucket's range.
+ * @param count Count of events in this bucket.
+ *****************************************************************************/
+void evel_measurement_latency_add(EVENT_MEASUREMENT * const measurement,
+ const double low_end,
+ const double high_end,
+ const int count)
+{
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Trust the assertions in the underlying methods. */
+ /***************************************************************************/
+ bucket = evel_new_meas_latency_bucket(count);
+ evel_meas_latency_bucket_low_end_set(bucket, low_end);
+ evel_meas_latency_bucket_high_end_set(bucket, high_end);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new vNIC Use to be added to a Measurement event.
+ *
+ * @note The mandatory fields on the ::MEASUREMENT_VNIC_USE must be supplied
+ * to this factory function and are immutable once set. Optional
+ * fields have explicit setter functions, but again values may only be
+ * set once so that the ::MEASUREMENT_VNIC_USE has immutable
+ * properties.
+ *
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param packets_in Total packets received.
+ * @param packets_out Total packets transmitted.
+ * @param bytes_in Total bytes received.
+ * @param bytes_out Total bytes transmitted.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_USE.
+ * If the structure is not used it must be released using
+ * ::evel_free_measurement_vnic_use.
+ * @retval NULL Failed to create the vNIC Use.
+ *****************************************************************************/
+MEASUREMENT_VNIC_USE * evel_new_measurement_vnic_use(char * const vnic_id,
+ const int packets_in,
+ const int packets_out,
+ const int bytes_in,
+ const int bytes_out)
+{
+ MEASUREMENT_VNIC_USE * vnic_use;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vnic_id != NULL);
+ assert(packets_in >= 0);
+ assert(packets_out >= 0);
+ assert(bytes_in >= 0);
+ assert(bytes_out >= 0);
+
+ /***************************************************************************/
+ /* Allocate, then set Mandatory Parameters. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding VNIC ID=%s", vnic_id);
+ vnic_use = malloc(sizeof(MEASUREMENT_VNIC_USE));
+ assert(vnic_use != NULL);
+ vnic_use->vnic_id = strdup(vnic_id);
+ vnic_use->packets_in = packets_in;
+ vnic_use->packets_out = packets_out;
+ vnic_use->bytes_in = bytes_in;
+ vnic_use->bytes_out = bytes_out;
+
+ /***************************************************************************/
+ /* Initialize Optional Parameters. */
+ /***************************************************************************/
+ evel_init_option_int(&vnic_use->broadcast_packets_in);
+ evel_init_option_int(&vnic_use->broadcast_packets_out);
+ evel_init_option_int(&vnic_use->multicast_packets_in);
+ evel_init_option_int(&vnic_use->multicast_packets_out);
+ evel_init_option_int(&vnic_use->unicast_packets_in);
+ evel_init_option_int(&vnic_use->unicast_packets_out);
+
+ EVEL_EXIT();
+
+ return vnic_use;
+}
+
+/**************************************************************************//**
+ * Free a vNIC Use.
+ *
+ * Free off the ::MEASUREMENT_VNIC_USE supplied. Will free all the contained
+ * allocated memory.
+ *
+ * @note It does not free the vNIC Use itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement_vnic_use(MEASUREMENT_VNIC_USE * const vnic_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vnic_use != NULL);
+ assert(vnic_use->vnic_id != NULL);
+
+ /***************************************************************************/
+ /* Free the duplicated string. */
+ /***************************************************************************/
+ free(vnic_use->vnic_id);
+ vnic_use->vnic_id = NULL;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Broadcast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param broadcast_packets_in
+ * Broadcast packets received.
+ *****************************************************************************/
+void evel_vnic_use_bcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int broadcast_packets_in)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(broadcast_packets_in >= 0);
+
+ evel_set_option_int(&vnic_use->broadcast_packets_in,
+ broadcast_packets_in,
+ "Broadcast Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Broadcast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param broadcast_packets_out
+ * Broadcast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_bcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int broadcast_packets_out)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(broadcast_packets_out >= 0);
+
+ evel_set_option_int(&vnic_use->broadcast_packets_out,
+ broadcast_packets_out,
+ "Broadcast Packets Transmitted");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Multicast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param multicast_packets_in
+ * Multicast packets received.
+ *****************************************************************************/
+void evel_vnic_use_mcast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int multicast_packets_in)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(multicast_packets_in >= 0);
+
+ evel_set_option_int(&vnic_use->multicast_packets_in,
+ multicast_packets_in,
+ "Multicast Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Multicast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param multicast_packets_out
+ * Multicast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_mcast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int multicast_packets_out)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(multicast_packets_out >= 0);
+
+ evel_set_option_int(&vnic_use->multicast_packets_out,
+ multicast_packets_out,
+ "Multicast Packets Transmitted");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Unicast Packets Received property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param unicast_packets_in
+ * Unicast packets received.
+ *****************************************************************************/
+void evel_vnic_use_ucast_pkt_in_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int unicast_packets_in)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(unicast_packets_in >= 0);
+
+ evel_set_option_int(&vnic_use->unicast_packets_in,
+ unicast_packets_in,
+ "Unicast Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Unicast Packets Transmitted property of the vNIC Use.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param vnic_use Pointer to the vNIC Use.
+ * @param unicast_packets_out
+ * Unicast packets transmitted.
+ *****************************************************************************/
+void evel_vnic_use_ucast_pkt_out_set(MEASUREMENT_VNIC_USE * const vnic_use,
+ const int unicast_packets_out)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(unicast_packets_out >= 0);
+
+ evel_set_option_int(&vnic_use->unicast_packets_out,
+ unicast_packets_out,
+ "Unicast Packets Transmitted");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional vNIC Use to the specified Measurement event.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_use Pointer to the vNIC Use to add.
+ *****************************************************************************/
+void evel_meas_vnic_use_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_VNIC_USE * const vnic_use)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(vnic_use != NULL);
+
+ dlist_push_last(&measurement->vnic_usage, vnic_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional vNIC usage record Measurement.
+ *
+ * This function implements the previous API, purely for convenience.
+ *
+ * The ID is null delimited ASCII string. The library takes a copy so the
+ * caller does not have to preserve values after the function returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param packets_in Total packets received.
+ * @param packets_out Total packets transmitted.
+ * @param broadcast_packets_in Broadcast packets received.
+ * @param broadcast_packets_out Broadcast packets transmitted.
+ * @param bytes_in Total bytes received.
+ * @param bytes_out Total bytes transmitted.
+ * @param multicast_packets_in Multicast packets received.
+ * @param multicast_packets_out Multicast packets transmitted.
+ * @param unicast_packets_in Unicast packets received.
+ * @param unicast_packets_out Unicast packets transmitted.
+ *****************************************************************************/
+void evel_measurement_vnic_use_add(EVENT_MEASUREMENT * const measurement,
+ char * const vnic_id,
+ const int packets_in,
+ const int packets_out,
+ const int broadcast_packets_in,
+ const int broadcast_packets_out,
+ const int bytes_in,
+ const int bytes_out,
+ const int multicast_packets_in,
+ const int multicast_packets_out,
+ const int unicast_packets_in,
+ const int unicast_packets_out)
+{
+ MEASUREMENT_VNIC_USE * vnic_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Trust the assertions in the underlying methods. */
+ /***************************************************************************/
+ vnic_use = evel_new_measurement_vnic_use(vnic_id,
+ packets_in,
+ packets_out,
+ bytes_in,
+ bytes_out);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, broadcast_packets_in);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, broadcast_packets_out);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, multicast_packets_in);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, multicast_packets_out);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, unicast_packets_in);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, unicast_packets_out);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+}
+
+/**************************************************************************//**
+ * Encode the measurement as a JSON measurement.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_measurement(EVEL_JSON_BUFFER * jbuf,
+ EVENT_MEASUREMENT * event)
+{
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_USE * vnic_use = NULL;
+ MEASUREMENT_ERRORS * errors = NULL;
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ DLIST_ITEM * nested_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "measurementsForVfScalingFields");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_double(jbuf, "measurementInterval", event->measurement_interval);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ evel_enc_kv_opt_int(jbuf, "concurrentSessions", &event->concurrent_sessions);
+ evel_enc_kv_opt_int(jbuf, "configuredEntities", &event->configured_entities);
+
+ /***************************************************************************/
+ /* CPU Use list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "cpuUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->cpu_usage);
+ while (item != NULL)
+ {
+ cpu_use = (MEASUREMENT_CPU_USE*) item->item;
+ assert(cpu_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "cpuUsageArray",
+ cpu_use->id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "cpuIdentifier", cpu_use->id);
+ evel_enc_kv_double(jbuf, "percentUsage", cpu_use->usage);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Filesystem Usage list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "filesystemUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->filesystem_usage);
+ while (item != NULL)
+ {
+ fsys_use = (MEASUREMENT_FSYS_USE *) item->item;
+ assert(fsys_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "filesystemUsageArray",
+ fsys_use->filesystem_name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_double(
+ jbuf, "blockConfigured", fsys_use->block_configured);
+ evel_enc_kv_int(jbuf, "blockIops", fsys_use->block_iops);
+ evel_enc_kv_double(jbuf, "blockUsed", fsys_use->block_used);
+ evel_enc_kv_double(
+ jbuf, "ephemeralConfigured", fsys_use->ephemeral_configured);
+ evel_enc_kv_int(jbuf, "ephemeralIops", fsys_use->ephemeral_iops);
+ evel_enc_kv_double(jbuf, "ephemeralUsed", fsys_use->ephemeral_used);
+ evel_enc_kv_string(jbuf, "filesystemName", fsys_use->filesystem_name);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Latency distribution. */
+ /***************************************************************************/
+ item = dlist_get_first(&event->latency_distribution);
+ if ((item != NULL) &&
+ evel_json_open_opt_named_list(jbuf, "latencyDistribution"))
+ {
+ while (item != NULL)
+ {
+ bucket = (MEASUREMENT_LATENCY_BUCKET*) item->item;
+ assert(bucket != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_opt_double(
+ jbuf, "lowEndOfLatencyBucket", &bucket->low_end);
+ evel_enc_kv_opt_double(
+ jbuf, "highEndOfLatencyBucket", &bucket->high_end);
+ evel_enc_kv_int(jbuf, "countsInTheBucket", bucket->count);
+ evel_json_close_object(jbuf);
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ evel_enc_kv_opt_double(
+ jbuf, "meanRequestLatency", &event->mean_request_latency);
+ evel_enc_kv_opt_double(jbuf, "memoryConfigured", &event->memory_configured);
+ evel_enc_kv_opt_double(jbuf, "memoryUsed", &event->memory_used);
+ evel_enc_kv_opt_int(jbuf, "requestRate", &event->request_rate);
+
+ /***************************************************************************/
+ /* vNIC Usage */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "vNicUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->vnic_usage);
+ while (item != NULL)
+ {
+ vnic_use = (MEASUREMENT_VNIC_USE *) item->item;
+ assert(vnic_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "vNicUsageArray",
+ vnic_use->vnic_id))
+ {
+ evel_json_open_object(jbuf);
+
+ /*********************************************************************/
+ /* Mandatory fields. */
+ /*********************************************************************/
+ evel_enc_kv_int(jbuf, "bytesIn", vnic_use->bytes_in);
+ evel_enc_kv_int(jbuf, "bytesOut", vnic_use->bytes_out);
+ evel_enc_kv_int(jbuf, "packetsIn", vnic_use->packets_in);
+ evel_enc_kv_int(jbuf, "packetsOut", vnic_use->packets_out);
+ evel_enc_kv_string(jbuf, "vNicIdentifier", vnic_use->vnic_id);
+
+ /*********************************************************************/
+ /* Optional fields. */
+ /*********************************************************************/
+ evel_enc_kv_opt_int(
+ jbuf, "broadcastPacketsIn", &vnic_use->broadcast_packets_in);
+ evel_enc_kv_opt_int(
+ jbuf, "broadcastPacketsOut", &vnic_use->broadcast_packets_out);
+ evel_enc_kv_opt_int(
+ jbuf, "multicastPacketsIn", &vnic_use->multicast_packets_in);
+ evel_enc_kv_opt_int(
+ jbuf, "multicastPacketsOut", &vnic_use->multicast_packets_out);
+ evel_enc_kv_opt_int(
+ jbuf, "unicastPacketsIn", &vnic_use->unicast_packets_in);
+ evel_enc_kv_opt_int(
+ jbuf, "unicastPacketsOut", &vnic_use->unicast_packets_out);
+
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ evel_enc_kv_opt_double(
+ jbuf, "aggregateCpuUsage", &event->aggregate_cpu_usage);
+ evel_enc_kv_opt_int(
+ jbuf, "numberOfMediaPortsInUse", &event->media_ports_in_use);
+ evel_enc_kv_opt_double(
+ jbuf, "vnfcScalingMetric", &event->vnfc_scaling_metric);
+
+ /***************************************************************************/
+ /* Errors list. */
+ /***************************************************************************/
+ if ((event->errors != NULL) &&
+ evel_json_open_opt_named_object(jbuf, "errors"))
+ {
+ errors = event->errors;
+ evel_enc_kv_int(jbuf, "receiveDiscards", errors->receive_discards);
+ evel_enc_kv_int(jbuf, "receiveErrors", errors->receive_errors);
+ evel_enc_kv_int(jbuf, "transmitDiscards", errors->transmit_discards);
+ evel_enc_kv_int(jbuf, "transmitErrors", errors->transmit_errors);
+ evel_json_close_object(jbuf);
+ }
+
+ /***************************************************************************/
+ /* Feature Utilization list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "featureUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->feature_usage);
+ while (item != NULL)
+ {
+ feature_use = (MEASUREMENT_FEATURE_USE*) item->item;
+ assert(feature_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "featureUsageArray",
+ feature_use->feature_id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "featureIdentifier", feature_use->feature_id);
+ evel_enc_kv_int(
+ jbuf, "featureUtilization", feature_use->feature_utilization);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Codec Utilization list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "codecUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->codec_usage);
+ while (item != NULL)
+ {
+ codec_use = (MEASUREMENT_CODEC_USE*) item->item;
+ assert(codec_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "codecUsageArray",
+ codec_use->codec_id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "codecIdentifier", codec_use->codec_id);
+ evel_enc_kv_int(jbuf, "numberInUse", codec_use->number_in_use);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Additional Measurement Groups list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalMeasurements"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->additional_measurements);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalMeasurements",
+ measurement_group->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", measurement_group->name);
+ evel_json_open_opt_named_list(jbuf, "measurements");
+
+ /*********************************************************************/
+ /* Measurements list. */
+ /*********************************************************************/
+ nested_item = dlist_get_first(&measurement_group->measurements);
+ while (nested_item != NULL)
+ {
+ custom_measurement = (CUSTOM_MEASUREMENT *) nested_item->item;
+ assert(custom_measurement != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", custom_measurement->name);
+ evel_enc_kv_string(jbuf, "value", custom_measurement->value);
+ evel_json_close_object(jbuf);
+ nested_item = dlist_get_next(nested_item);
+ }
+ evel_json_close_list(jbuf);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Although optional, we always generate the version. Note that this */
+ /* closes the object, too. */
+ /***************************************************************************/
+ evel_enc_version(jbuf,
+ "measurementsForVfScalingVersion",
+ event->major_version,
+ event->major_version);
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Measurement.
+ *
+ * Free off the Measurement supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Measurement itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement(EVENT_MEASUREMENT * event)
+{
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_USE * vnic_use = NULL;
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * measurement = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ cpu_use = dlist_pop_last(&event->cpu_usage);
+ while (cpu_use != NULL)
+ {
+ EVEL_DEBUG("Freeing CPU use Info (%s)", cpu_use->id);
+ free(cpu_use->id);
+ free(cpu_use);
+ cpu_use = dlist_pop_last(&event->cpu_usage);
+ }
+
+ fsys_use = dlist_pop_last(&event->filesystem_usage);
+ while (fsys_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Filesystem Use info (%s)", fsys_use->filesystem_name);
+ free(fsys_use->filesystem_name);
+ free(fsys_use);
+ fsys_use = dlist_pop_last(&event->filesystem_usage);
+ }
+
+ bucket = dlist_pop_last(&event->latency_distribution);
+ while (bucket != NULL)
+ {
+ EVEL_DEBUG("Freeing Latency Bucket");
+ free(bucket);
+ bucket = dlist_pop_last(&event->latency_distribution);
+ }
+
+ vnic_use = dlist_pop_last(&event->vnic_usage);
+ while (vnic_use != NULL)
+ {
+ EVEL_DEBUG("Freeing vNIC use Info (%s)", vnic_use->vnic_id);
+ evel_free_measurement_vnic_use(vnic_use);
+ free(vnic_use);
+ vnic_use = dlist_pop_last(&event->vnic_usage);
+ }
+
+ codec_use = dlist_pop_last(&event->codec_usage);
+ while (codec_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Codec use Info (%s)", codec_use->codec_id);
+ free(codec_use->codec_id);
+ free(codec_use);
+ codec_use = dlist_pop_last(&event->codec_usage);
+ }
+
+ if (event->errors != NULL)
+ {
+ EVEL_DEBUG("Freeing Errors");
+ free(event->errors);
+ }
+
+ feature_use = dlist_pop_last(&event->feature_usage);
+ while (feature_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Feature use Info (%s)", feature_use->feature_id);
+ free(feature_use->feature_id);
+ free(feature_use);
+ feature_use = dlist_pop_last(&event->feature_usage);
+ }
+
+ measurement_group = dlist_pop_last(&event->additional_measurements);
+ while (measurement_group != NULL)
+ {
+ EVEL_DEBUG("Freeing Measurement Group (%s)", measurement_group->name);
+
+ measurement = dlist_pop_last(&measurement_group->measurements);
+ while (measurement != NULL)
+ {
+ EVEL_DEBUG("Freeing Measurement (%s)", measurement->name);
+ free(measurement->name);
+ free(measurement->value);
+ free(measurement);
+ measurement = dlist_pop_last(&measurement_group->measurements);
+ }
+ free(measurement_group->name);
+ free(measurement_group);
+ measurement_group = dlist_pop_last(&event->additional_measurements);
+ }
+
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_service.c b/vnfs/VES/code/evel_library/evel_service.c
new file mode 100644
index 00000000..03699517
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_service.c
@@ -0,0 +1,1313 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Service.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Service event.
+ *
+ * @note The mandatory fields on the Service must be supplied to
+ * this factory function and are immutable once set. Optional fields
+ * have explicit setter functions, but again values may only be set
+ * once so that the event has immutable properties.
+ * @param vendor_id The vendor id to encode in the event instance id.
+ * @param event_id The vendor event id to encode in the event instance id.
+ * @returns pointer to the newly manufactured ::EVENT_SERVICE. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_service.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SERVICE * evel_new_service(const char * const vendor_id,
+ const char * const event_id)
+{
+ EVENT_SERVICE * event = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vendor_id != NULL);
+ assert(event_id != NULL);
+
+ /***************************************************************************/
+ /* Allocate the Service event. */
+ /***************************************************************************/
+ event = malloc(sizeof(EVENT_SERVICE));
+ if (event == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(event, 0, sizeof(EVENT_SERVICE));
+ EVEL_DEBUG("New Service event is at %lp", event);
+
+ /***************************************************************************/
+ /* Initialize the header & the Service fields. */
+ /***************************************************************************/
+ evel_init_header(&event->header);
+ event->header.event_domain = EVEL_DOMAIN_SERVICE;
+ event->major_version = EVEL_SERVICE_MAJOR_VERSION;
+ event->minor_version = EVEL_SERVICE_MINOR_VERSION;
+ evel_init_event_instance_id(&event->instance_id, vendor_id, event_id);
+ evel_init_option_string(&event->correlator);
+ dlist_initialize(&event->additional_fields);
+ evel_init_option_string(&event->codec);
+ evel_init_option_string(&event->callee_side_codec);
+ evel_init_option_string(&event->caller_side_codec);
+ evel_init_option_string(&event->rtcp_data);
+ evel_init_option_string(&event->adjacency_name);
+ evel_init_option_string(&event->endpoint_description);
+ evel_init_option_int(&event->endpoint_jitter);
+ evel_init_option_int(&event->endpoint_rtp_oct_disc);
+ evel_init_option_int(&event->endpoint_rtp_oct_recv);
+ evel_init_option_int(&event->endpoint_rtp_oct_sent);
+ evel_init_option_int(&event->endpoint_rtp_pkt_disc);
+ evel_init_option_int(&event->endpoint_rtp_pkt_recv);
+ evel_init_option_int(&event->endpoint_rtp_pkt_sent);
+ evel_init_option_int(&event->local_jitter);
+ evel_init_option_int(&event->local_rtp_oct_disc);
+ evel_init_option_int(&event->local_rtp_oct_recv);
+ evel_init_option_int(&event->local_rtp_oct_sent);
+ evel_init_option_int(&event->local_rtp_pkt_disc);
+ evel_init_option_int(&event->local_rtp_pkt_recv);
+ evel_init_option_int(&event->local_rtp_pkt_sent);
+ evel_init_option_double(&event->mos_cqe);
+ evel_init_option_int(&event->packets_lost);
+ evel_init_option_double(&event->packet_loss_percent);
+ evel_init_option_int(&event->r_factor);
+ evel_init_option_int(&event->round_trip_delay);
+ evel_init_option_string(&event->phone_number);
+
+exit_label:
+
+ EVEL_EXIT();
+ return event;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_type_set(EVENT_SERVICE * const event,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_header_type_set(&event->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a name/value pair to the Service, under the additionalFields array.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param event Pointer to the Service event.
+ * @param name ASCIIZ string with the field's name. The caller does not
+ * need to preserve the value once the function returns.
+ * @param value ASCIIZ string with the field's value. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_addl_field_add(EVENT_SERVICE * const event,
+ const char * const name,
+ const char * const value)
+{
+ OTHER_FIELD * nv_pair = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ nv_pair = malloc(sizeof(OTHER_FIELD));
+ assert(nv_pair != NULL);
+ nv_pair->name = strdup(name);
+ nv_pair->value = strdup(value);
+ assert(nv_pair->name != NULL);
+ assert(nv_pair->value != NULL);
+
+ dlist_push_last(&event->additional_fields, nv_pair);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Product Id property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param product_id The vendor product id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_service_product_id_set(EVENT_SERVICE * const event,
+ const char * const product_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->instance_id.product_id,
+ product_id,
+ "Product Id");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Subsystem Id property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param subsystem_id The vendor subsystem id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_service_subsystem_id_set(EVENT_SERVICE * const event,
+ const char * const subsystem_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->instance_id.subsystem_id,
+ subsystem_id,
+ "Subsystem Id");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Friendly Name property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param friendly_name The vendor friendly name to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_service_friendly_name_set(EVENT_SERVICE * const event,
+ const char * const friendly_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->instance_id.event_friendly_name,
+ friendly_name,
+ "Friendly Name");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Correlator property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param correlator The correlator to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_correlator_set(EVENT_SERVICE * const event,
+ const char * const correlator)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->correlator,
+ correlator,
+ "Correlator");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Codec property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param codec The codec to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_codec_set(EVENT_SERVICE * const event,
+ const char * const codec)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->codec,
+ codec,
+ "Codec");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Callee Side Codec property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param codec The codec to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_callee_codec_set(EVENT_SERVICE * const event,
+ const char * const codec)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->callee_side_codec,
+ codec,
+ "Callee Side Codec");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Caller Side Codec property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param codec The codec to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_service_caller_codec_set(EVENT_SERVICE * const event,
+ const char * const codec)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->caller_side_codec,
+ codec,
+ "Caller Side Codec");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the RTCP Data property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtcp_data The RTCP Data to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_rtcp_data_set(EVENT_SERVICE * const event,
+ const char * const rtcp_data)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->rtcp_data,
+ rtcp_data,
+ "RTCP Data");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Adjacency Name property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param adjacency_name
+ * The adjacency name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_adjacency_name_set(EVENT_SERVICE * const event,
+ const char * const adjacency_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->adjacency_name,
+ adjacency_name,
+ "Adjacency Name");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Descriptor property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param endpoint_desc The endpoint descriptor to be set.
+ *****************************************************************************/
+void evel_service_endpoint_desc_set(
+ EVENT_SERVICE * const event,
+ const EVEL_SERVICE_ENDPOINT_DESC endpoint_desc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->endpoint_description,
+ evel_service_endpoint_desc(endpoint_desc),
+ "Endpoint Description");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Jitter property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param jitter The jitter to be set.
+ *****************************************************************************/
+void evel_service_endpoint_jitter_set(EVENT_SERVICE * const event,
+ const int jitter)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_jitter,
+ jitter,
+ "Endpoint Jitter");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Octets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_disc The discard count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_oct_disc_set(EVENT_SERVICE * const event,
+ const int rtp_oct_disc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_rtp_oct_disc,
+ rtp_oct_disc,
+ "Endpoint Rtp Octets Discarded");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Octets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_recv The receive count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_oct_recv_set(EVENT_SERVICE * const event,
+ const int rtp_oct_recv)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_rtp_oct_recv,
+ rtp_oct_recv,
+ "Endpoint Rtp Octets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Octets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_sent The send count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_oct_sent_set(EVENT_SERVICE * const event,
+ const int rtp_oct_sent)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_rtp_oct_sent,
+ rtp_oct_sent,
+ "Endpoint Rtp Octets Sent");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Packets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_disc The discard count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_pkt_disc_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_disc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_rtp_pkt_disc,
+ rtp_pkt_disc,
+ "Endpoint Rtp Packets Discarded");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Packets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_recv The receive count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_pkt_recv_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_recv)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_rtp_pkt_recv,
+ rtp_pkt_recv,
+ "Endpoint Rtp Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Endpoint Rtp Packets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_sent The send count.
+ *****************************************************************************/
+void evel_service_endpoint_rtp_pkt_sent_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_sent)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->endpoint_rtp_pkt_sent,
+ rtp_pkt_sent,
+ "Endpoint Rtp Packets Sent");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Jitter property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param jitter The jitter to be set.
+ *****************************************************************************/
+void evel_service_local_jitter_set(EVENT_SERVICE * const event,
+ const int jitter)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_jitter,
+ jitter,
+ "Local Jitter");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Rtp Octets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_disc The discard count.
+ *****************************************************************************/
+void evel_service_local_rtp_oct_disc_set(EVENT_SERVICE * const event,
+ const int rtp_oct_disc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_rtp_oct_disc,
+ rtp_oct_disc,
+ "Local Rtp Octets Discarded");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Rtp Octets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_recv The receive count.
+ *****************************************************************************/
+void evel_service_local_rtp_oct_recv_set(EVENT_SERVICE * const event,
+ const int rtp_oct_recv)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_rtp_oct_recv,
+ rtp_oct_recv,
+ "Local Rtp Octets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Rtp Octets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_oct_sent The send count.
+ *****************************************************************************/
+void evel_service_local_rtp_oct_sent_set(EVENT_SERVICE * const event,
+ const int rtp_oct_sent)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_rtp_oct_sent,
+ rtp_oct_sent,
+ "Local Rtp Octets Sent");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Rtp Packets Discarded property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_disc The discard count.
+ *****************************************************************************/
+void evel_service_local_rtp_pkt_disc_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_disc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_rtp_pkt_disc,
+ rtp_pkt_disc,
+ "Local Rtp Packets Discarded");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Rtp Packets Received property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_recv The receive count.
+ *****************************************************************************/
+void evel_service_local_rtp_pkt_recv_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_recv)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_rtp_pkt_recv,
+ rtp_pkt_recv,
+ "Local Rtp Packets Received");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Rtp Packets Sent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param rtp_pkt_sent The send count.
+ *****************************************************************************/
+void evel_service_local_rtp_pkt_sent_set(EVENT_SERVICE * const event,
+ const int rtp_pkt_sent)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->local_rtp_pkt_sent,
+ rtp_pkt_sent,
+ "Local Rtp Packets Sent");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Mos Cqe property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param mos_cqe The mosCqe to be set.
+ *****************************************************************************/
+void evel_service_mos_cqe_set(EVENT_SERVICE * const event,
+ const double mos_cqe)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_double(&event->mos_cqe,
+ mos_cqe,
+ "Mos Cqe");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Packets Lost property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param packets_lost The number of packets lost to be set.
+ *****************************************************************************/
+void evel_service_packets_lost_set(EVENT_SERVICE * const event,
+ const int packets_lost)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->packets_lost,
+ packets_lost,
+ "Packets Lost");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the packet Loss Percent property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param packet_loss_percent
+ * The packet loss in percent.
+ *****************************************************************************/
+void evel_service_packet_loss_percent_set(EVENT_SERVICE * const event,
+ const double packet_loss_percent)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_double(&event->packet_loss_percent,
+ packet_loss_percent,
+ "Packet Loss Percent");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the R Factor property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param r_factor The R Factor to be set.
+ *****************************************************************************/
+void evel_service_r_factor_set(EVENT_SERVICE * const event,
+ const int r_factor)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->r_factor,
+ r_factor,
+ "R Factor");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Round Trip Delay property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param round_trip_delay
+ * The Round trip delay to be set.
+ *****************************************************************************/
+void evel_service_round_trip_delay_set(EVENT_SERVICE * const event,
+ const int round_trip_delay)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_int(&event->round_trip_delay,
+ round_trip_delay,
+ "Round Trip Delay");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Phone Number property of the Service event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Service event.
+ * @param phone_number The Phone Number to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_service_phone_number_set(EVENT_SERVICE * const event,
+ const char * const phone_number)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+ evel_set_option_string(&event->phone_number,
+ phone_number,
+ "Phone Number");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Service in JSON according to AT&T's schema for the
+ * event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_service(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_SERVICE * const event)
+{
+ OTHER_FIELD * nv_pair = NULL;
+ DLIST_ITEM * dlist_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "serviceEventsFields");
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ evel_json_encode_instance_id(jbuf, &event->instance_id);
+ evel_enc_version(jbuf,
+ "serviceEventsFieldsVersion",
+ event->major_version,
+ event->minor_version);
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "correlator", &event->correlator);
+
+ /***************************************************************************/
+ /* Checkpoint, so that we can wind back if all fields are suppressed. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
+ {
+ bool added = false;
+
+ dlist_item = dlist_get_first(&event->additional_fields);
+ while (dlist_item != NULL)
+ {
+ nv_pair = (OTHER_FIELD *) dlist_item->item;
+ assert(nv_pair != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalFields",
+ nv_pair->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", nv_pair->name);
+ evel_enc_kv_string(jbuf, "value", nv_pair->value);
+ evel_json_close_object(jbuf);
+ added = true;
+ }
+ dlist_item = dlist_get_next(dlist_item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: codecSelected */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_object(jbuf, "codecSelected"))
+ {
+ bool added = false;
+ added |= evel_enc_kv_opt_string(jbuf,
+ "codec",
+ &event->codec);
+ evel_json_close_object(jbuf);
+
+ /*************************************************************************/
+ /* If the object is empty, rewind to before we opened it. */
+ /*************************************************************************/
+ if (!added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: codecSelectedTranscoding */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_object(jbuf, "codecSelectedTranscoding"))
+ {
+ bool added = false;
+ added |= evel_enc_kv_opt_string(jbuf,
+ "calleeSideCodec",
+ &event->callee_side_codec);
+ added |= evel_enc_kv_opt_string(jbuf,
+ "callerSideCodec",
+ &event->caller_side_codec);
+ evel_json_close_object(jbuf);
+
+ /*************************************************************************/
+ /* If the object is empty, rewind to before we opened it. */
+ /*************************************************************************/
+ if (!added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: midCallRtcp */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_object(jbuf, "midCallRtcp"))
+ {
+ bool added = false;
+ added |= evel_enc_kv_opt_string(jbuf,
+ "rtcpData",
+ &event->rtcp_data);
+ evel_json_close_object(jbuf);
+
+ /*************************************************************************/
+ /* If the object is empty, rewind to before we opened it. */
+ /*************************************************************************/
+ if (!added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: endOfCallVqmSummaries */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_object(jbuf, "endOfCallVqmSummaries"))
+ {
+ bool added = false;
+ added |= evel_enc_kv_opt_string(jbuf,
+ "adjacencyName",
+ &event->adjacency_name);
+ added |= evel_enc_kv_opt_string(jbuf,
+ "endpointDescription",
+ &event->endpoint_description);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointJitter",
+ &event->endpoint_jitter);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointRtpOctetsDiscarded",
+ &event->endpoint_rtp_oct_disc);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointRtpOctetsReceived",
+ &event->endpoint_rtp_oct_recv);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointRtpOctetsSent",
+ &event->endpoint_rtp_oct_sent);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointRtpPacketsDiscarded",
+ &event->endpoint_rtp_pkt_disc);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointRtpPacketsReceived",
+ &event->endpoint_rtp_pkt_recv);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "endpointRtpPacketsSent",
+ &event->endpoint_rtp_pkt_sent);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localJitter",
+ &event->local_jitter);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localRtpOctetsDiscarded",
+ &event->local_rtp_oct_disc);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localRtpOctetsReceived",
+ &event->local_rtp_oct_recv);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localRtpOctetsSent",
+ &event->local_rtp_oct_sent);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localRtpPacketsDiscarded",
+ &event->local_rtp_pkt_disc);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localRtpPacketsReceived",
+ &event->local_rtp_pkt_recv);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "localRtpPacketsSent",
+ &event->local_rtp_pkt_sent);
+ added |= evel_enc_kv_opt_double(jbuf,
+ "mosCqe",
+ &event->mos_cqe);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "packetsLost",
+ &event->packets_lost);
+ added |= evel_enc_kv_opt_double(jbuf,
+ "packetLossPercent",
+ &event->packet_loss_percent);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "rFactor",
+ &event->r_factor);
+ added |= evel_enc_kv_opt_int(jbuf,
+ "roundTripDelay",
+ &event->round_trip_delay);
+ evel_json_close_object(jbuf);
+
+ /*************************************************************************/
+ /* If the object is empty, rewind to before we opened it. */
+ /*************************************************************************/
+ if (!added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Optional fields within JSON equivalent object: marker */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_object(jbuf, "marker"))
+ {
+ bool added = false;
+ added |= evel_enc_kv_opt_string(jbuf, "phoneNumber", &event->phone_number);
+ evel_json_close_object(jbuf);
+
+ /*************************************************************************/
+ /* If the object is empty, rewind to before we opened it. */
+ /*************************************************************************/
+ if (!added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Service event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the event itself, since that may be part of a larger
+ * structure.
+ *****************************************************************************/
+void evel_free_service(EVENT_SERVICE * const event)
+{
+ OTHER_FIELD * nv_pair = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SERVICE);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ nv_pair = dlist_pop_last(&event->additional_fields);
+ while (nv_pair != NULL)
+ {
+ EVEL_DEBUG("Freeing Other Field (%s, %s)", nv_pair->name, nv_pair->value);
+ free(nv_pair->name);
+ free(nv_pair->value);
+ free(nv_pair);
+ nv_pair = dlist_pop_last(&event->additional_fields);
+ }
+ evel_free_option_string(&event->correlator);
+ evel_free_option_string(&event->codec);
+ evel_free_option_string(&event->callee_side_codec);
+ evel_free_option_string(&event->caller_side_codec);
+ evel_free_option_string(&event->rtcp_data);
+ evel_free_option_string(&event->adjacency_name);
+ evel_free_option_string(&event->endpoint_description);
+ evel_free_option_string(&event->phone_number);
+ evel_free_event_instance_id(&event->instance_id);
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_signaling.c b/vnfs/VES/code/evel_library/evel_signaling.c
new file mode 100644
index 00000000..102e89ef
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_signaling.c
@@ -0,0 +1,509 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Signaling.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Signaling event.
+ *
+ * @note The mandatory fields on the Signaling must be supplied to
+ * this factory function and are immutable once set. Optional fields
+ * have explicit setter functions, but again values may only be set
+ * once so that the event has immutable properties.
+ * @param vendor_id The vendor id to encode in the event instance id.
+ * @param event_id The vendor event id to encode in the event instance id.
+ * @returns pointer to the newly manufactured ::EVENT_SIGNALING. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_signaling.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SIGNALING * evel_new_signaling(const char * const vendor_id,
+ const char * const event_id)
+{
+ EVENT_SIGNALING * event = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vendor_id != NULL);
+ assert(event_id != NULL);
+
+ /***************************************************************************/
+ /* Allocate the Signaling event. */
+ /***************************************************************************/
+ event = malloc(sizeof(EVENT_SIGNALING));
+ if (event == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(event, 0, sizeof(EVENT_SIGNALING));
+ EVEL_DEBUG("New Signaling event is at %lp", event);
+
+ /***************************************************************************/
+ /* Initialize the header & the Signaling fields. */
+ /***************************************************************************/
+ evel_init_header(&event->header);
+ event->header.event_domain = EVEL_DOMAIN_SIGNALING;
+ event->major_version = EVEL_SIGNALING_MAJOR_VERSION;
+ event->minor_version = EVEL_SIGNALING_MINOR_VERSION;
+ evel_init_event_instance_id(&event->instance_id, vendor_id, event_id);
+ evel_init_option_string(&event->correlator);
+ evel_init_option_string(&event->local_ip_address);
+ evel_init_option_string(&event->local_port);
+ evel_init_option_string(&event->remote_ip_address);
+ evel_init_option_string(&event->remote_port);
+ evel_init_option_string(&event->compressed_sip);
+ evel_init_option_string(&event->summary_sip);
+
+exit_label:
+
+ EVEL_EXIT();
+ return event;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_type_set(EVENT_SIGNALING * const event,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ evel_header_type_set(&event->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Ip Address property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param local_ip_address
+ * The Local Ip Address to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_local_ip_address_set(EVENT_SIGNALING * const event,
+ const char * const local_ip_address)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ assert(local_ip_address != NULL);
+
+ evel_set_option_string(&event->local_ip_address,
+ local_ip_address,
+ "Local Ip Address");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Local Port property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param local_port The Local Port to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_local_port_set(EVENT_SIGNALING * const event,
+ const char * const local_port)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ assert(local_port != NULL);
+
+ evel_set_option_string(&event->local_port,
+ local_port,
+ "Local Port");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Remote Ip Address property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param remote_ip_address
+ * The Remote Ip Address to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_remote_ip_address_set(EVENT_SIGNALING * const event,
+ const char * const remote_ip_address)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ assert(remote_ip_address != NULL);
+
+ evel_set_option_string(&event->remote_ip_address,
+ remote_ip_address,
+ "Remote Ip Address");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Remote Port property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param remote_port The Remote Port to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_remote_port_set(EVENT_SIGNALING * const event,
+ const char * const remote_port)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ assert(remote_port != NULL);
+
+ evel_set_option_string(&event->remote_port,
+ remote_port,
+ "Remote Port");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Compressed SIP property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param compressed_sip
+ * The Compressed SIP to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_compressed_sip_set(EVENT_SIGNALING * const event,
+ const char * const compressed_sip)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ assert(compressed_sip != NULL);
+
+ evel_set_option_string(&event->compressed_sip,
+ compressed_sip,
+ "Compressed SIP");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Summary SIP property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param summary_sip The Summary SIP to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_summary_sip_set(EVENT_SIGNALING * const event,
+ const char * const summary_sip)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ assert(summary_sip != NULL);
+
+ evel_set_option_string(&event->summary_sip,
+ summary_sip,
+ "Summary SIP");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Product Id property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param product_id The vendor product id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_product_id_set(EVENT_SIGNALING * const event,
+ const char * const product_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ evel_set_option_string(&event->instance_id.product_id,
+ product_id,
+ "Product Id");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Subsystem Id property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param subsystem_id The vendor subsystem id to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_subsystem_id_set(EVENT_SIGNALING * const event,
+ const char * const subsystem_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ evel_set_option_string(&event->instance_id.subsystem_id,
+ subsystem_id,
+ "Subsystem Id");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Friendly Name property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param friendly_name The vendor friendly name to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_signaling_friendly_name_set(EVENT_SIGNALING * const event,
+ const char * const friendly_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ evel_set_option_string(&event->instance_id.event_friendly_name,
+ friendly_name,
+ "Friendly Name");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Correlator property of the Signaling event.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param event Pointer to the Signaling event.
+ * @param correlator The correlator to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_correlator_set(EVENT_SIGNALING * const event,
+ const char * const correlator)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+ evel_set_option_string(&event->correlator,
+ correlator,
+ "Correlator");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Signaling in JSON according to AT&T's schema for the
+ * event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_signaling(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_SIGNALING * const event)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "signalingFields");
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ evel_json_encode_instance_id(jbuf, &event->instance_id);
+ evel_enc_version(jbuf,
+ "signalingFieldsVersion",
+ event->major_version,
+ event->minor_version);
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "correlator", &event->correlator);
+ evel_enc_kv_opt_string(jbuf, "localIpAddress", &event->local_ip_address);
+ evel_enc_kv_opt_string(jbuf, "localPort", &event->local_port);
+ evel_enc_kv_opt_string(jbuf, "remoteIpAddress", &event->remote_ip_address);
+ evel_enc_kv_opt_string(jbuf, "remotePort", &event->remote_port);
+ evel_enc_kv_opt_string(jbuf, "compressedSip", &event->compressed_sip);
+ evel_enc_kv_opt_string(jbuf, "summarySip", &event->summary_sip);
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Signaling event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the event itself, since that may be part of a larger
+ * structure.
+ *****************************************************************************/
+void evel_free_signaling(EVENT_SIGNALING * const event)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIGNALING);
+
+ evel_free_header(&event->header);
+ evel_free_event_instance_id(&event->instance_id);
+ evel_free_option_string(&event->correlator);
+ evel_free_option_string(&event->local_ip_address);
+ evel_free_option_string(&event->local_port);
+ evel_free_option_string(&event->remote_ip_address);
+ evel_free_option_string(&event->remote_port);
+ evel_free_option_string(&event->compressed_sip);
+ evel_free_option_string(&event->summary_sip);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_state_change.c b/vnfs/VES/code/evel_library/evel_state_change.c
new file mode 100644
index 00000000..4b4671d6
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_state_change.c
@@ -0,0 +1,295 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the State Change.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new State Change event.
+ *
+ * @note The mandatory fields on the State Change must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once
+ * so that the State Change has immutable properties.
+ *
+ * @param new_state The new state of the reporting entity.
+ * @param old_state The old state of the reporting entity.
+ * @param interface The card or port name of the reporting entity.
+ *
+ * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE. If the
+ * event is not used it must be released using
+ * ::evel_free_state_change
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_STATE_CHANGE * evel_new_state_change(const EVEL_ENTITY_STATE new_state,
+ const EVEL_ENTITY_STATE old_state,
+ const char * const interface)
+{
+ EVENT_STATE_CHANGE * state_change = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(new_state < EVEL_MAX_ENTITY_STATES);
+ assert(old_state < EVEL_MAX_ENTITY_STATES);
+ assert(interface != NULL);
+
+ /***************************************************************************/
+ /* Allocate the State Change. */
+ /***************************************************************************/
+ state_change = malloc(sizeof(EVENT_STATE_CHANGE));
+ if (state_change == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(state_change, 0, sizeof(EVENT_STATE_CHANGE));
+ EVEL_DEBUG("New State Change is at %lp", state_change);
+
+ /***************************************************************************/
+ /* Initialize the header & the State Change fields. Optional string */
+ /* values are uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&state_change->header);
+ state_change->header.event_domain = EVEL_DOMAIN_STATE_CHANGE;
+ state_change->major_version = EVEL_STATE_CHANGE_MAJOR_VERSION;
+ state_change->minor_version = EVEL_STATE_CHANGE_MINOR_VERSION;
+ state_change->new_state = new_state;
+ state_change->old_state = old_state;
+ state_change->state_interface = strdup(interface);
+ dlist_initialize(&state_change->additional_fields);
+
+exit_label:
+ EVEL_EXIT();
+ return state_change;
+}
+
+/**************************************************************************//**
+ * Free a State Change.
+ *
+ * Free off the State Change supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the State Change itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_state_change(EVENT_STATE_CHANGE * const state_change)
+{
+ STATE_CHANGE_ADDL_FIELD * addl_field = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(state_change != NULL);
+ assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ addl_field = dlist_pop_last(&state_change->additional_fields);
+ while (addl_field != NULL)
+ {
+ EVEL_DEBUG("Freeing Additional Field (%s, %s)",
+ addl_field->name,
+ addl_field->value);
+ free(addl_field->name);
+ free(addl_field->value);
+ free(addl_field);
+ addl_field = dlist_pop_last(&state_change->additional_fields);
+ }
+ free(state_change->state_interface);
+ evel_free_header(&state_change->header);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the State Change.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_state_change_type_set(EVENT_STATE_CHANGE * const state_change,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(state_change != NULL);
+ assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
+ evel_header_type_set(&state_change->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional field name/value pair to the State Change.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE.
+ * @param name ASCIIZ string with the attribute's name. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ * @param value ASCIIZ string with the attribute's value. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_state_change_addl_field_add(EVENT_STATE_CHANGE * const state_change,
+ const char * const name,
+ const char * const value)
+{
+ STATE_CHANGE_ADDL_FIELD * addl_field = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(state_change != NULL);
+ assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ addl_field = malloc(sizeof(STATE_CHANGE_ADDL_FIELD));
+ assert(addl_field != NULL);
+ memset(addl_field, 0, sizeof(STATE_CHANGE_ADDL_FIELD));
+ addl_field->name = strdup(name);
+ addl_field->value = strdup(value);
+ assert(addl_field->name != NULL);
+ assert(addl_field->value != NULL);
+
+ dlist_push_last(&state_change->additional_fields, addl_field);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the state change as a JSON state change.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE to encode.
+ *****************************************************************************/
+void evel_json_encode_state_change(EVEL_JSON_BUFFER * jbuf,
+ EVENT_STATE_CHANGE * state_change)
+{
+ STATE_CHANGE_ADDL_FIELD * addl_field = NULL;
+ DLIST_ITEM * addl_field_item = NULL;
+ char * new_state;
+ char * old_state;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(state_change != NULL);
+ assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
+
+ new_state = evel_entity_state(state_change->new_state);
+ old_state = evel_entity_state(state_change->old_state);
+
+ evel_json_encode_header(jbuf, &state_change->header);
+ evel_json_open_named_object(jbuf, "stateChangeFields");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "newState", new_state);
+ evel_enc_kv_string(jbuf, "oldState", old_state);
+ evel_enc_kv_string(jbuf, "stateInterface", state_change->state_interface);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
+ {
+ bool item_added = false;
+
+ addl_field_item = dlist_get_first(&state_change->additional_fields);
+ while (addl_field_item != NULL)
+ {
+ addl_field = (STATE_CHANGE_ADDL_FIELD *) addl_field_item->item;
+ assert(addl_field != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalFields",
+ addl_field->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", addl_field->name);
+ evel_enc_kv_string(jbuf, "value", addl_field->value);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ addl_field_item = dlist_get_next(addl_field_item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ evel_enc_version(jbuf,
+ "stateChangeFieldsVersion",
+ state_change->major_version,
+ state_change->minor_version);
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_strings.c b/vnfs/VES/code/evel_library/evel_strings.c
new file mode 100644
index 00000000..1f410cb1
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_strings.c
@@ -0,0 +1,477 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions to convert common enum types to strings.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Map an ::EVEL_COUNTER_CRITICALITIES enum value to the equivalent string.
+ *
+ * @param criticality The criticality to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_criticality(const EVEL_COUNTER_CRITICALITIES criticality)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (criticality)
+ {
+ case EVEL_COUNTER_CRITICALITY_CRIT:
+ result = "CRIT";
+ break;
+
+ case EVEL_COUNTER_CRITICALITY_MAJ:
+ result = "MAJ";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected counter criticality %d", criticality);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_SEVERITIES enum value to the equivalent string.
+ *
+ * @param severity The severity to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_severity(const EVEL_SEVERITIES severity)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (severity)
+ {
+ case EVEL_SEVERITY_CRITICAL:
+ result = "CRITICAL";
+ break;
+
+ case EVEL_SEVERITY_MAJOR:
+ result = "MAJOR";
+ break;
+
+ case EVEL_SEVERITY_MINOR:
+ result = "MINOR";
+ break;
+
+ case EVEL_SEVERITY_WARNING:
+ result = "WARNING";
+ break;
+
+ case EVEL_SEVERITY_NORMAL:
+ result = "NORMAL";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected event severity %d", severity);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_ALERT_ACTIONS enum value to the equivalent string.
+ *
+ * @param alert_action The alert_action to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_alert_action(const EVEL_ALERT_ACTIONS alert_action)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (alert_action)
+ {
+ case EVEL_ALERT_ACTION_CLEAR:
+ result = "CLEAR";
+ break;
+
+ case EVEL_ALERT_ACTION_CONT:
+ result = "CONT";
+ break;
+
+ case EVEL_ALERT_ACTION_SET:
+ result = "SET";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected alert action %d", alert_action);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_ALERT_TYPES enum value to the equivalent string.
+ *
+ * @param alert_type The alert_type to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_alert_type(const EVEL_ALERT_TYPES alert_type)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (alert_type)
+ {
+ case EVEL_ALERT_TYPE_CARD:
+ result = "CARD-ANOMALY";
+ break;
+
+ case EVEL_ALERT_TYPE_ELEMENT:
+ result = "ELEMENT-ANOMALY";
+ break;
+
+ case EVEL_ALERT_TYPE_INTERFACE:
+ result = "INTERFACE-ANOMALY";
+ break;
+
+ case EVEL_ALERT_TYPE_SERVICE:
+ result = "SERVICE-ANOMALY";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected alert type %d", alert_type);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_EVENT_DOMAINS enum value to the equivalent string.
+ *
+ * @param domain The domain to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_event_domain(const EVEL_EVENT_DOMAINS domain)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (domain)
+ {
+ case EVEL_DOMAIN_HEARTBEAT:
+ result = "heartbeat";
+ break;
+
+ case EVEL_DOMAIN_FAULT:
+ result = "fault";
+ break;
+
+ case EVEL_DOMAIN_MEASUREMENT:
+ result = "measurementsForVfScaling";
+ break;
+
+ case EVEL_DOMAIN_REPORT:
+ result = "measurementsForVfReporting";
+ break;
+
+ case EVEL_DOMAIN_MOBILE_FLOW:
+ result = "mobileFlow";
+ break;
+
+ case EVEL_DOMAIN_SERVICE:
+ result = "serviceEvents";
+ break;
+
+ case EVEL_DOMAIN_SIGNALING:
+ result = "signaling";
+ break;
+
+ case EVEL_DOMAIN_STATE_CHANGE:
+ result = "stateChange";
+ break;
+
+ case EVEL_DOMAIN_SYSLOG:
+ result = "syslog";
+ break;
+
+ case EVEL_DOMAIN_OTHER:
+ result = "other";
+ break;
+
+ default:
+ result = NULL;
+ EVEL_ERROR("Unexpected domain %d", domain);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_EVENT_PRIORITIES enum value to the equivalent string.
+ *
+ * @param priority The priority to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_event_priority(const EVEL_EVENT_PRIORITIES priority)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (priority)
+ {
+ case EVEL_PRIORITY_HIGH:
+ result = "High";
+ break;
+
+ case EVEL_PRIORITY_MEDIUM:
+ result = "Medium";
+ break;
+
+ case EVEL_PRIORITY_NORMAL:
+ result = "Normal";
+ break;
+
+ case EVEL_PRIORITY_LOW:
+ result = "Low";
+ break;
+
+ default:
+ result = NULL;
+ EVEL_ERROR("Unexpected priority %d", priority);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_SOURCE_TYPES enum value to the equivalent string.
+ *
+ * @param source_type The source type to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_source_type(const EVEL_SOURCE_TYPES source_type)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (source_type)
+ {
+ case EVEL_SOURCE_OTHER:
+ result = "other";
+ break;
+
+ case EVEL_SOURCE_ROUTER:
+ result = "router";
+ break;
+
+ case EVEL_SOURCE_SWITCH:
+ result = "switch";
+ break;
+
+ case EVEL_SOURCE_HOST:
+ result = "host";
+ break;
+
+ case EVEL_SOURCE_CARD:
+ result = "card";
+ break;
+
+ case EVEL_SOURCE_PORT:
+ result = "port";
+ break;
+
+ case EVEL_SOURCE_SLOT_THRESHOLD:
+ result = "slotThreshold";
+ break;
+
+ case EVEL_SOURCE_PORT_THRESHOLD:
+ result = "portThreshold";
+ break;
+
+ case EVEL_SOURCE_VIRTUAL_MACHINE:
+ result = "virtualMachine";
+ break;
+
+ case EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION:
+ result = "virtualNetworkFunction";
+ break;
+
+ default:
+ result = NULL;
+ EVEL_ERROR("Unexpected Event Source Type %d", (int) source_type);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_VF_STATUSES enum value to the equivalent string.
+ *
+ * @param vf_status The vf_status to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_vf_status(const EVEL_VF_STATUSES vf_status)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (vf_status)
+ {
+ case EVEL_VF_STATUS_ACTIVE:
+ result = "Active";
+ break;
+
+ case EVEL_VF_STATUS_IDLE:
+ result = "Idle";
+ break;
+
+ case EVEL_VF_STATUS_PREP_TERMINATE:
+ result = "Preparing to terminate";
+ break;
+
+ case EVEL_VF_STATUS_READY_TERMINATE:
+ result = "Ready to terminate";
+ break;
+
+ case EVEL_VF_STATUS_REQ_TERMINATE:
+ result = "Requesting termination";
+ break;
+
+ default:
+ result = NULL;
+ EVEL_ERROR("Unexpected VF Status %d", vf_status);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Convert a ::EVEL_ENTITY_STATE to it's string form for JSON encoding.
+ *
+ * @param state The entity state to encode.
+ *
+ * @returns the corresponding string
+ *****************************************************************************/
+char * evel_entity_state(const EVEL_ENTITY_STATE state)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (state)
+ {
+ case EVEL_ENTITY_STATE_IN_SERVICE:
+ result = "inService";
+ break;
+
+ case EVEL_ENTITY_STATE_MAINTENANCE:
+ result = "maintenance";
+ break;
+
+ case EVEL_ENTITY_STATE_OUT_OF_SERVICE:
+ result = "outOfService";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected entity state %d", state);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Convert a ::EVEL_SERVICE_ENDPOINT_DESC to string form for JSON encoding.
+ *
+ * @param endpoint_desc endpoint description to encode.
+ *
+ * @returns the corresponding string
+ *****************************************************************************/
+char * evel_service_endpoint_desc(const EVEL_ENTITY_STATE endpoint_desc)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (endpoint_desc)
+ {
+ case EVEL_SERVICE_ENDPOINT_CALLEE:
+ result = "Callee";
+ break;
+
+ case EVEL_SERVICE_ENDPOINT_CALLER:
+ result = "Caller";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected endpoint description %d", endpoint_desc);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
diff --git a/vnfs/VES/code/evel_library/evel_syslog.c b/vnfs/VES/code/evel_library/evel_syslog.c
new file mode 100644
index 00000000..64a94886
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_syslog.c
@@ -0,0 +1,500 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Syslog.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Syslog event.
+ *
+ * @note The mandatory fields on the Syslog must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Syslog has immutable properties.
+ * @param event_source_type The type of Syslog event source.
+ * @param syslog_msg The Syslog event message.
+ * @param syslog_tag The messgaeId identifying the type of message.
+ * @returns pointer to the newly manufactured ::EVENT_SYSLOG. If the event is
+ * not used (i.e. posted) it must be released using
+ * ::evel_free_syslog.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SYSLOG * evel_new_syslog(EVEL_SOURCE_TYPES event_source_type,
+ const char * const syslog_msg,
+ const char * const syslog_tag)
+{
+ EVENT_SYSLOG * syslog = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event_source_type < EVEL_MAX_SOURCE_TYPES);
+ assert(syslog_msg != NULL);
+ assert(syslog_tag != NULL);
+
+ /***************************************************************************/
+ /* Allocate the Syslog. */
+ /***************************************************************************/
+ syslog = malloc(sizeof(EVENT_SYSLOG));
+ if (syslog == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(syslog, 0, sizeof(EVENT_SYSLOG));
+ EVEL_DEBUG("New Syslog is at %lp", syslog);
+
+ /***************************************************************************/
+ /* Initialize the header & the Syslog fields. Optional string values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&syslog->header);
+ syslog->header.event_domain = EVEL_DOMAIN_SYSLOG;
+ syslog->major_version = EVEL_SYSLOG_MAJOR_VERSION;
+ syslog->minor_version = EVEL_SYSLOG_MINOR_VERSION;
+ syslog->event_source_type = event_source_type;
+ syslog->syslog_msg = strdup(syslog_msg);
+ syslog->syslog_tag = strdup(syslog_tag);
+ dlist_initialize(&syslog->additional_fields);
+ evel_init_option_int(&syslog->syslog_facility);
+ evel_init_option_int(&syslog->syslog_proc_id);
+ evel_init_option_int(&syslog->syslog_ver);
+ evel_init_option_string(&syslog->event_source_host);
+ evel_init_option_string(&syslog->syslog_proc);
+ evel_init_option_string(&syslog->syslog_s_data);
+
+exit_label:
+ EVEL_EXIT();
+ return syslog;
+}
+
+/**************************************************************************//**
+ * Set the Event Type property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the syslog.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_type_set(EVENT_SYSLOG * syslog,
+ const char * const type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ evel_header_type_set(&syslog->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the Syslog.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param syslog Pointer to the syslog.
+ * @param name ASCIIZ string with the attribute's name. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ * @param value ASCIIZ string with the attribute's value. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_addl_field_add(EVENT_SYSLOG * syslog,
+ char * name,
+ char * value)
+{
+ SYSLOG_ADDL_FIELD * addl_field = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ addl_field = malloc(sizeof(SYSLOG_ADDL_FIELD));
+ assert(addl_field != NULL);
+ memset(addl_field, 0, sizeof(SYSLOG_ADDL_FIELD));
+ addl_field->name = strdup(name);
+ addl_field->value = strdup(value);
+ assert(addl_field->name != NULL);
+ assert(addl_field->value != NULL);
+
+ dlist_push_last(&syslog->additional_fields, addl_field);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Event Source Host property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param host The Event Source Host to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_event_source_host_set(EVENT_SYSLOG * syslog,
+ const char * const host)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(host != NULL);
+
+ evel_set_option_string(&syslog->event_source_host,
+ host,
+ "Event Source Host");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Facility property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param facility The Syslog Facility to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_facility_set(EVENT_SYSLOG * syslog,
+ EVEL_SYSLOG_FACILITIES facility)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(facility < EVEL_MAX_SYSLOG_FACILITIES);
+
+ evel_set_option_int(&syslog->syslog_facility,
+ facility,
+ "Facility");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Process property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param proc The Process to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_syslog_proc_set(EVENT_SYSLOG * syslog, const char * const proc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(proc != NULL);
+
+ evel_set_option_string(&syslog->syslog_proc, proc, "Process");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Process ID property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param proc_id The Process ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_syslog_proc_id_set(EVENT_SYSLOG * syslog, int proc_id)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(proc_id > 0);
+
+ evel_set_option_int(&syslog->syslog_proc_id,
+ proc_id,
+ "Process ID");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Version property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param version The Version to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_syslog_version_set(EVENT_SYSLOG * syslog, int version)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(version >= 0);
+
+ evel_set_option_int(&syslog->syslog_ver,
+ version,
+ "Version");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Structured Data property of the Syslog.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param syslog Pointer to the Syslog.
+ * @param s_data The Structured Data to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_s_data_set(EVENT_SYSLOG * syslog, const char * const s_data)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(s_data != NULL);
+
+ evel_set_option_string(&syslog->syslog_s_data,
+ s_data,
+ "Structured Data");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Syslog in JSON according to AT&T's schema for the event type.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
+ * @param event Pointer to the ::EVENT_HEADER to encode.
+ *****************************************************************************/
+void evel_json_encode_syslog(EVEL_JSON_BUFFER * jbuf,
+ EVENT_SYSLOG * event)
+{
+ char * event_source_type;
+ SYSLOG_ADDL_FIELD * addl_field = NULL;
+ DLIST_ITEM * addl_field_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG);
+
+ event_source_type = evel_source_type(event->event_source_type);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "syslogFields");
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "eventSourceType", event_source_type);
+ evel_enc_kv_string(jbuf, "syslogMsg", event->syslog_msg);
+ evel_enc_kv_string(jbuf, "syslogTag", event->syslog_tag);
+ evel_enc_version(
+ jbuf, "syslogFieldsVersion", event->major_version, event->minor_version);
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
+ {
+ bool item_added = false;
+
+ addl_field_item = dlist_get_first(&event->additional_fields);
+ while (addl_field_item != NULL)
+ {
+ addl_field = (SYSLOG_ADDL_FIELD *) addl_field_item->item;
+ assert(addl_field != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalFields",
+ addl_field->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", addl_field->name);
+ evel_enc_kv_string(jbuf, "value", addl_field->value);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ addl_field_item = dlist_get_next(addl_field_item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ evel_enc_kv_opt_string(jbuf, "eventSourceHost", &event->event_source_host);
+ evel_enc_kv_opt_int(jbuf, "syslogFacility", &event->syslog_facility);
+ evel_enc_kv_opt_string(jbuf, "syslogProc", &event->syslog_proc);
+ evel_enc_kv_opt_int(jbuf, "syslogProcId", &event->syslog_proc_id);
+ evel_enc_kv_opt_string(jbuf, "syslogSData", &event->syslog_s_data);
+ evel_enc_kv_opt_int(jbuf, "syslogVer", &event->syslog_ver);
+ evel_json_close_object(jbuf);
+
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_KERNEL == 0);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_USER == 1);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_MAIL == 2);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SYSTEM_DAEMON == 3);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SECURITY_AUTH == 4);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_INTERNAL == 5);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LINE_PRINTER == 6);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_NETWORK_NEWS == 7);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_UUCP == 8);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_CLOCK_DAEMON == 9);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SECURITY_AUTH2 == 10);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_FTP_DAEMON == 11);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_NTP == 12);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOG_AUDIT == 13);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOG_ALERT == 14);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_CLOCK_DAEMON2 == 15);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL0 == 16);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL1 == 17);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL2 == 18);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL3 == 19);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL4 == 20);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL5 == 21);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL6 == 22);
+ EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL7 == 23);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Syslog.
+ *
+ * Free off the Syslog supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Syslog itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_syslog(EVENT_SYSLOG * event)
+{
+ SYSLOG_ADDL_FIELD * addl_field = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ addl_field = dlist_pop_last(&event->additional_fields);
+ while (addl_field != NULL)
+ {
+ EVEL_DEBUG("Freeing Additional Field (%s, %s)",
+ addl_field->name,
+ addl_field->value);
+ free(addl_field->name);
+ free(addl_field->value);
+ free(addl_field);
+ addl_field = dlist_pop_last(&event->additional_fields);
+ }
+
+ evel_free_option_string(&event->event_source_host);
+ free(event->syslog_msg);
+ evel_free_option_string(&event->syslog_proc);
+ evel_free_option_string(&event->syslog_s_data);
+ free(event->syslog_tag);
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/vnfs/VES/code/evel_library/evel_throttle.c b/vnfs/VES/code/evel_library/evel_throttle.c
new file mode 100644
index 00000000..866ece01
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_throttle.c
@@ -0,0 +1,2114 @@
+/**************************************************************************//**
+ * @file
+ * Event Manager
+ *
+ * Simple event manager that is responsible for taking events (Heartbeats,
+ * Faults and Measurements) from the ring-buffer and posting them to the API.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <pthread.h>
+#include <search.h>
+
+#include "evel_throttle.h"
+
+/*****************************************************************************/
+/* The Event Throttling State for all domains, indexed by */
+/* ::EVEL_EVENT_DOMAINS, corresponding to JSON eventDomain. */
+/* */
+/* A given domain is in a throttled state if ::evel_throttle_spec is */
+/* non-NULL. */
+/*****************************************************************************/
+static EVEL_THROTTLE_SPEC * evel_throttle_spec[EVEL_MAX_DOMAINS];
+
+/*****************************************************************************/
+/* The current measurement interval. Default: MEASUREMENT_INTERVAL_UKNOWN. */
+/* Must be protected by evel_measurement_interval_mutex. */
+/*****************************************************************************/
+static int evel_measurement_interval;
+
+/*****************************************************************************/
+/* Mutex protecting evel_measurement_interval from contention between an */
+/* EVEL client reading it, and the EVEL event handler updating it. */
+/*****************************************************************************/
+static pthread_mutex_t evel_measurement_interval_mutex;
+
+/*****************************************************************************/
+/* Flag stating that we have received a "provideThrottlingState" command. */
+/* Set during JSON processing and cleared on sending the throttling state. */
+/*****************************************************************************/
+static bool evel_provide_throttling_state;
+
+/*****************************************************************************/
+/* Holder for the "commandType" value during JSON processing. */
+/*****************************************************************************/
+static char * evel_command_type_value;
+
+/*****************************************************************************/
+/* Holder for the "measurementInterval" value during JSON processing. */
+/*****************************************************************************/
+static char * evel_measurement_interval_value;
+
+/*****************************************************************************/
+/* Holder for the "eventDomain" value during JSON processing. */
+/*****************************************************************************/
+static char * evel_throttle_spec_domain_value;
+
+/*****************************************************************************/
+/* Decoded version of ::evel_throttle_spec_domain_value. */
+/*****************************************************************************/
+static EVEL_EVENT_DOMAINS evel_throttle_spec_domain;
+
+/*****************************************************************************/
+/* During JSON processing of a single throttling specification, we collect */
+/* parameters in this working ::EVEL_THROTTLE_SPEC */
+/*****************************************************************************/
+static EVEL_THROTTLE_SPEC * evel_temp_throttle;
+
+/*****************************************************************************/
+/* State tracking our progress through the command list */
+/*****************************************************************************/
+EVEL_JSON_COMMAND_STATE evel_json_command_state;
+
+/*****************************************************************************/
+/* Debug strings for ::EVEL_JSON_COMMAND_STATE. */
+/*****************************************************************************/
+static const char * const evel_jcs_strings[EVEL_JCS_MAX] = {
+ "EVEL_JCS_START",
+ "EVEL_JCS_COMMAND_LIST",
+ "EVEL_JCS_COMMAND_LIST_ENTRY",
+ "EVEL_JCS_COMMAND",
+ "EVEL_JCS_SPEC",
+ "EVEL_JCS_FIELD_NAMES",
+ "EVEL_JCS_PAIRS_LIST",
+ "EVEL_JCS_PAIRS_LIST_ENTRY",
+ "EVEL_JCS_NV_PAIR_NAMES"
+};
+
+/*****************************************************************************/
+/* Debug strings for JSON token type. */
+/*****************************************************************************/
+#define JSON_TOKEN_TYPES (JSMN_PRIMITIVE + 1)
+static const char * const evel_json_token_strings[JSON_TOKEN_TYPES] = {
+ "JSMN_UNDEFINED",
+ "JSMN_OBJECT",
+ "JSMN_ARRAY",
+ "JSMN_STRING",
+ "JSMN_PRIMITIVE"
+};
+
+/*****************************************************************************/
+/* Debug strings for JSON domains. */
+/*****************************************************************************/
+static const char * evel_domain_strings[EVEL_MAX_DOMAINS] = {
+ "internal",
+ "heartbeat",
+ "fault",
+ "measurementsForVfScaling",
+ "mobileFlow",
+ "report",
+ "serviceEvents",
+ "signaling",
+ "stateChange",
+ "syslog",
+ "other"
+};
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void evel_throttle_finalize(EVEL_THROTTLE_SPEC * throttle_spec);
+static struct hsearch_data * evel_throttle_hash_create(DLIST * hash_keys);
+static void evel_throttle_free(EVEL_THROTTLE_SPEC * throttle_spec);
+static void evel_throttle_free_nv_pair(EVEL_SUPPRESSED_NV_PAIRS * nv_pairs);
+static void evel_init_json_stack(EVEL_JSON_STACK * json_stack,
+ const MEMORY_CHUNK * const chunk);
+static bool evel_stack_push(EVEL_JSON_STACK * const json_stack,
+ const int num_required,
+ const EVEL_JSON_STATE new_state);
+static void evel_stack_pop(EVEL_JSON_STACK * const json_stack);
+static void evel_stack_cleanup(EVEL_JSON_STACK * const json_stack);
+static char * evel_stack_strdup(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const token);
+static void evel_stack_store_key(EVEL_JSON_STACK * const json_stack,
+ const jsmntok_t * const token);
+static void evel_stack_store_value(EVEL_JSON_STACK * const json_stack,
+ const jsmntok_t * const token);
+static void evel_stack_store_item(EVEL_JSON_STACK * const json_stack,
+ const jsmntok_t * const token);
+static void evel_set_command_state(const EVEL_JSON_COMMAND_STATE new_state);
+static void evel_debug_token(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const token);
+static void evel_command_list_response(MEMORY_CHUNK * const post);
+static int evel_json_encode_throttle(char * const json, const int max_size);
+static int evel_json_encode_throttle_spec(char * const json,
+ const int max_size,
+ const EVEL_EVENT_DOMAINS domain);
+static int evel_json_encode_nv_pairs(char * const json,
+ const int max_size,
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs);
+static void evel_close_command();
+static void evel_open_command();
+static void evel_set_throttling_spec();
+static void evel_set_measurement_interval();
+static void evel_open_throttle_spec();
+static void evel_close_throttle_spec();
+static EVEL_EVENT_DOMAINS evel_decode_domain(char * domain_value);
+static void evel_open_nv_pairs_list_entry();
+static void evel_close_nv_pairs_list_entry();
+static void evel_store_nv_pair_field_name(char * const value);
+static void evel_store_nv_pair_name(char * const item);
+static void evel_store_suppressed_field_name(char * const item);
+static EVEL_SUPPRESSED_NV_PAIRS * evel_get_last_nv_pairs();
+
+/**************************************************************************//**
+ * Return the current measurement interval provided by the Event Listener.
+ *
+ * @returns The current measurement interval
+ * @retval EVEL_MEASUREMENT_INTERVAL_UKNOWN (0) - interval has not been
+ * specified
+ *****************************************************************************/
+int evel_get_measurement_interval()
+{
+ int result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Lock, read, unlock. */
+ /***************************************************************************/
+ pthread_mutex_lock(&evel_measurement_interval_mutex);
+ result = evel_measurement_interval;
+ pthread_mutex_unlock(&evel_measurement_interval_mutex);
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Return the ::EVEL_THROTTLE_SPEC for a given domain.
+ *
+ * @param domain The domain for which to return state.
+ *****************************************************************************/
+EVEL_THROTTLE_SPEC * evel_get_throttle_spec(EVEL_EVENT_DOMAINS domain)
+{
+ EVEL_THROTTLE_SPEC * result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(domain < EVEL_MAX_DOMAINS);
+
+ result = evel_throttle_spec[domain];
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Determine whether a field_name should be suppressed.
+ *
+ * @param throttle_spec Throttle specification for the domain being encoded.
+ * @param field_name The field name to encoded or suppress.
+ * @return true if the field_name should be suppressed, false otherwise.
+ *****************************************************************************/
+bool evel_throttle_suppress_field(EVEL_THROTTLE_SPEC * throttle_spec,
+ const char * const field_name)
+{
+ bool suppress = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(field_name != NULL);
+
+ /***************************************************************************/
+ /* If the throttle spec and hash table exist, query the field_names table. */
+ /***************************************************************************/
+ if ((throttle_spec != NULL) && (throttle_spec->hash_field_names != NULL))
+ {
+ ENTRY hash_query;
+ ENTRY * hash_result;
+ hash_query.key = (char * const) field_name;
+ suppress = (hsearch_r(hash_query,
+ FIND,
+ &hash_result,
+ throttle_spec->hash_field_names) != 0);
+ }
+
+ EVEL_EXIT();
+
+ return suppress;
+}
+
+/**************************************************************************//**
+ * Determine whether a name-value pair should be allowed (not suppressed).
+ *
+ * @param throttle_spec Throttle specification for the domain being encoded.
+ * @param field_name The field name holding the name-value pairs.
+ * @param name The name of the name-value pair to encoded or suppress.
+ * @return true if the name-value pair should be suppressed, false otherwise.
+ *****************************************************************************/
+bool evel_throttle_suppress_nv_pair(EVEL_THROTTLE_SPEC * throttle_spec,
+ const char * const field_name,
+ const char * const name)
+{
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+ bool hit = false;
+ bool suppress = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(field_name != NULL);
+ assert(name != NULL);
+
+ /***************************************************************************/
+ /* If the throttle spec and hash table exist, query the nv_pairs table. */
+ /***************************************************************************/
+ if ((throttle_spec != NULL) && (throttle_spec->hash_nv_pairs_list != NULL))
+ {
+ ENTRY hash_query;
+ ENTRY * hash_result;
+ hash_query.key = (char * const) field_name;
+ hit = (hsearch_r(hash_query,
+ FIND,
+ &hash_result,
+ throttle_spec->hash_nv_pairs_list) != 0);
+ if (hit)
+ {
+ nv_pairs = hash_result->data;
+ }
+ }
+
+ /***************************************************************************/
+ /* If we got a hit, and the nv_pairs and hash table exist, query the */
+ /* nv_pairs table. */
+ /***************************************************************************/
+ if (hit && (nv_pairs != NULL) && (nv_pairs->hash_nv_pair_names != NULL))
+ {
+ ENTRY hash_query;
+ ENTRY * hash_result;
+ hash_query.key = (char * const) name;
+ suppress = (hsearch_r(hash_query,
+ FIND,
+ &hash_result,
+ nv_pairs->hash_nv_pair_names) != 0);
+ }
+
+ EVEL_EXIT();
+
+ return suppress;
+}
+
+/**************************************************************************//**
+ * Initialize event throttling to the default state.
+ *
+ * Called from ::evel_initialize.
+ *****************************************************************************/
+void evel_throttle_initialize()
+{
+ int pthread_rc;
+ int ii;
+
+ EVEL_ENTER();
+
+ for (ii = 0; ii < EVEL_MAX_DOMAINS; ii++)
+ {
+ evel_throttle_spec[ii] = NULL;
+ }
+
+ pthread_rc = pthread_mutex_init(&evel_measurement_interval_mutex, NULL);
+ assert(pthread_rc == 0);
+
+ evel_measurement_interval = EVEL_MEASUREMENT_INTERVAL_UKNOWN;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Clean up event throttling.
+ *
+ * Called from ::evel_terminate.
+ *****************************************************************************/
+void evel_throttle_terminate()
+{
+ int pthread_rc;
+ int ii;
+
+ EVEL_ENTER();
+
+ for (ii = 0; ii < EVEL_MAX_DOMAINS; ii++)
+ {
+ if (evel_throttle_spec[ii] != NULL)
+ {
+ evel_throttle_free(evel_throttle_spec[ii]);
+ evel_throttle_spec[ii] = NULL;
+ }
+ }
+
+ pthread_rc = pthread_mutex_destroy(&evel_measurement_interval_mutex);
+ assert(pthread_rc == 0);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Finalize a single ::EVEL_THROTTLE_SPEC.
+ *
+ * Now that the specification is collected, build hash tables to simplify the
+ * throttling itself.
+ *
+ * @param throttle_spec The ::EVEL_THROTTLE_SPEC to finalize.
+ *****************************************************************************/
+void evel_throttle_finalize(EVEL_THROTTLE_SPEC * throttle_spec)
+{
+ int nv_pairs_count;
+ DLIST_ITEM * dlist_item;
+ ENTRY * add_result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(throttle_spec != NULL);
+
+ /***************************************************************************/
+ /* Populate the hash table for suppressed field names. */
+ /***************************************************************************/
+ throttle_spec->hash_field_names =
+ evel_throttle_hash_create(&throttle_spec->suppressed_field_names);
+
+ /***************************************************************************/
+ /* Create the hash table for suppressed nv pairs. */
+ /***************************************************************************/
+ nv_pairs_count = dlist_count(&throttle_spec->suppressed_nv_pairs_list);
+ if (nv_pairs_count > 0)
+ {
+ throttle_spec->hash_nv_pairs_list = calloc(1, sizeof(struct hsearch_data));
+ assert(throttle_spec->hash_nv_pairs_list != NULL);
+
+ /*************************************************************************/
+ /* Provide plenty of space in the table - see hcreate_r notes. */
+ /*************************************************************************/
+ if (hcreate_r(nv_pairs_count * 2, throttle_spec->hash_nv_pairs_list) == 0)
+ {
+ EVEL_ERROR("Failed to create hash table");
+ free(throttle_spec->hash_nv_pairs_list);
+ throttle_spec->hash_nv_pairs_list = NULL;
+ }
+ }
+
+ /***************************************************************************/
+ /* Populate the hash tables under suppressed field names. */
+ /***************************************************************************/
+ dlist_item = dlist_get_first(&throttle_spec->suppressed_nv_pairs_list);
+ while (dlist_item != NULL)
+ {
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs = dlist_item->item;
+ ENTRY hash_add;
+
+ /*************************************************************************/
+ /* Set the key to the string, and the item to the nv_pairs. */
+ /*************************************************************************/
+ assert(nv_pairs != NULL);
+ hash_add.key = nv_pairs->nv_pair_field_name;
+ hash_add.data = nv_pairs;
+ hsearch_r(hash_add, ENTER, &add_result, throttle_spec->hash_nv_pairs_list);
+
+ /*************************************************************************/
+ /* Create the nv_pair_names hash since we're in here. */
+ /*************************************************************************/
+ nv_pairs->hash_nv_pair_names =
+ evel_throttle_hash_create(&nv_pairs->suppressed_nv_pair_names);
+
+ dlist_item = dlist_get_next(dlist_item);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create and populate a hash table from a DLIST of keys.
+ *
+ * @param hash_keys Pointer to a DLIST of hash table keys.
+ * @return Pointer to the created hash-table, or NULL on failure.
+ *****************************************************************************/
+struct hsearch_data * evel_throttle_hash_create(DLIST * hash_keys)
+{
+ int key_count;
+ struct hsearch_data * hash_table;
+ ENTRY * add_result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(hash_keys != NULL);
+
+ /***************************************************************************/
+ /* Count the keys and if there are any, populate the hash table with them. */
+ /***************************************************************************/
+ key_count = dlist_count(hash_keys);
+ if (key_count > 0)
+ {
+ EVEL_DEBUG("Populating table for %d keys", key_count);
+
+ hash_table = calloc(1, sizeof(struct hsearch_data));
+ assert(hash_table != NULL);
+
+ /*************************************************************************/
+ /* We need to leave plenty of space in the table - see hcreate_r notes. */
+ /*************************************************************************/
+ if (hcreate_r(key_count * 2, hash_table) != 0)
+ {
+ DLIST_ITEM * dlist_item;
+ dlist_item = dlist_get_first(hash_keys);
+ while (dlist_item != NULL)
+ {
+ assert(dlist_item->item != NULL);
+
+ /*********************************************************************/
+ /* Set the key and data to the item, which is a string in this case. */
+ /*********************************************************************/
+ ENTRY hash_add;
+ hash_add.key = dlist_item->item;
+ hash_add.data = dlist_item->item;
+ hsearch_r(hash_add, ENTER, &add_result, hash_table);
+ dlist_item = dlist_get_next(dlist_item);
+ }
+ }
+ else
+ {
+ EVEL_ERROR("Failed to create hash table");
+ free(hash_table);
+ hash_table = NULL;
+ }
+ }
+ else
+ {
+ hash_table = NULL;
+ }
+
+ EVEL_EXIT();
+
+ return hash_table;
+}
+
+/**************************************************************************//**
+ * Free resources associated with a single ::EVEL_THROTTLE_SPEC.
+ *
+ * @param throttle_spec The ::EVEL_THROTTLE_SPEC to free.
+ *****************************************************************************/
+void evel_throttle_free(EVEL_THROTTLE_SPEC * throttle_spec)
+{
+ char * field_name;
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(throttle_spec != NULL);
+
+ /***************************************************************************/
+ /* Free any hash tables. */
+ /***************************************************************************/
+ if (throttle_spec->hash_field_names != NULL)
+ {
+ hdestroy_r(throttle_spec->hash_field_names);
+ free(throttle_spec->hash_field_names);
+ }
+ if (throttle_spec->hash_nv_pairs_list != NULL)
+ {
+ hdestroy_r(throttle_spec->hash_nv_pairs_list);
+ free(throttle_spec->hash_nv_pairs_list);
+ }
+
+ /***************************************************************************/
+ /* Iterate through the linked lists, freeing memory. */
+ /***************************************************************************/
+ field_name = dlist_pop_last(&throttle_spec->suppressed_field_names);
+ while (field_name != NULL)
+ {
+ free(field_name);
+ field_name = dlist_pop_last(&throttle_spec->suppressed_field_names);
+ }
+
+ nv_pairs = dlist_pop_last(&throttle_spec->suppressed_nv_pairs_list);
+ while (nv_pairs != NULL)
+ {
+ evel_throttle_free_nv_pair(nv_pairs);
+ nv_pairs = dlist_pop_last(&throttle_spec->suppressed_nv_pairs_list);
+ }
+
+ free(throttle_spec);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free resources associated with a single ::EVEL_SUPPRESSED_NV_PAIR.
+ *
+ * @param nv_pair The ::EVEL_SUPPRESSED_NV_PAIR to free.
+ *****************************************************************************/
+void evel_throttle_free_nv_pair(EVEL_SUPPRESSED_NV_PAIRS * nv_pairs)
+{
+ char * suppressed_name;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(nv_pairs != NULL);
+
+ /***************************************************************************/
+ /* Free any hash tables. */
+ /***************************************************************************/
+ if (nv_pairs->hash_nv_pair_names != NULL)
+ {
+ hdestroy_r(nv_pairs->hash_nv_pair_names);
+ free(nv_pairs->hash_nv_pair_names);
+ }
+
+ /***************************************************************************/
+ /* Iterate through the linked lists, freeing memory. */
+ /***************************************************************************/
+ suppressed_name = dlist_pop_last(&nv_pairs->suppressed_nv_pair_names);
+ while (suppressed_name != NULL)
+ {
+ free(suppressed_name);
+ suppressed_name = dlist_pop_last(&nv_pairs->suppressed_nv_pair_names);
+ }
+ if (nv_pairs->nv_pair_field_name != NULL)
+ {
+ free(nv_pairs->nv_pair_field_name);
+ }
+ free(nv_pairs);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, as a list of tokens from JSMN.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Array of tokens to handle.
+ * @param num_tokens The number of tokens to handle.
+ * @param post The memory chunk in which to place any resulting POST.
+ * @return true if the command was handled, false otherwise.
+ *****************************************************************************/
+bool evel_handle_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post)
+{
+ EVEL_JSON_STACK stack;
+ EVEL_JSON_STACK * json_stack = &stack;
+ EVEL_JSON_STACK_ENTRY * entry;
+
+ bool json_ok = true;
+ int token_index = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(json_tokens != NULL);
+ assert(num_tokens < EVEL_MAX_RESPONSE_TOKENS);
+
+ /***************************************************************************/
+ /* Collect one top-level item. */
+ /***************************************************************************/
+ evel_init_json_stack(json_stack, chunk);
+
+ /***************************************************************************/
+ /* Initialize JSON processing variables. */
+ /***************************************************************************/
+ evel_provide_throttling_state = false;
+ evel_command_type_value = NULL;
+ evel_measurement_interval_value = NULL;
+ evel_throttle_spec_domain_value = NULL;
+ evel_throttle_spec_domain = EVEL_MAX_DOMAINS;
+ evel_temp_throttle = NULL;
+ evel_json_command_state = EVEL_JCS_START;
+
+ /***************************************************************************/
+ /* Loop through the tokens, keeping a stack of state representing the */
+ /* nested JSON structure (see json_state). We also track our way through */
+ /* the ::EVEL_JSON_COMMAND_STATE as we go. */
+ /***************************************************************************/
+ while (json_ok && (token_index < num_tokens))
+ {
+ const jsmntok_t * const token = &json_tokens[token_index];
+
+ if (EVEL_DEBUG_ON())
+ {
+ evel_debug_token(chunk, token);
+ }
+
+ /*************************************************************************/
+ /* We may have popped or pushed, so always re-evaluate the stack entry. */
+ /*************************************************************************/
+ entry = &json_stack->entry[json_stack->level];
+
+ switch(token->type)
+ {
+ case JSMN_OBJECT:
+ if ((entry->json_state == EVEL_JSON_ITEM) ||
+ (entry->json_state == EVEL_JSON_VALUE))
+ {
+ json_ok = evel_stack_push(json_stack, token->size, EVEL_JSON_KEY);
+ }
+ else
+ {
+ EVEL_ERROR("Unexpected JSON state %d at token %d (%d)",
+ entry->json_state, token_index, token->type);
+ json_ok = false;
+ }
+ break;
+
+ case JSMN_ARRAY:
+ if ((entry->json_state == EVEL_JSON_ITEM) ||
+ (entry->json_state == EVEL_JSON_VALUE))
+ {
+ json_ok = evel_stack_push(json_stack, token->size, EVEL_JSON_ITEM);
+ }
+ else
+ {
+ EVEL_ERROR("Unexpected JSON state %d at token %d (%d)",
+ entry->json_state, token_index, token->type);
+ json_ok = false;
+ }
+ break;
+
+ case JSMN_STRING:
+ if (entry->json_state == EVEL_JSON_KEY)
+ {
+ evel_stack_store_key(json_stack, token);
+ }
+ else if (entry->json_state == EVEL_JSON_VALUE)
+ {
+ evel_stack_store_value(json_stack, token);
+ }
+ else if (entry->json_state == EVEL_JSON_ITEM)
+ {
+ evel_stack_store_item(json_stack, token);
+ }
+ else
+ {
+ EVEL_ERROR("Unexpected JSON state %d at token %d (%d)",
+ entry->json_state, token_index, token->type);
+ json_ok = false;
+ }
+ break;
+
+ case JSMN_PRIMITIVE:
+ if (entry->json_state == EVEL_JSON_VALUE)
+ {
+ evel_stack_store_value(json_stack, token);
+ }
+ else if (entry->json_state == EVEL_JSON_ITEM)
+ {
+ evel_stack_store_item(json_stack, token);
+ }
+ else
+ {
+ EVEL_ERROR("Unexpected JSON state %d at token %d (%d)",
+ entry->json_state, token_index, token->type);
+ json_ok = false;
+ }
+ break;
+
+ case JSMN_UNDEFINED:
+ default:
+ EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+ token_index, token->type);
+ json_ok = false;
+ break;
+ }
+
+ /*************************************************************************/
+ /* Pop the stack if we're counted enough nested items. */
+ /*************************************************************************/
+ evel_stack_pop(json_stack);
+
+ token_index++;
+ }
+
+ /***************************************************************************/
+ /* Cleanup the stack - we may have exited without winding it back, if the */
+ /* input was not well formed. */
+ /***************************************************************************/
+ evel_stack_cleanup(json_stack);
+
+ /***************************************************************************/
+ /* We may want to generate and POST a response to the command list. */
+ /***************************************************************************/
+ if (json_ok)
+ {
+ evel_command_list_response(post);
+ }
+
+ /***************************************************************************/
+ /* Make sure we're clean on exit. */
+ /***************************************************************************/
+ assert(evel_command_type_value == NULL);
+ assert(evel_measurement_interval_value == NULL);
+ assert(evel_throttle_spec_domain_value == NULL);
+ assert(evel_throttle_spec_domain == EVEL_MAX_DOMAINS);
+ assert(evel_temp_throttle == NULL);
+
+ EVEL_EXIT();
+
+ return json_ok;
+}
+
+/**************************************************************************//**
+ * Copy a copy of an element, in string form.
+ *
+ * The caller must manage memory allocated for the copied string.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param token The token to copy from.
+ * @return the copy of the element.
+ *****************************************************************************/
+char * evel_stack_strdup(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const token)
+{
+ char temp_char;
+ char * result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Call strdup to copy the string, inserting a temporary \0 for the call. */
+ /***************************************************************************/
+ temp_char = chunk->memory[token->end];
+ chunk->memory[token->end] = '\0';
+ result = strdup(chunk->memory + token->start);
+ assert(result != NULL);
+ chunk->memory[token->end] = temp_char;
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Copy a copy of an element, in string form.
+ *
+ * @param json_stack The JSON stack to initialize.
+ * @param chunk The underlying memory chunk used for parsing.
+ *****************************************************************************/
+void evel_init_json_stack(EVEL_JSON_STACK * json_stack,
+ const MEMORY_CHUNK * const chunk)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+
+ EVEL_ENTER();
+
+ json_stack->level = 0;
+ entry = json_stack->entry;
+ entry->json_state = EVEL_JSON_ITEM;
+ entry->json_count = 0;
+ entry->num_required = 1;
+ entry->json_key = NULL;
+ json_stack->chunk = chunk;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Push a new entry on the stack
+ *
+ * @param json_stack The stack.
+ * @param num_required The number of elements required.
+ * @param new_state The state for the new entry.
+ * @return false if we cannot push onto the stack.
+ *****************************************************************************/
+bool evel_stack_push(EVEL_JSON_STACK * const json_stack,
+ const int num_required,
+ const EVEL_JSON_STATE new_state)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+ char * key;
+ bool result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json_stack != NULL);
+ assert(json_stack->level >= 0);
+ assert(json_stack->level < EVEL_JSON_STACK_DEPTH);
+ assert((new_state == EVEL_JSON_ITEM) || (new_state == EVEL_JSON_KEY));
+
+ /***************************************************************************/
+ /* Check nesting depth, and stop processing if we hit the limit. */
+ /***************************************************************************/
+ if ((json_stack->level + 1) >= EVEL_JSON_STACK_DEPTH)
+ {
+ EVEL_ERROR("JSON Nesting is too deep - stop processing");
+ result = false;
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Evaluate cases where we recurse and are interested in the contents. */
+ /***************************************************************************/
+ entry = &json_stack->entry[json_stack->level];
+ key = entry->json_key;
+
+ /***************************************************************************/
+ /* Note that this is the key before we drop a level. */
+ /***************************************************************************/
+ if (key != NULL)
+ {
+ EVEL_DEBUG("Push with key: %s", key);
+
+ switch (evel_json_command_state)
+ {
+ case EVEL_JCS_START:
+ if (strcmp(key, "commandList") == 0)
+ {
+ evel_set_command_state(EVEL_JCS_COMMAND_LIST);
+ }
+ break;
+
+ case EVEL_JCS_COMMAND_LIST_ENTRY:
+ if (strcmp(key, "command") == 0)
+ {
+ evel_open_command();
+ evel_set_command_state(EVEL_JCS_COMMAND);
+ }
+ break;
+
+ case EVEL_JCS_COMMAND:
+ if (strcmp(key, "eventDomainThrottleSpecification") == 0)
+ {
+ evel_open_throttle_spec();
+ evel_set_command_state(EVEL_JCS_SPEC);
+ }
+ break;
+
+ case EVEL_JCS_SPEC:
+ if (strcmp(key, "suppressedFieldNames") == 0)
+ {
+ evel_set_command_state(EVEL_JCS_FIELD_NAMES);
+ }
+ else if (strcmp(key, "suppressedNvPairsList") == 0)
+ {
+ evel_set_command_state(EVEL_JCS_PAIRS_LIST);
+ }
+ break;
+
+ case EVEL_JCS_PAIRS_LIST_ENTRY:
+ if (strcmp(key, "suppressedNvPairNames") == 0)
+ {
+ evel_set_command_state(EVEL_JCS_NV_PAIR_NAMES);
+ }
+ break;
+
+ case EVEL_JCS_FIELD_NAMES:
+ case EVEL_JCS_PAIRS_LIST:
+ case EVEL_JCS_NV_PAIR_NAMES:
+ default:
+ EVEL_ERROR("Unexpected JSON key %s in state %d",
+ key,
+ evel_json_command_state);
+ break;
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("Push with no key");
+
+ /*************************************************************************/
+ /* If we're pushing without a key, then we're in an array. We switch */
+ /* state based on the existing state and stack level. */
+ /*************************************************************************/
+ const int COMMAND_LIST_LEVEL = 2;
+ const int NV_PAIRS_LIST_LEVEL = 6;
+
+ if ((evel_json_command_state == EVEL_JCS_PAIRS_LIST) &&
+ (json_stack->level == NV_PAIRS_LIST_LEVEL))
+ {
+ /***********************************************************************/
+ /* We are entering an object within the "suppressedNvPairsList" array. */
+ /***********************************************************************/
+ evel_open_nv_pairs_list_entry();
+ evel_set_command_state(EVEL_JCS_PAIRS_LIST_ENTRY);
+ }
+
+ if ((evel_json_command_state == EVEL_JCS_COMMAND_LIST) &&
+ (json_stack->level == COMMAND_LIST_LEVEL))
+ {
+ /***********************************************************************/
+ /* We are entering an object within the "commandList" array. */
+ /***********************************************************************/
+ evel_set_command_state(EVEL_JCS_COMMAND_LIST_ENTRY);
+ }
+ }
+
+ /***************************************************************************/
+ /* Push the stack and initialize the entry. */
+ /***************************************************************************/
+ json_stack->level++;
+ entry++;
+ EVEL_DEBUG("Stack Push -> %d", json_stack->level);
+ entry = &json_stack->entry[json_stack->level];
+ entry->json_count = 0;
+ entry->num_required = num_required;
+ entry->json_state = new_state;
+ entry->json_key = NULL;
+ result = true;
+
+exit_label:
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Pop any stack entries which have collected the required number of items.
+ *
+ * @param json_stack The stack.
+ *****************************************************************************/
+void evel_stack_pop(EVEL_JSON_STACK * const json_stack)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+ char * key;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json_stack != NULL);
+ assert(json_stack->level >= 0);
+ assert(json_stack->level < EVEL_JSON_STACK_DEPTH);
+
+ entry = &json_stack->entry[json_stack->level];
+ while ((json_stack->level > 0) && (entry->json_count == entry->num_required))
+ {
+ key = entry->json_key;
+
+ switch (evel_json_command_state)
+ {
+ case EVEL_JCS_COMMAND_LIST:
+ evel_set_command_state(EVEL_JCS_START);
+ break;
+
+ case EVEL_JCS_COMMAND_LIST_ENTRY:
+ evel_set_command_state(EVEL_JCS_COMMAND_LIST);
+ break;
+
+ case EVEL_JCS_COMMAND:
+ evel_close_command();
+ evel_set_command_state(EVEL_JCS_COMMAND_LIST_ENTRY);
+ break;
+
+ case EVEL_JCS_SPEC:
+ evel_close_throttle_spec();
+ evel_set_command_state(EVEL_JCS_COMMAND);
+ break;
+
+ case EVEL_JCS_FIELD_NAMES:
+ evel_set_command_state(EVEL_JCS_SPEC);
+ break;
+
+ case EVEL_JCS_PAIRS_LIST:
+ evel_set_command_state(EVEL_JCS_SPEC);
+ break;
+
+ case EVEL_JCS_PAIRS_LIST_ENTRY:
+ evel_close_nv_pairs_list_entry();
+ evel_set_command_state(EVEL_JCS_PAIRS_LIST);
+ break;
+
+ case EVEL_JCS_NV_PAIR_NAMES:
+ evel_set_command_state(EVEL_JCS_PAIRS_LIST_ENTRY);
+ break;
+
+ default:
+ break;
+ }
+
+ /*************************************************************************/
+ /* Free off any key that was duplicated and stored. */
+ /*************************************************************************/
+ if (key != NULL)
+ {
+ free(key);
+ entry->json_key = NULL;
+ }
+
+ /*************************************************************************/
+ /* We just reached the required number of key-value pairs or items, so */
+ /* pop the stack. */
+ /*************************************************************************/
+ json_stack->level--;
+ entry--;
+
+ EVEL_DEBUG("Stack Pop -> %d", json_stack->level);
+
+ /*************************************************************************/
+ /* We just completed collection of an ITEM (within an ARRAY) or a VALUE */
+ /* (within an OBJECT). Either way, we need to count it. */
+ /*************************************************************************/
+ entry->json_count++;
+
+ /*************************************************************************/
+ /* If we just completed a VALUE, then we expect the next element to be a */
+ /* key, if there is a next element. */
+ /*************************************************************************/
+ if (entry->json_state == EVEL_JSON_VALUE)
+ {
+ entry->json_state = EVEL_JSON_KEY;
+ }
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Pop all stack entries, freeing any memory as we go.
+ *
+ * @param json_stack The stack.
+ *****************************************************************************/
+void evel_stack_cleanup(EVEL_JSON_STACK * const json_stack)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json_stack != NULL);
+ assert(json_stack->level >= 0);
+ assert(json_stack->level < EVEL_JSON_STACK_DEPTH);
+
+ entry = &json_stack->entry[json_stack->level];
+ while ((json_stack->level > 0))
+ {
+ /*************************************************************************/
+ /* Free off any key that was duplicated and stored. */
+ /*************************************************************************/
+ if (entry->json_key != NULL)
+ {
+ free(entry->json_key);
+ entry->json_key = NULL;
+ }
+
+ /*************************************************************************/
+ /* We just reached the required number of key-value pairs or items, so */
+ /* pop the stack. */
+ /*************************************************************************/
+ json_stack->level--;
+ entry--;
+ }
+
+ /***************************************************************************/
+ /* If we hit EVEL_JSON_STACK_DEPTH, we exit the loop and can leave these */
+ /* values hanging - so clean them up. */
+ /***************************************************************************/
+ if (evel_command_type_value != NULL)
+ {
+ free(evel_command_type_value);
+ evel_command_type_value = NULL;
+ }
+ if (evel_measurement_interval_value != NULL)
+ {
+ free(evel_measurement_interval_value);
+ evel_measurement_interval_value = NULL;
+ }
+ if (evel_throttle_spec_domain_value != NULL)
+ {
+ free(evel_throttle_spec_domain_value);
+ evel_throttle_spec_domain_value = NULL;
+ }
+ evel_throttle_spec_domain = EVEL_MAX_DOMAINS;
+ if (evel_temp_throttle != NULL)
+ {
+ evel_throttle_free(evel_temp_throttle);
+ evel_temp_throttle = NULL;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Store a key in the JSON stack.
+ *
+ * We always store the most recent key at each level in the stack.
+ *
+ * @param json_stack The stack.
+ * @param token The token holding the key.
+ *****************************************************************************/
+void evel_stack_store_key(EVEL_JSON_STACK * const json_stack,
+ const jsmntok_t * const token)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json_stack != NULL);
+ assert(json_stack->level >= 0);
+ assert(json_stack->level < EVEL_JSON_STACK_DEPTH);
+
+ /***************************************************************************/
+ /* Free any previously stored key, replacing it with the new one. */
+ /***************************************************************************/
+ entry = &json_stack->entry[json_stack->level];
+ if (entry->json_key != NULL)
+ {
+ free(entry->json_key);
+ }
+ entry->json_key = evel_stack_strdup(json_stack->chunk, token);
+
+ /***************************************************************************/
+ /* Switch state to collecting the corresponding value. */
+ /***************************************************************************/
+ entry->json_state = EVEL_JSON_VALUE;
+
+ EVEL_DEBUG("Stored key: %s", entry->json_key);
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Store a value in the JSON stack.
+ *
+ * @param json_stack The stack.
+ * @param token The token holding the value.
+ *****************************************************************************/
+void evel_stack_store_value(EVEL_JSON_STACK * const json_stack,
+ const jsmntok_t * const token)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+ char * value;
+ bool stored;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json_stack != NULL);
+ assert(json_stack->level >= 0);
+ assert(json_stack->level < EVEL_JSON_STACK_DEPTH);
+
+ /***************************************************************************/
+ /* Based on the (key, state), work out whether we're expecting a value, */
+ /* then store or ignore it as required. */
+ /***************************************************************************/
+ entry = &json_stack->entry[json_stack->level];
+ value = evel_stack_strdup(json_stack->chunk, token);
+ stored = false;
+ EVEL_DEBUG("Store value: %s", value);
+
+ switch (evel_json_command_state)
+ {
+ case EVEL_JCS_COMMAND:
+ if (strcmp(entry->json_key, "commandType") == 0)
+ {
+ evel_command_type_value = value;
+ stored = true;
+ }
+ else if (strcmp(entry->json_key, "measurementInterval") == 0)
+ {
+ evel_measurement_interval_value = value;
+ stored = true;
+ }
+ break;
+
+ case EVEL_JCS_SPEC:
+ if (strcmp(entry->json_key, "eventDomain") == 0)
+ {
+ evel_throttle_spec_domain_value = value;
+ stored = true;
+ }
+ break;
+
+ case EVEL_JCS_PAIRS_LIST_ENTRY:
+ if (strcmp(entry->json_key, "nvPairFieldName") == 0)
+ {
+ evel_store_nv_pair_field_name(value);
+ stored = true;
+ }
+ break;
+
+ default:
+ EVEL_DEBUG("Ignoring value in state: %s",
+ evel_jcs_strings[evel_json_command_state]);
+ break;
+ }
+
+ if (!stored)
+ {
+ EVEL_DEBUG("Ignored value: %s", value);
+ free(value);
+ }
+
+ /***************************************************************************/
+ /* Switch state to another key. */
+ /***************************************************************************/
+ entry->json_state = EVEL_JSON_KEY;
+
+ /***************************************************************************/
+ /* Count the key-value pair. */
+ /***************************************************************************/
+ entry->json_count++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Store an item in the JSON stack - a string or primitive in an array.
+ *
+ * @param json_stack The stack.
+ * @param token The token holding the item.
+ *****************************************************************************/
+void evel_stack_store_item(EVEL_JSON_STACK * const json_stack,
+ const jsmntok_t * const token)
+{
+ EVEL_JSON_STACK_ENTRY * entry;
+ char * item;
+ bool stored;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json_stack != NULL);
+ assert(json_stack->level >= 0);
+ assert(json_stack->level < EVEL_JSON_STACK_DEPTH);
+
+ /***************************************************************************/
+ /* Based on the state, work out whether we're expecting an item, then */
+ /* store or ignore it as required. */
+ /***************************************************************************/
+ entry = &json_stack->entry[json_stack->level];
+ item = evel_stack_strdup(json_stack->chunk, token);
+ stored = false;
+ EVEL_DEBUG("Store item: %s", item);
+
+ switch (evel_json_command_state)
+ {
+ case EVEL_JCS_NV_PAIR_NAMES:
+ evel_store_nv_pair_name(item);
+ stored = true;
+ break;
+
+ case EVEL_JCS_FIELD_NAMES:
+ evel_store_suppressed_field_name(item);
+ stored = true;
+ break;
+
+ default:
+ EVEL_DEBUG("Ignoring item in state: %s",
+ evel_jcs_strings[evel_json_command_state]);
+ break;
+ }
+
+ if (!stored)
+ {
+ EVEL_DEBUG("Ignored item: %s", item);
+ free(item);
+ }
+
+ /***************************************************************************/
+ /* We need another item. This is purely defensive. */
+ /***************************************************************************/
+ entry->json_state = EVEL_JSON_ITEM;
+
+ /***************************************************************************/
+ /* Count the item. */
+ /***************************************************************************/
+ entry->json_count++;
+}
+
+/**************************************************************************//**
+ * Set the JSON command state to a new value.
+ *
+ * @param new_state The new state to set.
+ *****************************************************************************/
+void evel_set_command_state(const EVEL_JSON_COMMAND_STATE new_state)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(evel_json_command_state < EVEL_JCS_MAX);
+ assert(new_state < EVEL_JCS_MAX);
+
+ /***************************************************************************/
+ /* Provide common debug, and set the new state. */
+ /***************************************************************************/
+ EVEL_DEBUG("Command State: %s -> %s",
+ evel_jcs_strings[evel_json_command_state],
+ evel_jcs_strings[new_state]);
+ evel_json_command_state = new_state;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Produce debug output from a JSON token.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param token Token to dump.
+ *****************************************************************************/
+void evel_debug_token(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const token)
+{
+ char temp_char;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(token->type > 0);
+ assert(token->type < JSON_TOKEN_TYPES);
+
+ /***************************************************************************/
+ /* Log the token, leaving it in the state in which it started. */
+ /***************************************************************************/
+ temp_char = chunk->memory[token->end];
+ chunk->memory[token->end] = '\0';
+ EVEL_DEBUG("JSON token type: %s", evel_json_token_strings[token->type]);
+ EVEL_DEBUG("JSON token: %s", chunk->memory + token->start);
+ chunk->memory[token->end] = temp_char;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Post a response to the commandList.
+ *
+ * @param post Memory chunk in which to post a response.
+ *****************************************************************************/
+void evel_command_list_response(MEMORY_CHUNK * const post)
+{
+ char * json_post;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(post != NULL);
+ assert(post->memory == NULL);
+
+ if (evel_provide_throttling_state)
+ {
+ EVEL_DEBUG("Provide throttling state");
+
+ /*************************************************************************/
+ /* Encode the response, making it printf-able for debug. */
+ /*************************************************************************/
+ json_post = malloc(EVEL_MAX_JSON_BODY);
+ assert(json_post != NULL);
+ post->size = evel_json_encode_throttle(json_post, EVEL_MAX_JSON_BODY - 1);
+ post->memory = json_post;
+ post->memory[post->size] = '\0';
+ evel_provide_throttling_state = false;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the full throttling specification according to AT&T's schema.
+ *
+ * @param json Pointer to where to store the JSON encoded data.
+ * @param max_size Size of storage available in json_body.
+ * @returns Number of bytes actually written.
+ *****************************************************************************/
+int evel_json_encode_throttle(char * const json, const int max_size)
+{
+ bool throttled;
+ int domain;
+ int offset;
+ bool domain_added;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(json != NULL);
+ assert(max_size > 0);
+
+ /***************************************************************************/
+ /* Work out if we're throttled. */
+ /***************************************************************************/
+ throttled = false;
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (evel_throttle_spec[domain] != NULL)
+ {
+ throttled = true;
+ }
+ }
+
+ /***************************************************************************/
+ /* Encode the response. */
+ /***************************************************************************/
+ offset = 0;
+ offset += snprintf(json + offset, max_size - offset,
+ "{\"eventThrottlingState\": {");
+ offset += snprintf(json + offset, max_size - offset,
+ "\"eventThrottlingMode\": \"%s\"",
+ throttled ? "throttled" : "normal");
+ if (throttled)
+ {
+ offset += snprintf(json + offset, max_size - offset,
+ ", \"eventDomainThrottleSpecificationList\": [");
+
+ domain_added = false;
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (evel_throttle_spec[domain] != NULL)
+ {
+ if (domain_added)
+ {
+ offset += snprintf(json + offset, max_size - offset, ", ");
+ }
+
+ offset += evel_json_encode_throttle_spec(json + offset,
+ max_size - offset,
+ domain);
+ domain_added = true;
+ }
+ }
+
+ offset += snprintf(json + offset, max_size - offset, "]");
+ }
+
+ offset += snprintf(json + offset, max_size - offset, "}}");
+
+ EVEL_EXIT();
+
+ return offset;
+}
+
+/**************************************************************************//**
+ * Encode a throttling specification for a domain.
+ *
+ * @param json Pointer to where to store the JSON encoded data.
+ * @param max_size Size of storage available in json_body.
+ * @returns Number of bytes actually written.
+ *****************************************************************************/
+int evel_json_encode_throttle_spec(char * const json,
+ const int max_size,
+ const EVEL_EVENT_DOMAINS domain)
+{
+ int offset;
+ EVEL_THROTTLE_SPEC * throttle_spec;
+ DLIST_ITEM * dlist_item;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(domain >= EVEL_DOMAIN_FAULT);
+ assert(domain < EVEL_MAX_DOMAINS);
+ assert(evel_throttle_spec[domain] != NULL);
+
+ throttle_spec = evel_throttle_spec[domain];
+
+ /***************************************************************************/
+ /* Encode the domain. */
+ /***************************************************************************/
+ offset = 0;
+ offset += snprintf(json + offset, max_size - offset,
+ "{");
+ offset += snprintf(json + offset, max_size - offset,
+ "\"eventDomain\": \"%s\"",
+ evel_domain_strings[domain]);
+
+ /***************************************************************************/
+ /* Encode "suppressedFieldNames". */
+ /***************************************************************************/
+ dlist_item = dlist_get_first(&throttle_spec->suppressed_field_names);
+ if (dlist_item != NULL)
+ {
+ offset += snprintf(json + offset, max_size - offset,
+ ", \"suppressedFieldNames\": [");
+ while (dlist_item != NULL)
+ {
+ char * suppressed_field = dlist_item->item;
+ assert(suppressed_field != NULL);
+
+ offset += snprintf(json + offset, max_size - offset,
+ "\"%s\"", suppressed_field);
+ dlist_item = dlist_get_next(dlist_item);
+ if (dlist_item != NULL)
+ {
+ offset += snprintf(json + offset, max_size - offset, ", ");
+ }
+ }
+
+ offset += snprintf(json + offset, max_size - offset, "]");
+ }
+
+ /***************************************************************************/
+ /* Encode "suppressedNvPairsList". */
+ /***************************************************************************/
+ dlist_item = dlist_get_first(&throttle_spec->suppressed_nv_pairs_list);
+ if (dlist_item != NULL)
+ {
+ offset += snprintf(json + offset, max_size - offset,
+ ", \"suppressedNvPairsList\": [");
+ while (dlist_item != NULL)
+ {
+ offset += evel_json_encode_nv_pairs(json + offset,
+ max_size - offset,
+ dlist_item->item);
+ dlist_item = dlist_get_next(dlist_item);
+ if (dlist_item != NULL)
+ {
+ offset += snprintf(json + offset, max_size - offset, ", ");
+ }
+ }
+
+ offset += snprintf(json + offset, max_size - offset, "]");
+ }
+
+ offset += snprintf(json + offset, max_size - offset, "}");
+
+ EVEL_EXIT();
+
+ return offset;
+}
+
+/**************************************************************************//**
+ * Encode a single "suppressedNvPairsListEntry".
+ *
+ * @param json Pointer to where to store the JSON encoded data.
+ * @param max_size Size of storage available in json_body.
+ * @returns Number of bytes actually written.
+ *****************************************************************************/
+int evel_json_encode_nv_pairs(char * const json,
+ const int max_size,
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs)
+{
+ DLIST_ITEM * dlist_item;
+ char * name;
+ int offset;
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(nv_pairs != NULL);
+ assert(nv_pairs->nv_pair_field_name != NULL);
+ assert(!dlist_is_empty(&nv_pairs->suppressed_nv_pair_names));
+
+ /***************************************************************************/
+ /* Encode it. */
+ /***************************************************************************/
+ offset = 0;
+ offset += snprintf(json + offset, max_size - offset, "{");
+ offset += snprintf(json + offset, max_size - offset,
+ "\"nvPairFieldName\": \"%s\"",
+ nv_pairs->nv_pair_field_name);
+ dlist_item = dlist_get_first(&nv_pairs->suppressed_nv_pair_names);
+ offset += snprintf(json + offset, max_size - offset,
+ ", \"suppressedNvPairNames\": [");
+ while (dlist_item != NULL)
+ {
+ name = dlist_item->item;
+ assert(name != NULL);
+ offset += snprintf(json + offset, max_size - offset, "\"%s\"", name);
+ dlist_item = dlist_get_next(dlist_item);
+ if (dlist_item != NULL)
+ {
+ offset += snprintf(json + offset, max_size - offset, ", ");
+ }
+ }
+ offset += snprintf(json + offset, max_size - offset, "]");
+ offset += snprintf(json + offset, max_size - offset, "}");
+
+ EVEL_EXIT();
+
+ return offset;
+}
+
+/**************************************************************************//**
+ * Method called when we open a "command" object.
+ *****************************************************************************/
+void evel_open_command()
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Make some assertions. */
+ /***************************************************************************/
+ assert(evel_command_type_value == NULL);
+ assert(evel_measurement_interval_value == NULL);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Method called when we close a "command" object.
+ *****************************************************************************/
+void evel_close_command()
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* If a commandType was provided, fan out and handle it now what we have */
+ /* fathered all related information. */
+ /* */
+ /* Note that we handle throttling specification and measurement interval */
+ /* updates immediately on closing the command (not the list). We could */
+ /* reject *all* commands in a list if any of them are invalid, but we are */
+ /* take a best-effort strategy here - any valid-looking command gets */
+ /* implemented regardless of what follows. */
+ /***************************************************************************/
+ if (evel_command_type_value != NULL)
+ {
+ EVEL_DEBUG("Closing command %s", evel_command_type_value);
+
+ if (strcmp(evel_command_type_value, "provideThrottlingState") == 0)
+ {
+ evel_provide_throttling_state = true;
+ }
+ else if (strcmp(evel_command_type_value, "throttlingSpecification") == 0)
+ {
+ evel_set_throttling_spec();
+ }
+ else if (strcmp(evel_command_type_value, "measurementIntervalChange") == 0)
+ {
+ evel_set_measurement_interval();
+ }
+ else
+ {
+ EVEL_ERROR("Ignoring unknown commandType: %s\n",
+ evel_command_type_value);
+ }
+
+ /*************************************************************************/
+ /* Free the captured "commandType" value. */
+ /*************************************************************************/
+ free(evel_command_type_value);
+ evel_command_type_value = NULL;
+ }
+
+ /***************************************************************************/
+ /* There could be an unused working throttle spec at this point - if the */
+ /* "throttlingSpecification" commandType was not provided, or an invalid */
+ /* domain was provided, or was not provided at all. */
+ /***************************************************************************/
+ if (evel_temp_throttle != NULL)
+ {
+ evel_throttle_free(evel_temp_throttle);
+ evel_temp_throttle = NULL;
+ }
+
+ /***************************************************************************/
+ /* Similarly, the domain could be set. */
+ /***************************************************************************/
+ evel_throttle_spec_domain = EVEL_MAX_DOMAINS;
+
+ /***************************************************************************/
+ /* There could be an unused measurement interval value at this point - if */
+ /* the "measurementIntervalChange" command was not provided. */
+ /***************************************************************************/
+ if (evel_measurement_interval_value != NULL)
+ {
+ free(evel_measurement_interval_value);
+ evel_measurement_interval_value = NULL;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the provided throttling specification, when the command closes.
+ *****************************************************************************/
+void evel_set_throttling_spec()
+{
+ EVEL_ENTER();
+
+ if ((evel_throttle_spec_domain >= 0) &&
+ (evel_throttle_spec_domain < EVEL_MAX_DOMAINS))
+ {
+ EVEL_DEBUG("Updating throttle spec for domain: %s",
+ evel_domain_strings[evel_throttle_spec_domain]);
+
+ /*************************************************************************/
+ /* Free off the previous throttle specification for the domain, if there */
+ /* is one. */
+ /*************************************************************************/
+ if (evel_throttle_spec[evel_throttle_spec_domain] != NULL)
+ {
+ evel_throttle_free(evel_throttle_spec[evel_throttle_spec_domain]);
+ }
+
+ /*************************************************************************/
+ /* Finalize the working throttling spec, if there is one. */
+ /*************************************************************************/
+ if (evel_temp_throttle != NULL)
+ {
+ evel_throttle_finalize(evel_temp_throttle);
+ }
+
+ /*************************************************************************/
+ /* Replace the throttle specification for the domain with the working */
+ /* throttle specification. This could be NULL, if an empty throttle */
+ /* specification has been received for a domain. */
+ /*************************************************************************/
+ evel_throttle_spec[evel_throttle_spec_domain] = evel_temp_throttle;
+ evel_temp_throttle = NULL;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the provided measurement interval, when the command closes.
+ *****************************************************************************/
+void evel_set_measurement_interval()
+{
+ EVEL_ENTER();
+
+ if (evel_measurement_interval_value != NULL)
+ {
+ const long int value = strtol(evel_measurement_interval_value, NULL, 10);
+
+ if ((value >= 0) && (value <= INT_MAX))
+ {
+ /***********************************************************************/
+ /* Lock, update, unlock. */
+ /***********************************************************************/
+ EVEL_DEBUG("Updating measurement interval to %d\n", value);
+
+ pthread_mutex_lock(&evel_measurement_interval_mutex);
+ evel_measurement_interval = value;
+ pthread_mutex_unlock(&evel_measurement_interval_mutex);
+ }
+ else
+ {
+ EVEL_ERROR("Ignoring invalid measurement interval: %s",
+ evel_measurement_interval_value);
+ }
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Method called when we open an "eventDomainThrottleSpecification" object.
+ *****************************************************************************/
+void evel_open_throttle_spec()
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(evel_throttle_spec_domain_value == NULL);
+ assert(evel_throttle_spec_domain == EVEL_MAX_DOMAINS);
+ assert(evel_temp_throttle == NULL);
+
+ /***************************************************************************/
+ /* Allocate and initialize an ::EVEL_THROTTLE_SPEC in which to hold */
+ /* captured JSON elements. */
+ /***************************************************************************/
+ evel_temp_throttle = malloc(sizeof(EVEL_THROTTLE_SPEC));
+ assert(evel_temp_throttle != NULL);
+ dlist_initialize(&evel_temp_throttle->suppressed_field_names);
+ dlist_initialize(&evel_temp_throttle->suppressed_nv_pairs_list);
+ evel_temp_throttle->hash_field_names = NULL;
+ evel_temp_throttle->hash_nv_pairs_list = NULL;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Method called when we close an "eventDomainThrottleSpecification" object.
+ *****************************************************************************/
+void evel_close_throttle_spec()
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Decode, free and blank a captured event domain value. */
+ /***************************************************************************/
+ if (evel_throttle_spec_domain_value != NULL)
+ {
+ evel_throttle_spec_domain =
+ evel_decode_domain(evel_throttle_spec_domain_value);
+ free(evel_throttle_spec_domain_value);
+ evel_throttle_spec_domain_value = NULL;
+ }
+
+ /***************************************************************************/
+ /* Free off an empty working throttle spec, to stop it being used. This */
+ /* state should be represented by a NULL pointer for the domain. */
+ /***************************************************************************/
+ if (evel_temp_throttle != NULL)
+ {
+ if (dlist_is_empty(&evel_temp_throttle->suppressed_field_names) &&
+ dlist_is_empty(&evel_temp_throttle->suppressed_nv_pairs_list))
+ {
+ free(evel_temp_throttle);
+ evel_temp_throttle = NULL;
+ }
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Convert a value for an "eventDomain" into an ::EVEL_EVENT_DOMAINS.
+ *
+ * @param domain_value The domain string value to decode.
+ * @returns The matching ::EVEL_EVENT_DOMAINS, or ::EVEL_MAX_DOMAINS on error.
+ *****************************************************************************/
+EVEL_EVENT_DOMAINS evel_decode_domain(char * domain_value)
+{
+ EVEL_EVENT_DOMAINS result;
+ int ii;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(domain_value != NULL);
+
+ result = EVEL_MAX_DOMAINS;
+ for (ii = EVEL_DOMAIN_FAULT; ii < EVEL_MAX_DOMAINS; ii++)
+ {
+ assert(evel_domain_strings[ii] != NULL);
+ if (strcmp(evel_domain_strings[ii], domain_value) == 0)
+ {
+ result = ii;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Method called when we open a "suppressedNvPairsListEntry" object.
+ *****************************************************************************/
+void evel_open_nv_pairs_list_entry()
+{
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(evel_temp_throttle != NULL);
+
+ /***************************************************************************/
+ /* Allocate and initialize an ::EVEL_SUPPRESSED_NV_PAIRS, and add it to */
+ /* the list. */
+ /***************************************************************************/
+ nv_pairs = malloc(sizeof(EVEL_SUPPRESSED_NV_PAIRS));
+ assert(nv_pairs != NULL);
+ nv_pairs->nv_pair_field_name = NULL;
+ dlist_initialize(&nv_pairs->suppressed_nv_pair_names);
+ nv_pairs->hash_nv_pair_names = NULL;
+ dlist_push_last(&evel_temp_throttle->suppressed_nv_pairs_list, nv_pairs);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Method called when we close a "suppressedNvPairsListEntry" object.
+ *****************************************************************************/
+void evel_close_nv_pairs_list_entry()
+{
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+ EVEL_SUPPRESSED_NV_PAIRS * popped;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Get the latest nv pairs. This also performs the required checks. */
+ /***************************************************************************/
+ nv_pairs = evel_get_last_nv_pairs();
+
+ /***************************************************************************/
+ /* For a "suppressedNvPairsListEntry" to have any meaning, we need both */
+ /* "nvPairFieldName" and "suppressedNvPairNames". If we don't, then pop */
+ /* and free whatever we just collected. */
+ /***************************************************************************/
+ if ((nv_pairs->nv_pair_field_name == NULL) ||
+ dlist_is_empty(&nv_pairs->suppressed_nv_pair_names))
+ {
+ popped = dlist_pop_last(&evel_temp_throttle->suppressed_nv_pairs_list);
+ assert(popped == nv_pairs);
+ evel_throttle_free_nv_pair(popped);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Store an "nvPairFieldName" value in the working throttle spec.
+ *
+ * @param value The value to store.
+ *****************************************************************************/
+void evel_store_nv_pair_field_name(char * const value)
+{
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Get the latest nv pairs. This also performs the required checks. */
+ /***************************************************************************/
+ nv_pairs = evel_get_last_nv_pairs();
+
+ /***************************************************************************/
+ /* Store the value. */
+ /***************************************************************************/
+ nv_pairs->nv_pair_field_name = value;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Store a "suppressedNvPairNames" item in the working throttle spec.
+ *
+ * @param item The item to store.
+ *****************************************************************************/
+void evel_store_nv_pair_name(char * const item)
+{
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Get the latest nv pairs. This also performs the required checks. */
+ /***************************************************************************/
+ nv_pairs = evel_get_last_nv_pairs();
+
+ /***************************************************************************/
+ /* Store the item. */
+ /***************************************************************************/
+ dlist_push_last(&nv_pairs->suppressed_nv_pair_names, item);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Store a "suppressedFieldNames" item in the working throttle spec.
+ *
+ * @param item The item to store.
+ *****************************************************************************/
+void evel_store_suppressed_field_name(char * const item)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(evel_temp_throttle != NULL);
+
+ /***************************************************************************/
+ /* Store the item. */
+ /***************************************************************************/
+ dlist_push_last(&evel_temp_throttle->suppressed_field_names, item);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Get the last added suppressed nv pairs list entry in the working spec.
+ *
+ * @returns The last entry.
+ *****************************************************************************/
+EVEL_SUPPRESSED_NV_PAIRS * evel_get_last_nv_pairs()
+{
+ DLIST_ITEM * dlist_item;
+ EVEL_SUPPRESSED_NV_PAIRS * nv_pairs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(evel_temp_throttle != NULL);
+
+ /***************************************************************************/
+ /* Get the pair that was added when we opened the list entry. */
+ /***************************************************************************/
+ dlist_item = dlist_get_last(&evel_temp_throttle->suppressed_nv_pairs_list);
+ assert(dlist_item != NULL);
+ nv_pairs = dlist_item->item;
+ assert(nv_pairs != NULL);
+
+ EVEL_EXIT();
+
+ return nv_pairs;
+}
diff --git a/vnfs/VES/code/evel_library/evel_throttle.h b/vnfs/VES/code/evel_library/evel_throttle.h
new file mode 100644
index 00000000..5f02cd2f
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_throttle.h
@@ -0,0 +1,228 @@
+#ifndef EVEL_THROTTLE_INCLUDED
+#define EVEL_THROTTLE_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * EVEL throttle definitions.
+ *
+ * These are internal definitions related to throttling specicications, which
+ * are required within the library but are not intended for external
+ * consumption.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "evel_internal.h"
+#include "jsmn.h"
+
+/*****************************************************************************/
+/* Maximum depth of JSON response that we can handle. */
+/*****************************************************************************/
+#define EVEL_JSON_STACK_DEPTH 10
+
+/**************************************************************************//**
+ * Maximum number of tokens that we allow for in a JSON response.
+ *****************************************************************************/
+#define EVEL_MAX_RESPONSE_TOKENS 1024
+
+/**************************************************************************//**
+ * The nature of the next token that we are iterating through. Within an
+ * object, we alternate between collecting keys and values. Within an array,
+ * we only collect items.
+ *****************************************************************************/
+typedef enum {
+ EVEL_JSON_KEY,
+ EVEL_JSON_VALUE,
+ EVEL_JSON_ITEM
+} EVEL_JSON_STATE;
+
+/**************************************************************************//**
+ * States which we move through during JSON processing, tracking our way
+ * through the supported JSON structure.
+ *****************************************************************************/
+typedef enum
+{
+ /***************************************************************************/
+ /* Initial state. */
+ /***************************************************************************/
+ EVEL_JCS_START,
+
+ /***************************************************************************/
+ /* {"commandList": [ */
+ /***************************************************************************/
+ EVEL_JCS_COMMAND_LIST,
+
+ /***************************************************************************/
+ /* {"commandList": [{ */
+ /***************************************************************************/
+ EVEL_JCS_COMMAND_LIST_ENTRY,
+
+ /***************************************************************************/
+ /* {"commandList": [{"command": { */
+ /***************************************************************************/
+ EVEL_JCS_COMMAND,
+
+ /***************************************************************************/
+ /* ... "eventDomainThrottleSpecification": { */
+ /***************************************************************************/
+ EVEL_JCS_SPEC,
+
+ /***************************************************************************/
+ /* ... "suppressedFieldNames": [ */
+ /***************************************************************************/
+ EVEL_JCS_FIELD_NAMES,
+
+ /***************************************************************************/
+ /* ... "suppressedNvPairsList": [ */
+ /***************************************************************************/
+ EVEL_JCS_PAIRS_LIST,
+
+ /***************************************************************************/
+ /* ... "suppressedNvPairsList": [{ */
+ /***************************************************************************/
+ EVEL_JCS_PAIRS_LIST_ENTRY,
+
+ /***************************************************************************/
+ /* ... "suppressedNvPairNames": [ */
+ /***************************************************************************/
+ EVEL_JCS_NV_PAIR_NAMES,
+
+ EVEL_JCS_MAX
+} EVEL_JSON_COMMAND_STATE;
+
+/**************************************************************************//**
+ * An entry in the JSON stack.
+ *****************************************************************************/
+typedef struct evel_json_stack_entry {
+
+ /***************************************************************************/
+ /* The number of elements required at this level. */
+ /***************************************************************************/
+ int num_required;
+
+ /***************************************************************************/
+ /* The number of elements collected at this level. */
+ /***************************************************************************/
+ int json_count;
+
+ /***************************************************************************/
+ /* The collection state at this level in the JSON stack. */
+ /***************************************************************************/
+ EVEL_JSON_STATE json_state;
+
+ /***************************************************************************/
+ /* The key being collected (if json_state is EVEL_JSON_VALUE), or NULL. */
+ /***************************************************************************/
+ char * json_key;
+
+} EVEL_JSON_STACK_ENTRY;
+
+/**************************************************************************//**
+ * The JSON stack.
+ *****************************************************************************/
+typedef struct evel_json_stack {
+
+ /***************************************************************************/
+ /* The current position of the stack - starting at zero. */
+ /***************************************************************************/
+ int level;
+
+ /***************************************************************************/
+ /* The stack itself. */
+ /***************************************************************************/
+ EVEL_JSON_STACK_ENTRY entry[EVEL_JSON_STACK_DEPTH];
+
+ /***************************************************************************/
+ /* The underlying memory chunk. */
+ /***************************************************************************/
+ const MEMORY_CHUNK * chunk;
+
+} EVEL_JSON_STACK;
+
+/**************************************************************************//**
+ * Initialize event throttling to the default state.
+ *
+ * Called from ::evel_initialize.
+ *****************************************************************************/
+void evel_throttle_initialize();
+
+/**************************************************************************//**
+ * Clean up event throttling.
+ *
+ * Called from ::evel_terminate.
+ *****************************************************************************/
+void evel_throttle_terminate();
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, as a list of tokens from JSMN.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Array of tokens to handle.
+ * @param num_tokens The number of tokens to handle.
+ * @param post The memory chunk in which to place any resulting POST.
+ * @return true if the command was handled, false otherwise.
+ *****************************************************************************/
+bool evel_handle_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post);
+
+/**************************************************************************//**
+ * Return the ::EVEL_THROTTLE_SPEC for a given domain.
+ *
+ * @param domain The domain for which to return state.
+ *****************************************************************************/
+EVEL_THROTTLE_SPEC * evel_get_throttle_spec(EVEL_EVENT_DOMAINS domain);
+
+/**************************************************************************//**
+ * Determine whether a field_name should be suppressed.
+ *
+ * @param throttle_spec Throttle specification for the domain being encoded.
+ * @param field_name The field name to encoded or suppress.
+ * @return true if the field_name should be suppressed, false otherwise.
+ *****************************************************************************/
+bool evel_throttle_suppress_field(EVEL_THROTTLE_SPEC * throttle_spec,
+ const char * const field_name);
+
+/**************************************************************************//**
+ * Determine whether a name-value pair should be allowed (not suppressed).
+ *
+ * @param throttle_spec Throttle specification for the domain being encoded.
+ * @param field_name The field name holding the name-value pairs.
+ * @param name The name of the name-value pair to encoded or suppress.
+ * @return true if the name-value pair should be suppressed, false otherwise.
+ *****************************************************************************/
+bool evel_throttle_suppress_nv_pair(EVEL_THROTTLE_SPEC * throttle_spec,
+ const char * const field_name,
+ const char * const name);
+
+#endif
diff --git a/vnfs/VES/code/evel_library/jsmn.c b/vnfs/VES/code/evel_library/jsmn.c
new file mode 100644
index 00000000..e7765eb1
--- /dev/null
+++ b/vnfs/VES/code/evel_library/jsmn.c
@@ -0,0 +1,311 @@
+#include "jsmn.h"
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+ jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *tok;
+ if (parser->toknext >= num_tokens) {
+ return NULL;
+ }
+ tok = &tokens[parser->toknext++];
+ tok->start = tok->end = -1;
+ tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+ tok->parent = -1;
+#endif
+ return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+ int start, int end) {
+ token->type = type;
+ token->start = start;
+ token->end = end;
+ token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+ int start;
+
+ start = parser->pos;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+ /* In strict mode primitive must be followed by "," or "}" or "]" */
+ case ':':
+#endif
+ case '\t' : case '\r' : case '\n' : case ' ' :
+ case ',' : case ']' : case '}' :
+ goto found;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#ifdef JSMN_STRICT
+ /* In strict mode primitive must be followed by a comma/object/array */
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+#endif
+
+found:
+ if (tokens == NULL) {
+ parser->pos--;
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ parser->pos--;
+ return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+
+ int start = parser->pos;
+
+ parser->pos++;
+
+ /* Skip starting quote */
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"') {
+ if (tokens == NULL) {
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ return 0;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\' && parser->pos + 1 < len) {
+ int i;
+ parser->pos++;
+ switch (js[parser->pos]) {
+ /* Allowed escaped symbols */
+ case '\"': case '/' : case '\\' : case 'b' :
+ case 'f' : case 'r' : case 'n' : case 't' :
+ break;
+ /* Allows escaped symbol \uXXXX */
+ case 'u':
+ parser->pos++;
+ for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+ /* If it isn't a hex character we have an error */
+ if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ parser->pos++;
+ }
+ parser->pos--;
+ break;
+ /* Unexpected symbol */
+ default:
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+ }
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, unsigned int num_tokens) {
+ int r;
+ int i;
+ jsmntok_t *token;
+ int count = parser->toknext;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c;
+ jsmntype_t type;
+
+ c = js[parser->pos];
+ switch (c) {
+ case '{': case '[':
+ count++;
+ if (tokens == NULL) {
+ break;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL)
+ return JSMN_ERROR_NOMEM;
+ if (parser->toksuper != -1) {
+ tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ }
+ token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+ token->start = parser->pos;
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case '}': case ']':
+ if (tokens == NULL)
+ break;
+ type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+ if (parser->toknext < 1) {
+ return JSMN_ERROR_INVAL;
+ }
+ token = &tokens[parser->toknext - 1];
+ for (;;) {
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ token->end = parser->pos + 1;
+ parser->toksuper = token->parent;
+ break;
+ }
+ if (token->parent == -1) {
+ break;
+ }
+ token = &tokens[token->parent];
+ }
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ parser->toksuper = -1;
+ token->end = parser->pos + 1;
+ break;
+ }
+ }
+ /* Error if unmatched closing bracket */
+ if (i == -1) return JSMN_ERROR_INVAL;
+ for (; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+#endif
+ break;
+ case '\"':
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+ case '\t' : case '\r' : case '\n' : case ' ':
+ break;
+ case ':':
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case ',':
+ if (tokens != NULL && parser->toksuper != -1 &&
+ tokens[parser->toksuper].type != JSMN_ARRAY &&
+ tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+ parser->toksuper = tokens[parser->toksuper].parent;
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ break;
+#ifdef JSMN_STRICT
+ /* In strict mode primitives are: numbers and booleans */
+ case '-': case '0': case '1' : case '2': case '3' : case '4':
+ case '5': case '6': case '7' : case '8': case '9':
+ case 't': case 'f': case 'n' :
+ /* And they must not be keys of the object */
+ if (tokens != NULL && parser->toksuper != -1) {
+ jsmntok_t *t = &tokens[parser->toksuper];
+ if (t->type == JSMN_OBJECT ||
+ (t->type == JSMN_STRING && t->size != 0)) {
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#else
+ /* In non-strict mode every unquoted value is a primitive */
+ default:
+#endif
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+
+#ifdef JSMN_STRICT
+ /* Unexpected char in strict mode */
+ default:
+ return JSMN_ERROR_INVAL;
+#endif
+ }
+ }
+
+ if (tokens != NULL) {
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ /* Unmatched opened object or array */
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ return JSMN_ERROR_PART;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser) {
+ parser->pos = 0;
+ parser->toknext = 0;
+ parser->toksuper = -1;
+}
+
diff --git a/vnfs/VES/code/evel_library/jsmn.h b/vnfs/VES/code/evel_library/jsmn.h
new file mode 100644
index 00000000..01ca99c8
--- /dev/null
+++ b/vnfs/VES/code/evel_library/jsmn.h
@@ -0,0 +1,76 @@
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * o Object
+ * o Array
+ * o String
+ * o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+ JSMN_UNDEFINED = 0,
+ JSMN_OBJECT = 1,
+ JSMN_ARRAY = 2,
+ JSMN_STRING = 3,
+ JSMN_PRIMITIVE = 4
+} jsmntype_t;
+
+enum jsmnerr {
+ /* Not enough tokens were provided */
+ JSMN_ERROR_NOMEM = -1,
+ /* Invalid character inside JSON string */
+ JSMN_ERROR_INVAL = -2,
+ /* The string is not a full JSON packet, more bytes expected */
+ JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * @param type type (object, array, string etc.)
+ * @param start start position in JSON data string
+ * @param end end position in JSON data string
+ */
+typedef struct {
+ jsmntype_t type;
+ int start;
+ int end;
+ int size;
+#ifdef JSMN_PARENT_LINKS
+ int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+ unsigned int pos; /* offset in the JSON string */
+ unsigned int toknext; /* next token to allocate */
+ int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
+ * a single JSON object.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, unsigned int num_tokens);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __JSMN_H_ */
diff --git a/vnfs/VES/code/evel_library/license.md b/vnfs/VES/code/evel_library/license.md
new file mode 100644
index 00000000..9851dcac
--- /dev/null
+++ b/vnfs/VES/code/evel_library/license.md
@@ -0,0 +1,95 @@
+# Licensing {#licensing}
+
+# Introduction {#lic_intro}
+
+This Licensing section describes licensing of IPR in the EVEL Library.
+
+# Licensed Software {#lic_software}
+
+## EVEL Library {#lic_evel}
+
+Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement: This product includes
+ software developed by the AT&T.
+4. Neither the name of AT&T nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+## libcurl {#lic_libcurl}
+
+The EVEL Library makes use of the the [cURL Library]
+(https://curl.haxx.se/libcurl/) in order to send and receive HTTP data.
+
+### License
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2016, Daniel Stenberg, daniel@haxx.se, and many
+contributors, see the THANKS file.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization of the copyright holder.
+
+## JSMN {#lic_jsmn}
+
+The EVEL Library makes use of the [JSMN library](http://zserge.com/jsmn.html)
+in order to decode JSON data.
+
+### License {#lic_jsmn_license}
+
+Copyright (c) 2010 Serge A. Zaitsev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of 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 of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ \ No newline at end of file
diff --git a/vnfs/VES/code/evel_library/metadata.c b/vnfs/VES/code/evel_library/metadata.c
new file mode 100644
index 00000000..dfdca052
--- /dev/null
+++ b/vnfs/VES/code/evel_library/metadata.c
@@ -0,0 +1,607 @@
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <malloc.h>
+
+#include <curl/curl.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "jsmn.h"
+#include "metadata.h"
+
+/**************************************************************************//**
+ * URL on the link-local IP address where we can get the metadata in
+ * machine-friendly format.
+ *****************************************************************************/
+static const char * OPENSTACK_METADATA_URL =
+ "http://169.254.169.254/openstack/latest/meta_data.json";
+
+/**************************************************************************//**
+ * How long we're prepared to wait for the metadata service to respond in
+ * seconds.
+ *****************************************************************************/
+static const int OPENSTACK_METADATA_TIMEOUT = 2;
+
+/**************************************************************************//**
+ * Size of fields extracted from metadata service.
+ *****************************************************************************/
+#define MAX_METADATA_STRING 64
+
+/**************************************************************************//**
+ * UUID of the VM extracted from the OpenStack metadata service.
+ *****************************************************************************/
+static char vm_uuid[MAX_METADATA_STRING+1] = {0};
+
+/**************************************************************************//**
+ * Name of the VM extracted from the OpenStack metadata service.
+ *****************************************************************************/
+static char vm_name[MAX_METADATA_STRING+1] = {0};
+
+/**************************************************************************//**
+ * How many metadata elements we allow for in the retrieved JSON.
+ *****************************************************************************/
+static const int MAX_METADATA_TOKENS = 128;
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static EVEL_ERR_CODES json_get_top_level_string(const char * json_string,
+ const jsmntok_t *tokens,
+ int json_token_count,
+ const char * key,
+ char * value);
+static EVEL_ERR_CODES json_get_string(const char * json_string,
+ const jsmntok_t *tokens,
+ int json_token_count,
+ const char * key,
+ char * value);
+static int jsoneq(const char *json, const jsmntok_t *tok, const char *s);
+
+/**************************************************************************//**
+ * Download metadata from the OpenStack metadata service.
+ *
+ * @param verbosity Controls whether to generate debug to stdout. Zero:
+ * none. Non-zero: generate debug.
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES openstack_metadata(int verbosity)
+{
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc = CURLE_OK;
+ CURL * curl_handle = NULL;
+ MEMORY_CHUNK rx_chunk;
+ char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
+ jsmn_parser json_parser;
+ jsmntok_t tokens[MAX_METADATA_TOKENS];
+ int json_token_count = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Initialize dummy values for the metadata - needed for test */
+ /* environments. */
+ /***************************************************************************/
+ openstack_metadata_initialize();
+
+ /***************************************************************************/
+ /* Get a curl handle which we'll use for accessing the metadata service. */
+ /***************************************************************************/
+ curl_handle = curl_easy_init();
+ if (curl_handle == NULL)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to get libcurl handle");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Prime the library to give friendly error codes. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_ERRORBUFFER,
+ curl_err_string);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl to provide friendly errors. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set the URL for the metadata API. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, OPENSTACK_METADATA_URL);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl with the API URL. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* send all data to this function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_WRITEFUNCTION,
+ evel_write_callback);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl with the write callback. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* some servers don't like requests that are made without a user-agent */
+ /* field, so we provide one. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_USERAGENT,
+ "libcurl-agent/1.0");
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl to upload. Error code=%d (%s)",
+ curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set the timeout for the operation. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_TIMEOUT,
+ OPENSTACK_METADATA_TIMEOUT);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_NO_METADATA;
+ EVEL_ERROR("Failed to initialize libcurl to set timeout. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Create the memory chunk to be used for the response to the post. The */
+ /* will be realloced. */
+ /***************************************************************************/
+ rx_chunk.memory = malloc(1);
+ assert(rx_chunk.memory != NULL);
+ rx_chunk.size = 0;
+
+ /***************************************************************************/
+ /* Point to the data to be received. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&rx_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl to receive metadata. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized data to receive");
+
+ /***************************************************************************/
+ /* If running in verbose mode generate more output. */
+ /***************************************************************************/
+ if (verbosity > 0)
+ {
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libcurl to be verbose. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+ }
+
+ /***************************************************************************/
+ /* Now run off and do what you've been told! */
+ /***************************************************************************/
+ curl_rc = curl_easy_perform(curl_handle);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to transfer the data from metadata service. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ }
+ else
+ {
+ /*************************************************************************/
+ /* We have some metadata available, so break it out into tokens. */
+ /*************************************************************************/
+ EVEL_DEBUG("Received metadata size = %d", rx_chunk.size);
+ EVEL_INFO("Received metadata = %s", rx_chunk.memory);
+ jsmn_init(&json_parser);
+ json_token_count = jsmn_parse(&json_parser,
+ rx_chunk.memory, rx_chunk.size,
+ tokens, MAX_METADATA_TOKENS);
+
+ /*************************************************************************/
+ /* Check that we parsed some data and that the top level is as expected. */
+ /*************************************************************************/
+ if (json_token_count < 0 || tokens[0].type != JSMN_OBJECT)
+ {
+ rc = EVEL_BAD_METADATA;
+ EVEL_ERROR("Failed to parse received JSON OpenStack metadata. "
+ "Error code=%d", json_token_count);
+ goto exit_label;
+ }
+ else
+ {
+ EVEL_DEBUG("Extracted %d tokens from the JSON OpenStack metadata. ",
+ json_token_count);
+ }
+
+ /*************************************************************************/
+ /* Find the keys we want from the metadata. */
+ /*************************************************************************/
+ if (json_get_string(rx_chunk.memory,
+ tokens,
+ json_token_count,
+ "uuid",
+ vm_uuid) != EVEL_SUCCESS)
+ {
+ rc = EVEL_BAD_METADATA;
+ EVEL_ERROR("Failed to extract UUID from OpenStack metadata");
+ }
+ else
+ {
+ EVEL_DEBUG("UUID: %s", vm_uuid);
+ }
+ if (json_get_top_level_string(rx_chunk.memory,
+ tokens,
+ json_token_count,
+ "name",
+ vm_name) != EVEL_SUCCESS)
+ {
+ rc = EVEL_BAD_METADATA;
+ EVEL_ERROR("Failed to extract VM Name from OpenStack metadata");
+ }
+ else
+ {
+ EVEL_DEBUG("VM Name: %s", vm_name);
+ }
+ }
+
+exit_label:
+
+ /***************************************************************************/
+ /* Shut down the cURL library in a tidy manner. */
+ /***************************************************************************/
+ if (curl_handle != NULL)
+ {
+ curl_easy_cleanup(curl_handle);
+ curl_handle = NULL;
+ }
+ free(rx_chunk.memory);
+
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Initialize default values for vm_name and vm_uuid - for testing purposes.
+ *****************************************************************************/
+void openstack_metadata_initialize()
+{
+ strncpy(vm_uuid,
+ "Dummy VM UUID - No Metadata available",
+ MAX_METADATA_STRING);
+ strncpy(vm_name,
+ "Dummy VM name - No Metadata available",
+ MAX_METADATA_STRING);
+}
+
+/**************************************************************************//**
+ * Get a string value from supplied JSON by matching the key.
+ *
+ * As the structure of the metadata we're looking at is pretty straightforward
+ * we don't do anything complex (a la XPath) to extract nested keys with the
+ * same leaf name, for example. Simply walk the structure until we find a
+ * string with the correct value.
+ *
+ * @param[in] json_string The string which contains the JSON and has already
+ * been parsed.
+ * @param[in] tokens The tokens which the JSON parser found in the JSON.
+ * @param[in] json_token_count How many tokens were found.
+ * @param[in] key The key we're looking for.
+ * @param[out] value The string we found at @p key.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success - contents of @p value updated.
+ * @retval EVEL_JSON_KEY_NOT_FOUND Key not found - @p value not updated.
+ * @retval EVEL_BAD_JSON Parser hit unexpected data - @p value not
+ * updated.
+ *****************************************************************************/
+static EVEL_ERR_CODES json_get_string(const char * json_string,
+ const jsmntok_t * tokens,
+ int json_token_count,
+ const char * key,
+ char * value)
+{
+ EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND;
+ int token_num = 0;
+ int token_len = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(json_string != NULL);
+ assert(tokens != NULL);
+ assert(json_token_count >= 0);
+ assert(key != NULL);
+ assert(value != NULL);
+
+ for (token_num = 0; token_num < json_token_count; token_num++)
+ {
+ switch(tokens[token_num].type)
+ {
+ case JSMN_OBJECT:
+ EVEL_DEBUG("Skipping object");
+ break;
+
+ case JSMN_ARRAY:
+ EVEL_DEBUG("Skipping array");
+ break;
+
+ case JSMN_STRING:
+ /***********************************************************************/
+ /* This is a string, so may be what we want. Compare keys. */
+ /***********************************************************************/
+ if (jsoneq(json_string, &tokens[token_num], key) == 0)
+ {
+ token_len = tokens[token_num + 1].end - tokens[token_num + 1].start;
+ EVEL_DEBUG("Token %d len %d matches at %d to %d", token_num,
+ tokens[token_num + 1].start,
+ tokens[token_num + 1].end);
+ strncpy(value, json_string + tokens[token_num + 1].start, token_len);
+ value[token_len] = '\0';
+ EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value);
+ rc = EVEL_SUCCESS;
+ goto exit_label;
+ }
+ else
+ {
+ EVEL_DEBUG("String key did not match");
+ }
+
+ /***********************************************************************/
+ /* Step over the value, whether we used it or not. */
+ /***********************************************************************/
+ token_num++;
+ break;
+
+ case JSMN_PRIMITIVE:
+ EVEL_INFO("Skipping primitive");
+ break;
+
+ case JSMN_UNDEFINED:
+ default:
+ rc = EVEL_BAD_JSON_FORMAT;
+ EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+ token_num,
+ tokens[token_num].type);
+ goto exit_label;
+ }
+ }
+
+exit_label:
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Get a top-level string value from supplied JSON by matching the key.
+ *
+ * Unlike json_get_string, this only returns a value that is in the top-level
+ * JSON object.
+ *
+ * @param[in] json_string The string which contains the JSON and has already
+ * been parsed.
+ * @param[in] tokens The tokens which the JSON parser found in the JSON.
+ * @param[in] json_token_count How many tokens were found.
+ * @param[in] key The key we're looking for.
+ * @param[out] value The string we found at @p key.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success - contents of @p value updated.
+ * @retval EVEL_JSON_KEY_NOT_FOUND Key not found - @p value not updated.
+ * @retval EVEL_BAD_JSON Parser hit unexpected data - @p value not
+ * updated.
+ *****************************************************************************/
+static EVEL_ERR_CODES json_get_top_level_string(const char * json_string,
+ const jsmntok_t * tokens,
+ int json_token_count,
+ const char * key,
+ char * value)
+{
+ EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND;
+ int token_num = 0;
+ int token_len = 0;
+ int bracket_count = 0;
+ int string_index = 0;
+ int increment = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(json_string != NULL);
+ assert(tokens != NULL);
+ assert(json_token_count >= 0);
+ assert(key != NULL);
+ assert(value != NULL);
+
+ for (token_num = 0; token_num < json_token_count; token_num++)
+ {
+ switch(tokens[token_num].type)
+ {
+ case JSMN_OBJECT:
+ EVEL_DEBUG("Skipping object");
+ break;
+
+ case JSMN_ARRAY:
+ EVEL_DEBUG("Skipping array");
+ break;
+
+ case JSMN_STRING:
+ /***********************************************************************/
+ /* This is a string, so may be what we want. Compare keys. */
+ /***********************************************************************/
+ if (jsoneq(json_string, &tokens[token_num], key) == 0)
+ {
+ /*********************************************************************/
+ /* Count the difference in the number of opening and closing */
+ /* brackets up to this token. This needs to be 1 for a top-level */
+ /* string. Let's just hope we don't have any strings containing */
+ /* brackets. */
+ /*********************************************************************/
+ increment = ((string_index < tokens[token_num].start) ? 1 : -1);
+
+ while (string_index != tokens[token_num].start)
+ {
+ if (json_string[string_index] == '{')
+ {
+ bracket_count += increment;
+ }
+ else if (json_string[string_index] == '}')
+ {
+ bracket_count -= increment;
+ }
+
+ string_index += increment;
+ }
+
+ if (bracket_count == 1)
+ {
+ token_len = tokens[token_num + 1].end - tokens[token_num + 1].start;
+ EVEL_DEBUG("Token %d len %d matches at top level at %d to %d",
+ token_num,
+ tokens[token_num + 1].start,
+ tokens[token_num + 1].end);
+ strncpy(value, json_string + tokens[token_num + 1].start, token_len);
+ value[token_len] = '\0';
+ EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value);
+ rc = EVEL_SUCCESS;
+ goto exit_label;
+ }
+ else
+ {
+ EVEL_DEBUG("String key did match, but not at top level");
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("String key did not match");
+ }
+
+ /***********************************************************************/
+ /* Step over the value, whether we used it or not. */
+ /***********************************************************************/
+ token_num++;
+ break;
+
+ case JSMN_PRIMITIVE:
+ EVEL_INFO("Skipping primitive");
+ break;
+
+ case JSMN_UNDEFINED:
+ default:
+ rc = EVEL_BAD_JSON_FORMAT;
+ EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+ token_num,
+ tokens[token_num].type);
+ goto exit_label;
+ }
+ }
+
+exit_label:
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Compare a JSON string token with a value.
+ *
+ * @param[in] json The string which contains the JSON and has already been
+ * parsed.
+ * @param[in] tok The token which the JSON parser found in the JSON.
+ * @param[in] s The string we're looking for.
+ *
+ * @returns Whether the token matches the string or not.
+ * @retval 0 Value matches
+ * @retval -1 Value does not match.
+ *****************************************************************************/
+static int jsoneq(const char *json, const jsmntok_t *tok, const char *s) {
+ if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+ strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+/**************************************************************************//**
+ * Get the VM name provided by the metadata service.
+ *
+ * @returns VM name
+ *****************************************************************************/
+const char *openstack_vm_name()
+{
+ return vm_name;
+}
+
+/**************************************************************************//**
+ * Get the VM UUID provided by the metadata service.
+ *
+ * @returns VM UUID
+ *****************************************************************************/
+const char *openstack_vm_uuid()
+{
+ return vm_uuid;
+}
diff --git a/vnfs/VES/code/evel_library/metadata.h b/vnfs/VES/code/evel_library/metadata.h
new file mode 100644
index 00000000..d9d0cc1a
--- /dev/null
+++ b/vnfs/VES/code/evel_library/metadata.h
@@ -0,0 +1,72 @@
+#ifndef METADATA_INCLUDED
+#define METADATA_INCLUDED
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+
+#include "evel.h"
+
+/**************************************************************************//**
+ * Download metadata from the OpenStack metadata service.
+ *
+ * @param verbosity Controls whether to generate debug to stdout. Zero:
+ * none. Non-zero: generate debug.
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES openstack_metadata(int verbosity);
+
+/**************************************************************************//**
+ * Initialize default values for vm_name and vm_uuid - for testing purposes.
+ *****************************************************************************/
+void openstack_metadata_initialize();
+
+/**************************************************************************//**
+ * Get the VM name provided by the metadata service.
+ *
+ * @returns VM name
+ *****************************************************************************/
+const char *openstack_vm_name();
+
+/**************************************************************************//**
+ * Get the VM UUID provided by the metadata service.
+ *
+ * @returns VM UUID
+ *****************************************************************************/
+const char *openstack_vm_uuid();
+
+#endif
diff --git a/vnfs/VES/code/evel_library/quickstart.md b/vnfs/VES/code/evel_library/quickstart.md
new file mode 100644
index 00000000..1c735cc4
--- /dev/null
+++ b/vnfs/VES/code/evel_library/quickstart.md
@@ -0,0 +1,445 @@
+# Quick Start Guide {#quickstart}
+
+# Introduction {#qs_intro}
+
+This Quick-Start section describes how to:
+
+ * Install and compile the supplied library code
+ * Integrate an existing project to use the EVEL library
+
+# Installation {#qs_install}
+
+The library is supplied as a source-code compressed-tar file. It is
+straightforward to install and build to integrate with an existing or new
+development project.
+
+## Unpack the Source Code {#qs_unpack}
+
+The file should unpacked into your development environment:
+```
+$ mkdir evel
+$ cd evel
+$ tar zxvf evel-library-package.tgz
+```
+### Satisfy Dependencies {#qs_depend}
+
+Note that all commands in this section are based on CentOS package management
+tools and you may need to substitute the appropriate tools/packages for your
+distribution, for example `apt-get` for Ubuntu.
+
+Ensure that GCC development tools are available.
+
+```
+$ sudo yum install gcc
+```
+Additionally, the library has a dependency on the cURL library, so you'll need
+the development tools for libCurl installed. (At runtime, only the runtime
+library is required, of course.)
+
+```
+$ sudo yum install libcurl-devel
+```
+If you wish to make the project documentation, then Doxygen and Graphviz are
+required. (Again, this is only in the development environment, not the runtime
+environment!)
+
+```
+$ sudo yum install doxygen graphviz
+```
+
+Note that some distributions have quite old versions of Doxygen by default and
+it may be necessary to install a later version to use all the features.
+
+If you want to build PDFs from the LaTeX you will need a texlive install.
+
+```
+$ sudo yum install texlive
+```
+
+### Test Build {#qs_build}
+Make sure that the library makes cleanly:
+
+```
+$ cd bldjobs
+$ make
+Making dependency file evel_unit.d for evel_unit.c
+Making dependency file evel_test_control.d for evel_test_control.c
+Making dependency file evel_demo.d for evel_demo.c
+Making dependency file jsmn.d for jsmn.c
+Making dependency file evel_logging.d for evel_logging.c
+Making dependency file evel_event_mgr.d for evel_event_mgr.c
+Making dependency file evel_internal_event.d for evel_internal_event.c
+Making dependency file evel_throttle.d for evel_throttle.c
+Making dependency file evel_syslog.d for evel_syslog.c
+Making dependency file evel_strings.d for evel_strings.c
+Making dependency file evel_state_change.d for evel_state_change.c
+Making dependency file evel_scaling_measurement.d for evel_scaling_measurement.c
+Making dependency file evel_signaling.d for evel_signaling.c
+Making dependency file evel_service.d for evel_service.c
+Making dependency file evel_reporting_measurement.d for evel_reporting_measurement.c
+Making dependency file evel_json_buffer.d for evel_json_buffer.c
+Making dependency file evel_other.d for evel_other.c
+Making dependency file evel_option.d for evel_option.c
+Making dependency file evel_mobile_flow.d for evel_mobile_flow.c
+Making dependency file evel_fault.d for evel_fault.c
+Making dependency file evel_event.d for evel_event.c
+Making dependency file double_list.d for double_list.c
+Making dependency file ring_buffer.d for ring_buffer.c
+Making dependency file metadata.d for metadata.c
+Making dependency file evel.d for evel.c
+Making evel.o from evel.c
+Making metadata.o from metadata.c
+Making ring_buffer.o from ring_buffer.c
+Making double_list.o from double_list.c
+Making evel_event.o from evel_event.c
+Making evel_fault.o from evel_fault.c
+Making evel_mobile_flow.o from evel_mobile_flow.c
+Making evel_option.o from evel_option.c
+Making evel_other.o from evel_other.c
+Making evel_json_buffer.o from evel_json_buffer.c
+Making evel_reporting_measurement.o from evel_reporting_measurement.c
+Making evel_service.o from evel_service.c
+Making evel_signaling.o from evel_signaling.c
+Making evel_scaling_measurement.o from evel_scaling_measurement.c
+Making evel_state_change.o from evel_state_change.c
+Making evel_strings.o from evel_strings.c
+Making evel_syslog.o from evel_syslog.c
+Making evel_throttle.o from evel_throttle.c
+Making evel_internal_event.o from evel_internal_event.c
+Making evel_event_mgr.o from evel_event_mgr.c
+Making evel_logging.o from evel_logging.c
+Making jsmn.o from jsmn.c
+Linking API Shared Library
+Linking API Static Library
+Making evel_demo.o from evel_demo.c
+Making evel_test_control.o from evel_test_control.c
+Linking EVEL demo
+Making EVEL training
+$
+```
+You should now be able to run the demo CLI application. Since it will want to
+dynamically link to the library that you've just made, you will need to set
+your `LD_LIBRARY_PATH` appropriately first. Make sure that you specify
+your actual directory paths correctly in the following:
+
+```
+$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/centos/evel/libs/x86_64
+$ ../output/x86_64/evel_demo
+evel_demo [--help]
+ --fqdn <domain>
+ --port <port_number>
+ [--path <path>]
+ [--topic <topic>]
+ [--username <username>]
+ [--password <password>]
+ [--https]
+ [--cycles <cycles>]
+ [--nothrott]
+
+Demonstrate use of the ECOMP Vendor Event Listener API.
+
+ -h Display this usage message.
+ --help
+
+ -f The FQDN or IP address to the RESTful API.
+ --fqdn
+
+ -n The port number the RESTful API.
+ --port
+
+ -p The optional path prefix to the RESTful API.
+ --path
+
+ -t The optional topic part of the RESTful API.
+ --topic
+
+ -u The optional username for basic authentication of requests.
+ --username
+
+ -w The optional password for basic authentication of requests.
+ --password
+
+ -s Use HTTPS rather than HTTP for the transport.
+ --https
+
+ -c Loop <cycles> times round the main loop. Default = 1.
+ --cycles
+
+ -v Generate much chattier logs.
+ --verbose
+
+ -x Exclude throttling commands from demonstration.
+ --nothrott
+
+$
+```
+Assuming that all worked as expected, you are ready to start integrating with
+your application. It probably makes sense to make the LD_LIBRARY_PATH change
+above permanent by incorporating it into your `.bash_profile` file.
+
+### Project Documentation {#qs_build_docs}
+
+The source comes with its own documentation included. The documentation can be
+built using the `docs` target in the Makefile. By default this builds HTML
+and LaTeX documentation, the latter being used to prepare PDFs.
+
+To make the documentation:
+```
+$ cd bldjobs
+$ make docs
+Cleaning docs...
+Making Doxygen documentation
+$
+```
+
+There is a make target that is intended to install the documentation on a
+"team server" - it will need adaptation for your team's environment - see the
+`docs_install` target in the Makefile:
+
+```
+$ make docs_install
+Cleaning docs...
+Making Doxygen documentation
+Copying docs to team web-server...
+Enter passphrase for key '/data/home/.ssh/id_rsa':
+annotated.html 100% 8088 7.9KB/s 00:00
+arrowdown.png 100% 246 0.2KB/s 00:00
+arrowright.png 100% 229 0.2KB/s 00:00
+ ...
+$
+```
+
+# Project Integration {#qs_integrate}
+
+There are two key steps to the integration which have to be undertaken:
+
+ * Initialization/Termination of the library.
+ * Creation & posting of individual events.
+
+Additionally, it may be necessary to consider changes to the EVEL library's
+source code if assumptions made by the library are either not satisfied or
+inconvenient. In particular:
+
+ * If the project already uses libcurl then the global initialization of the
+ library should be removed from the _EVEL Library_.
+ * The _EVEL Library_ uses `syslog` for event logging. If the project uses a
+ different event logging process, then EVEL's event logging macros should be
+ rewritten appropriately.
+
+These steps are considered in the [Normal Use](@ref qs_normal_use) and
+[EVEL Adaptation](@ref qs_adaptation) sections below.
+
+## Normal Use {#qs_normal_use}
+
+The _EVEL Library_ should be integrated with your project at a per-process
+level: each process is an independent client of the ECOMP Vendor Event Listener
+API.
+
+### Initialization {#qs_initialize}
+
+The _EVEL Library_ should be initialized before the process becomes
+multi-threaded. This constraint arises from the use of libcurl which imposes
+the constraint that initialization occurs before the system is multi-threaded.
+This is described in more detail in the libcurl documentation for the
+[curl_global_init](https://curl.haxx.se/libcurl/c/curl_global_init.html)
+function.
+
+Initialization stores configuration of the Vendor Event Listener API's details,
+such as the FQDN or IP address of the service, so the initializing process must
+have either extracted this information from its configuration or have this
+information "hard-wired" into the application, so that it is available at the
+point the `evel_initialize()` function is called:
+
+```C
+ #include "evel.h"
+ ...
+ if (evel_initialize(api_fqdn,
+ api_port,
+ api_path,
+ api_topic,
+ api_secure,
+ "Alice",
+ "This isn't very secure!",
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL demo client",
+ verbose_mode))
+ {
+ fprintf(stderr, "Failed to initialize the EVEL library!!!");
+ exit(-1);
+ }
+ ...
+```
+Once initialization has occurred successfully, the application may raise events
+and may also use the logging functions such as EVEL_INFO().
+
+Initialization is entirely local (there is no interaction with the service) so
+it is very unlikely to fail, unless the application environment is seriously
+degraded.
+
+### Event Generation {#qs_generate}
+
+Generating events is a two stage process:
+
+ 1. Firstly, the _EVEL Library_ is called to allocate an event of the correct
+ type.
+ * If this is successful, the caller is given a pointer to the event.
+ * All mandatory fields on the event are provided to this factory function
+ and are thereafter immutable.
+ * The application may add any necessary optional fields to the event, using
+ the pointer previously returned.
+ 2. The event is sent to the JSON API using the evel_post_event() function.
+ * At this point, the application relinquishes all responsibility for the
+ event:
+ * It will be posted to the JSON API, if possible.
+ * Whether or not the posting is successful, the memory used will be
+ freed.
+
+In practice this looks like:
+
+```C
+ #include "evel.h"
+ ...
+
+ /***************************************************************************/
+ /* Create a new Fault object, setting mandatory fields as we do so... */
+ /***************************************************************************/
+ fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR);
+ if (fault != NULL)
+ {
+ /*************************************************************************/
+ /* We have a Fault object - add some optional fields to it... */
+ /*************************************************************************/
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+
+ /*************************************************************************/
+ /* Finally, post the Fault. In practice this will only ever fail if */
+ /* local ring-buffer is full because of event overload. */
+ /*************************************************************************/
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ ...
+```
+### Event Types {#qs_event_types}
+
+The _EVEL Library_ supports the following types of events:
+
+ 1. Faults
+
+ These represent the **fault** domain in the event schema.
+
+ 2. Measurements
+
+ These represent the **measurementsForVfScaling** domain in the event
+ schema.
+
+ 3. Reports
+
+ This is an experimental type, designed to allow VNFs to report
+ application-level statistics unencumbered with platform measurements.
+ The formal AT&T schema has been updated to include this experimental
+ type as **measurementsForVfReporting**.
+
+ 4. Mobile Flow
+
+ These represent the **mobileFlow** domain in the event schema.
+
+ 5. Other
+
+ These represent the **other** domain in the event schema.
+
+ 6. Service Events
+
+ These represent the **serviceEvents** domain in the event schema.
+
+ 7. Signaling
+
+ These represent the **signaling** domain in the event schema.
+
+ 8. State Change
+
+ These represent the **stateChange** domain in the event schema.
+
+ 9. Syslog
+
+ These represent the **syslog** domain in the event schema.
+
+### Throttling {#qs_throttling}
+
+The _EVEL library_ supports the following command types as defined in the JSON API:
+
+ 1. commandType: throttlingSpecification
+
+ This is handled internally by the EVEL library, which stores the provided
+ throttling specification internally and applies it to all subsequent events.
+
+ 2. commandType: provideThrottlingState
+
+ This is handled internally by the EVEL library, which returns the current
+ throttling specification for each domain.
+
+ 3. commandType: measurementIntervalChange
+
+ This is handled by the EVEL library, which makes the latest measurement
+ interval available via the ::evel_get_measurement_interval function.
+ The application is responsible for checking and adhering to the latest
+ provided interval.
+
+### Termination {#qs_termination}
+
+Termination of the _EVEL Library_ is swift and brutal! Events in the buffer
+at the time are "dropped on the floor" rather than waiting for the buffer to
+deplete first.
+
+```C
+ #include "evel.h"
+ ...
+
+ /***************************************************************************/
+ /* Shutdown the library. */
+ /***************************************************************************/
+ evel_terminate();
+
+ ...
+```
+
+## EVEL Adaptation {#qs_adaptation}
+
+The _EVEL Library_ is relatively simple and should be easy to adapt into other
+project environments.
+
+### LibcURL Lifecycle
+
+There are two circumstances where initialization of libcurl may be required:
+
+ 1. If libcurl is used by the project already, and therefore already takes
+ responsibility of its initialization, then the libcurl initialization and
+ termination functions should be removed from evel_initialize() and
+ evel_terminate() respectively.
+ 2. If the project is unable to satisfy the constraint that libcurl
+ initialization takes place in a single-threaded environment at the point
+ that the _EVEL Library_ can be initialized (for example, if MT code is
+ necessary to read the configuration parameters required for
+ _EVEL Library_ initialization) then it may be necessary to extract the
+ libcurl functions and call them separately, earlier in the program's
+ operation.
+
+### Event Logging
+
+The _EVEL Library_ uses `syslog` for logging. If this is inappropriate then
+the log_debug() and log_initialize() functions should be rewritten accordingly.
+
+**Note**: it would be a really bad idea to use the _EVEL Library_ itself for this
+logging function.
+[Turtles all the way down...](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)
+
+ \ No newline at end of file
diff --git a/vnfs/VES/code/evel_library/readme.md b/vnfs/VES/code/evel_library/readme.md
new file mode 100644
index 00000000..3cf57083
--- /dev/null
+++ b/vnfs/VES/code/evel_library/readme.md
@@ -0,0 +1,236 @@
+# EVEL Library Overview {#mainpage}
+
+# Introduction
+
+The ECOMP Vendor Event Listener ("EVEL") library encapsulates the use of
+AT&T's JSON API to the collector function within the ECOMP infrastructure.
+
+As such, it provides a reference implementation of the EVEL JSON API which
+can either be directly as part of a project or can be used to inform the
+independent implementation of an equivalent binding to the API in another
+development environment.
+
+This section provides an overview of the library and how it is integrated
+into the target application. If all you want is a set of instructions to
+get you started, the @ref quickstart "Quick Start" section is for you. If
+you want a more in-depth understanding of the _EVEL Library_ then this section
+provides an overview and then you can read the detailed API documentation for
+each function. The documentation for evel.h is a good starting point, since
+that defines the public API of the _EVEL Library_.
+
+# Library Structure
+
+The API is designed to be used on multi-process platforms where each process
+may be multi-threaded. Each process using this library will create an
+independent HTTP client (using libcURL). Each process will have a single
+thread running the HTTP client but that thread receives work on a
+ring-buffer from however may threads are required to implement the function.
+
+**Note**: libcurl imposes a constraint that it is initialized before
+the process starts multi-threaded operation.
+
+# Typical Usage
+
+The library is designed to be very straightforward to use and lightweight to
+integrate into projects. The only serious external dependency is on libcURL.
+
+The supplied Makefile produces a single library **libevel.so** or
+**libevel.a** which your application needs to be linked against.
+
+Each process within the application which wants to generate events needs to
+call ::evel_initialize at the start of day (observing the above warning
+about not being MT safe at this stage.) The initialization specifies the
+details of where the API is located. Management of configuration is the
+responsibility of the client.
+
+Once initialized, and now MT-safe, there are factory functions to produce
+new events:
+- Faults - ::evel_new_fault
+- Measurements - ::evel_new_measurement
+- Report - ::evel_new_report
+- State Change - ::evel_new_state_change
+- Syslog - ::evel_new_syslog
+- Other - ::evel_new_other
+- Mobile Flow - ::evel_new_mobile_flow
+
+There is also a factory function ::evel_new_mobile_gtp_flow_metrics to create
+the parameter gtp_per_flow_metrics, which is then configured and passed to the
+::evel_new_mobile_flow factory function.
+
+The event structures are initialized with mandatory fields at the point of
+creation and optional fields may be added thereafter. Once set, values in
+the structures are immutable.
+
+Once the event is prepared, it may be posted, using ::evel_post_event, at
+which point the calling thread relinquishes all responsibility for the
+event. It will be freed once successfully or unsuccessfully posted to the
+API. If, for any reason, you change your mind and don't want to post a
+created event, it must be destroyed with ::evel_free_event.
+
+Finally, at the end of day, the library can be terminated cleanly by calling
+::evel_terminate.
+
+## Example Code
+
+The following fragment illustrates the above usage:
+
+```C
+
+ if (evel_initialize(api_fqdn,
+ api_port,
+ api_path,
+ api_topic,
+ api_secure,
+ "Alice",
+ "This isn't very secure!",
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL demo client",
+ verbose_mode))
+ {
+ fprintf(stderr, "Failed to initialize the EVEL library!!!");
+ exit(-1);
+ }
+
+ ...
+
+ fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR);
+ if (fault != NULL)
+ {
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+
+```
+
+The public API to the library is defined in evel.h. The internal APIs
+within library are defined in separate headers (<em>e.g.</em>
+evel_internal.h), but these should not need to be included by the code
+using the library.
+
+# Example Application
+
+A simple command-line application to generate events is provided as part of
+the source package (the above code fragment is taken from that application).
+
+The following illustrates its operation to a co-located "test-collector":
+```
+$ ./evel_demo --fqdn 127.0.0.1 --port 30000 --path vendor_event_listener --topic example_vnf --verbose
+./evel_demo built Feb 26 2016 18:14:48
+* About to connect() to 169.254.169.254 port 80 (#0)
+* Trying 169.254.169.254... * Timeout
+* connect() timed out!
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+* Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 510
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+<
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+* Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 865
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+<
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+* Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 2325
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+<
+* Closing connection #0
+^C
+
+Interrupted - quitting!
+$
+```
+
+# Restrictions and Limitations
+
+## Constraint Validation
+
+The _EVEL Library_ has been designed to be production-safe code with the
+emphasis at this stage being in correctness of operation rather than
+raw performance.
+
+The API tries to check as much information as possible to avoid misuse and
+will **assert()** if constraints are not satisfied. This is likely to lead
+to the rapid discovery of coding errors by programmers, but does mean that
+the application can fail abruptly if the library is misused in any way.
+
+## Performance
+
+The default Makefile avoids aggressive optimizations so that any core-files
+are easy to interpret. Production code should use greater optimization
+levels.
+
+As described above, the HTTP client is single threaded and will run all
+transactions synchronously. As transactions are serialized, a client that
+generates a lot of events will be paced by the round-trip time.
+
+It would be a straightforward enhancement to use the multi-thread API into
+libcurl and use a pool of client threads to run transactions in parallel if
+this ever became a bottleneck.
+
+## Logging
+
+The initialization of the library includes the log verbosity. The verbose
+operation makes the library very chatty so syslog may get rather clogged
+with detailed diagnostics. It is possible to configure syslog to put these
+events into a separate file. A trivial syslog.conf file would be:
+
+```
+
+# Log all user messages so debug information is captured.
+
+user.* /var/log/debug
+```
+
+If verbose logging is enabled, the cURL library will generate information
+about the HTTP operations on **stdout**.
+
diff --git a/vnfs/VES/code/evel_library/ring_buffer.c b/vnfs/VES/code/evel_library/ring_buffer.c
new file mode 100644
index 00000000..3795ed36
--- /dev/null
+++ b/vnfs/VES/code/evel_library/ring_buffer.c
@@ -0,0 +1,206 @@
+/**************************************************************************//**
+ * @file
+ * A ring buffer with multi-threaded synchronization.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <malloc.h>
+
+#include "ring_buffer.h"
+#include "evel.h"
+
+/**************************************************************************//**
+ * Ring buffer initialization.
+ *
+ * Initialize the buffer supplied to the specified size.
+ *
+ * @param buffer Pointer to the ring-buffer to be initialized.
+ * @param size How many elements to be stored in the ring-buffer.
+ *
+ * @returns Nothing
+******************************************************************************/
+void ring_buffer_initialize(ring_buffer * buffer, int size)
+{
+ int pthread_rc = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(buffer != NULL);
+ assert(size > 0);
+
+ /***************************************************************************/
+ /* Initialize the synchronization objects. */
+ /***************************************************************************/
+ pthread_rc = pthread_mutex_init(&buffer->ring_mutex, NULL);
+ assert(pthread_rc == 0);
+ pthread_rc = pthread_cond_init(&buffer->ring_cv, NULL);
+ assert(pthread_rc == 0);
+
+ /***************************************************************************/
+ /* Allocate the ring buffer itself. */
+ /***************************************************************************/
+ buffer->ring = malloc(size * sizeof(void *));
+ assert(buffer->ring != NULL);
+
+ /***************************************************************************/
+ /* Initialize the ring as empty. */
+ /***************************************************************************/
+ buffer->next_write = 0;
+ buffer->next_read = 0;
+ buffer->size = size;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Read an element from a ring_buffer.
+ *
+ * Reads an element from the ring_buffer, advancing the next-read position.
+ * Operation is synchronized and therefore MT-safe. Blocks if no data is
+ * available.
+ *
+ * @param buffer Pointer to the ring-buffer to be read.
+ *
+ * @returns Pointer to the element read from the buffer.
+******************************************************************************/
+void * ring_buffer_read(ring_buffer * buffer)
+{
+ void *msg = NULL;
+ EVEL_DEBUG("RBR: Ring buffer read");
+
+ pthread_mutex_lock(&buffer->ring_mutex);
+ while (1)
+ {
+ EVEL_DEBUG("RBR: got lock. NR=%d NW=%d",
+ buffer->next_read,
+ buffer->next_write);
+ if(buffer->next_read != buffer->next_write)
+ {
+ EVEL_DEBUG("RBR: buffer has item available");
+ msg = (buffer->ring)[buffer->next_read];
+ buffer->ring[buffer->next_read] = NULL;
+ buffer->next_read = (buffer->next_read + 1) % buffer->size;
+ EVEL_DEBUG("RBR: next read location is %d", buffer->next_read);
+ pthread_mutex_unlock(&buffer->ring_mutex);
+ break;
+ }
+ else
+ {
+ EVEL_DEBUG("RBR: Waiting for condition variable");
+ pthread_cond_wait(&buffer->ring_cv, &buffer->ring_mutex);
+ EVEL_DEBUG("RBR: Condition variable wait completed");
+ }
+ }
+ EVEL_DEBUG("RBR: Ring buffer read returning data at %lp", msg);
+ return msg;
+}
+
+/**************************************************************************//**
+ * Write an element into a ring_buffer.
+ *
+ * Writes an element into the ring_buffer, advancing the next-write position.
+ * Operation is synchronized and therefore MT-safe. Fails if the buffer is
+ * full without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be written.
+ * @param msg Pointer to data to be stored in the ring_buffer.
+ *
+ * @returns Number of items written.
+ * @retval 1 The data was written successfully.
+ * @retval 0 The ring_buffer was full so no data written.
+******************************************************************************/
+int ring_buffer_write(ring_buffer * buffer, void * msg)
+{
+ int item_count = 0;
+ int items_written = 0;
+ EVEL_DEBUG("RBW: Ring Buffer Write message at %lp", msg);
+
+ pthread_mutex_lock(&buffer->ring_mutex);
+ EVEL_DEBUG("RBW: got lock. NR=%d NW=%d SZ=%d",
+ buffer->next_read,
+ buffer->next_write,
+ buffer->size);
+
+ item_count = (buffer->next_write - buffer->next_read) % buffer->size;
+ if (item_count < 0)
+ {
+ item_count += buffer->size;
+ }
+ if (item_count < buffer->size - 1)
+ {
+ EVEL_DEBUG("RBW: %d items in buffer", item_count);
+ buffer->ring[buffer->next_write] = msg;
+ buffer->next_write = (buffer->next_write + 1) % buffer->size;
+ EVEL_DEBUG("RBW: next write location is %d", buffer->next_write);
+ items_written = 1;
+ }
+ else
+ {
+ EVEL_ERROR("RBW: ring buffer full - unable to write event");
+ }
+
+ pthread_mutex_unlock(&buffer->ring_mutex);
+ EVEL_DEBUG("RBW: released lock");
+ pthread_cond_signal(&buffer->ring_cv);
+
+ return items_written;
+}
+
+/**************************************************************************//**
+ * Tests whether there is data in the ring_buffer.
+ *
+ * Tests whether there is currently data in the ring_buffer without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be tested.
+ *
+ * @returns Whether there is data in the ring_buffer.
+ * @retval 0 There isn't any data in the ring_buffer.
+ * @retval 1 There is data in the ring_buffer.
+******************************************************************************/
+int ring_buffer_is_empty(ring_buffer * buffer)
+{
+ int is_empty = 0;
+ EVEL_DEBUG("RBE: Ring empty check");
+
+ pthread_mutex_lock(&buffer->ring_mutex);
+ is_empty = (buffer->next_read == buffer->next_write);
+ pthread_mutex_unlock(&buffer->ring_mutex);
+
+ EVEL_DEBUG("RBE: Ring state= %d", is_empty);
+ return is_empty;
+}
+
diff --git a/vnfs/VES/code/evel_library/ring_buffer.h b/vnfs/VES/code/evel_library/ring_buffer.h
new file mode 100644
index 00000000..c6870508
--- /dev/null
+++ b/vnfs/VES/code/evel_library/ring_buffer.h
@@ -0,0 +1,109 @@
+#ifndef RING_BUFFER_INCLUDED
+#define RING_BUFFER_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * A ring buffer.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <pthread.h>
+
+/**************************************************************************//**
+ * Ring buffer structure.
+ *****************************************************************************/
+typedef struct ring_buffer
+{
+ int size;
+ int next_write;
+ int next_read;
+ void ** ring;
+ pthread_cond_t ring_cv;
+ pthread_mutex_t ring_mutex;
+} ring_buffer;
+
+/**************************************************************************//**
+ * Ring buffer initialization.
+ *
+ * Initialize the buffer supplied to the specified size.
+ *
+ * @param buffer Pointer to the ring-buffer to be initialized.
+ * @param size How many elements to be stored in the ring-buffer.
+ *
+ * @returns Nothing
+******************************************************************************/
+void ring_buffer_initialize(ring_buffer * buffer, int size);
+
+/**************************************************************************//**
+ * Read an element from a ring_buffer.
+ *
+ * Reads an element from the ring_buffer, advancing the next-read position.
+ * Operation is synchronized and therefore MT-safe. Blocks if no data is
+ * available.
+ *
+ * @param buffer Pointer to the ring-buffer to be read.
+ *
+ * @returns Pointer to the element read from the buffer.
+******************************************************************************/
+void * ring_buffer_read(ring_buffer * buffer);
+
+/**************************************************************************//**
+ * Write an element into a ring_buffer.
+ *
+ * Writes an element into the ring_buffer, advancing the next-write position.
+ * Operation is synchronized and therefore MT-safe. Fails if the buffer is
+ * full without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be written.
+ * @param msg Pointer to data to be stored in the ring_buffer.
+ *
+ * @returns Number of items written.
+ * @retval 1 The data was written successfully.
+ * @retval 0 The ring_buffer was full so no data written.
+******************************************************************************/
+int ring_buffer_write(ring_buffer * buffer, void * msg);
+
+/**************************************************************************//**
+ * Tests whether there is data in the ring_buffer.
+ *
+ * Tests whether there is currently data in the ring_buffer without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be tested.
+ *
+ * @returns Whether there is data in the ring_buffer.
+ * @retval 0 There isn't any data in the ring_buffer.
+ * @retval 1 There is data in the ring_buffer.
+******************************************************************************/
+int ring_buffer_is_empty(ring_buffer * buffer);
+
+#endif