summaryrefslogtreecommitdiffstats
path: root/veslibrary/ves_clibrary/evel/evel-library/code
diff options
context:
space:
mode:
authorGokul Singaraju <goksing@gmail.com>2017-09-21 12:51:55 -0400
committerGokul Singaraju <goksing@gmail.com>2017-09-21 12:55:40 -0400
commita43e38e7bdc183709399bc49179b7137c6debe23 (patch)
tree49fe0e277d7b4065e1f5e57b17ad1c7b3e631481 /veslibrary/ves_clibrary/evel/evel-library/code
parentd5ffdf731a1f163728c859ece5c861f6c403e4d7 (diff)
Adding C and Java VES Vendor libs
Issue-Id: VNFRQTS-94 Change-Id: Iee0e154a94f3ef4ea43efcd474acacb0fa54c43f Signed-Off-by: Gokul Singaraju <goksing@gmail.com>
Diffstat (limited to 'veslibrary/ves_clibrary/evel/evel-library/code')
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c182
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h57
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c396
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h4494
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c755
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c1050
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c367
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c269
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h858
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c113
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c870
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c446
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c167
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c2122
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c526
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c492
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c437
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c3716
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c574
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c286
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c473
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c505
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c531
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c2103
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h214
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c640
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c222
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h97
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c328
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h93
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md81
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c592
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h58
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md445
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md236
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c192
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h96
-rw-r--r--veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c3484
38 files changed, 28567 insertions, 0 deletions
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c
new file mode 100644
index 0000000..6ce8a80
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c
@@ -0,0 +1,182 @@
+
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * A simple double-linked list.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ ****************************************************************************/
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h
new file mode 100644
index 0000000..5cf7e1a
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h
@@ -0,0 +1,57 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * A simple double-linked list.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ ****************************************************************************/
+
+#ifndef DOUBLE_LIST_INCLUDED
+#define DOUBLE_LIST_INCLUDED
+
+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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c
new file mode 100644
index 0000000..20b386d
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c
@@ -0,0 +1,396 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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.
+ *
+ ****************************************************************************/
+
+#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_HEARTBEAT_FIELD:
+ EVEL_DEBUG("Event is a Heartbeat Field Event at %lp", evt_ptr);
+ evel_free_hrtbt_field((EVENT_HEARTBEAT_FIELD *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_HEARTBEAT_FIELD));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_SIPSIGNALING:
+ 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;
+
+ case EVEL_DOMAIN_VOICE_QUALITY:
+ EVEL_DEBUG("Event is an VoiceQuality at %lp", evt_ptr);
+ evel_free_voice_quality((EVENT_VOICE_QUALITY *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_VOICE_QUALITY));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_THRESHOLD_CROSS:
+ EVEL_DEBUG("Event is a Threshold crossing at %lp", evt_ptr);
+ evel_free_threshold_cross((EVENT_THRESHOLD_CROSS *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_THRESHOLD_CROSS));
+ free(evt_ptr);
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);
+ assert(0);
+ }
+ }
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h
new file mode 100644
index 0000000..0ae1713
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h
@@ -0,0 +1,4494 @@
+#ifndef EVEL_INCLUDED
+#define EVEL_INCLUDED
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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.
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "jsmn.h"
+#include "double_list.h"
+#include "hashtable.h"
+
+/*****************************************************************************/
+/* Supported API version. */
+/*****************************************************************************/
+#define EVEL_API_MAJOR_VERSION 5
+#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_HEARTBEAT_FIELD,/** A Heartbeat field event. */
+ EVEL_DOMAIN_SIPSIGNALING, /** A Signaling event. */
+ EVEL_DOMAIN_STATE_CHANGE, /** A State Change event. */
+ EVEL_DOMAIN_SYSLOG, /** A Syslog event. */
+ EVEL_DOMAIN_OTHER, /** Another event. */
+ EVEL_DOMAIN_THRESHOLD_CROSS, /** A Threshold Crossing Event */
+ EVEL_DOMAIN_VOICE_QUALITY, /** A Voice Quality 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;
+
+/**************************************************************************//**
+ * enrichment fields for internal VES Event Listener service use only,
+ * not supplied by event sources
+ *****************************************************************************/
+typedef struct internal_header_fields
+{
+ void *object;
+ EVEL_BOOLEAN is_set;
+} EVEL_OPTION_INTHEADER_FIELDS;
+
+/*****************************************************************************/
+/* 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 * event_name;
+ char * source_name;
+ 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;
+ EVEL_OPTION_INTHEADER_FIELDS internal_field;
+ EVEL_OPTION_STRING nfcnaming_code;
+ EVEL_OPTION_STRING nfnaming_code;
+
+} EVENT_HEADER;
+
+/*****************************************************************************/
+/* Supported Fault version. */
+/*****************************************************************************/
+#define EVEL_FAULT_MAJOR_VERSION 2
+#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 category;
+ 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;
+
+
+/**************************************************************************//**
+ * optional field block for fields specific to heartbeat events
+ *****************************************************************************/
+typedef struct event_heartbeat_fields
+{
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ double heartbeat_version;
+ int heartbeat_interval;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ DLIST additional_info;
+
+} EVENT_HEARTBEAT_FIELD;
+
+/**************************************************************************//**
+ * tuple which provides the name of a key along with its value and
+ * relative order
+ *****************************************************************************/
+typedef struct internal_key
+{
+ char *keyname;
+ EVEL_OPTION_INT keyorder;
+ EVEL_OPTION_STRING keyvalue;
+} EVEL_INTERNAL_KEY;
+
+/**************************************************************************//**
+ * meta-information about an instance of a jsonObject along with
+ * the actual object instance
+ *****************************************************************************/
+typedef struct json_object_instance
+{
+
+ char *jsonstring;
+ unsigned long long objinst_epoch_microsec;
+ DLIST object_keys; /*EVEL_INTERNAL_KEY list */
+
+} EVEL_JSON_OBJECT_INSTANCE;
+#define MAX_JSON_TOKENS 128
+/**************************************************************************//**
+ * Create a new json object instance.
+ *
+ * @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.
+ * @param yourjson json string.
+ * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT_INSTANCE.
+ * not used (i.e. posted) it must be released using ::evel_free_jsonobjectinstance.
+ * @retval NULL Failed to create the json object instance.
+ *****************************************************************************/
+EVEL_JSON_OBJECT_INSTANCE * evel_new_jsonobjinstance(const char *const yourjson);
+/**************************************************************************//**
+ * Free an json object instance.
+ *
+ * Free off the json object instance supplied.
+ * Will free all the contained allocated memory.
+ *
+ *****************************************************************************/
+void evel_free_jsonobjinst(EVEL_JSON_OBJECT_INSTANCE * objinst);
+
+/**************************************************************************//**
+ * enrichment fields for internal VES Event Listener service use only,
+ * not supplied by event sources
+ *****************************************************************************/
+typedef struct json_object
+{
+
+ char *object_name;
+ EVEL_OPTION_STRING objectschema;
+ EVEL_OPTION_STRING objectschemaurl;
+ EVEL_OPTION_STRING nfsubscribedobjname;
+ EVEL_OPTION_STRING nfsubscriptionid;
+ DLIST jsonobjectinstances; /* EVEL_JSON_OBJECT_INSTANCE list */
+
+} EVEL_JSON_OBJECT;
+
+/**************************************************************************//**
+ * Create a new json object.
+ *
+ * @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.
+ * @param name name of the object.
+ * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT.
+ * not used (i.e. posted) it must be released using ::evel_free_jsonobject.
+ * @retval NULL Failed to create the json object.
+ *****************************************************************************/
+EVEL_JSON_OBJECT * evel_new_jsonobject(const char *const name);
+/**************************************************************************//**
+ * Free an json object.
+ *
+ * Free off the json object instance supplied.
+ * Will free all the contained allocated memory.
+ *
+ *****************************************************************************/
+void evel_free_jsonobject(EVEL_JSON_OBJECT * jsobj);
+/*****************************************************************************/
+/* Supported Measurement version. */
+/*****************************************************************************/
+#define EVEL_MEASUREMENT_MAJOR_VERSION 2
+#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_info;
+ DLIST additional_measurements;
+ DLIST additional_objects;
+ DLIST codec_usage;
+ EVEL_OPTION_INT concurrent_sessions;
+ EVEL_OPTION_INT configured_entities;
+ DLIST cpu_usage;
+ DLIST disk_usage;
+ MEASUREMENT_ERRORS * errors;
+ DLIST feature_usage;
+ DLIST filesystem_usage;
+ DLIST latency_distribution;
+ EVEL_OPTION_DOUBLE mean_request_latency;
+ DLIST mem_usage;
+ EVEL_OPTION_INT media_ports_in_use;
+ EVEL_OPTION_INT request_rate;
+ EVEL_OPTION_INT vnfc_scaling_metric;
+ DLIST vnic_usage;
+
+} EVENT_MEASUREMENT;
+
+/**************************************************************************//**
+ * CPU Usage.
+ * JSON equivalent field: cpuUsage
+ *****************************************************************************/
+typedef struct measurement_cpu_use {
+ char * id;
+ double usage;
+ EVEL_OPTION_DOUBLE idle;
+ EVEL_OPTION_DOUBLE intrpt;
+ EVEL_OPTION_DOUBLE nice;
+ EVEL_OPTION_DOUBLE softirq;
+ EVEL_OPTION_DOUBLE steal;
+ EVEL_OPTION_DOUBLE sys;
+ EVEL_OPTION_DOUBLE user;
+ EVEL_OPTION_DOUBLE wait;
+} MEASUREMENT_CPU_USE;
+
+
+/**************************************************************************//**
+ * Disk Usage.
+ * JSON equivalent field: diskUsage
+ *****************************************************************************/
+typedef struct measurement_disk_use {
+ char * id;
+ EVEL_OPTION_DOUBLE iotimeavg;
+ EVEL_OPTION_DOUBLE iotimelast;
+ EVEL_OPTION_DOUBLE iotimemax;
+ EVEL_OPTION_DOUBLE iotimemin;
+ EVEL_OPTION_DOUBLE mergereadavg;
+ EVEL_OPTION_DOUBLE mergereadlast;
+ EVEL_OPTION_DOUBLE mergereadmax;
+ EVEL_OPTION_DOUBLE mergereadmin;
+ EVEL_OPTION_DOUBLE mergewriteavg;
+ EVEL_OPTION_DOUBLE mergewritelast;
+ EVEL_OPTION_DOUBLE mergewritemax;
+ EVEL_OPTION_DOUBLE mergewritemin;
+ EVEL_OPTION_DOUBLE octetsreadavg;
+ EVEL_OPTION_DOUBLE octetsreadlast;
+ EVEL_OPTION_DOUBLE octetsreadmax;
+ EVEL_OPTION_DOUBLE octetsreadmin;
+ EVEL_OPTION_DOUBLE octetswriteavg;
+ EVEL_OPTION_DOUBLE octetswritelast;
+ EVEL_OPTION_DOUBLE octetswritemax;
+ EVEL_OPTION_DOUBLE octetswritemin;
+ EVEL_OPTION_DOUBLE opsreadavg;
+ EVEL_OPTION_DOUBLE opsreadlast;
+ EVEL_OPTION_DOUBLE opsreadmax;
+ EVEL_OPTION_DOUBLE opsreadmin;
+ EVEL_OPTION_DOUBLE opswriteavg;
+ EVEL_OPTION_DOUBLE opswritelast;
+ EVEL_OPTION_DOUBLE opswritemax;
+ EVEL_OPTION_DOUBLE opswritemin;
+ EVEL_OPTION_DOUBLE pendingopsavg;
+ EVEL_OPTION_DOUBLE pendingopslast;
+ EVEL_OPTION_DOUBLE pendingopsmax;
+ EVEL_OPTION_DOUBLE pendingopsmin;
+ EVEL_OPTION_DOUBLE timereadavg;
+ EVEL_OPTION_DOUBLE timereadlast;
+ EVEL_OPTION_DOUBLE timereadmax;
+ EVEL_OPTION_DOUBLE timereadmin;
+ EVEL_OPTION_DOUBLE timewriteavg;
+ EVEL_OPTION_DOUBLE timewritelast;
+ EVEL_OPTION_DOUBLE timewritemax;
+ EVEL_OPTION_DOUBLE timewritemin;
+
+} MEASUREMENT_DISK_USE;
+
+/**************************************************************************//**
+ * Add an additional Disk 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 Disk utilization.
+ *****************************************************************************/
+MEASUREMENT_DISK_USE * evel_measurement_new_disk_use_add(EVENT_MEASUREMENT * measurement, char * id);
+
+/**************************************************************************//**
+ * Filesystem Usage.
+ * JSON equivalent field: filesystemUsage
+ *****************************************************************************/
+typedef struct measurement_fsys_use {
+ char * filesystem_name;
+ double block_configured;
+ double block_iops;
+ double block_used;
+ double ephemeral_configured;
+ double ephemeral_iops;
+ double ephemeral_used;
+} MEASUREMENT_FSYS_USE;
+
+/**************************************************************************//**
+ * Memory Usage.
+ * JSON equivalent field: memoryUsage
+ *****************************************************************************/
+typedef struct measurement_mem_use {
+ char * id;
+ char * vmid;
+ double membuffsz;
+ EVEL_OPTION_DOUBLE memcache;
+ EVEL_OPTION_DOUBLE memconfig;
+ EVEL_OPTION_DOUBLE memfree;
+ EVEL_OPTION_DOUBLE slabrecl;
+ EVEL_OPTION_DOUBLE slabunrecl;
+ EVEL_OPTION_DOUBLE memused;
+} MEASUREMENT_MEM_USE;
+
+/**************************************************************************//**
+ * Add an additional Memory 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 Memory identifier.
+ * @param vmidentifier ASCIIZ string with the VM's identifier.
+ * @param membuffsz Memory Size.
+ *
+ * @return Returns pointer to memory use structure in measurements
+ *****************************************************************************/
+MEASUREMENT_MEM_USE * evel_measurement_new_mem_use_add(EVENT_MEASUREMENT * measurement,
+ char * id, char *vmidentifier, double membuffsz);
+
+/**************************************************************************//**
+ * Set kilobytes of memory used for cache
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_memcache_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val);
+/**************************************************************************//**
+ * Set kilobytes of memory configured in the virtual machine on which the VNFC reporting
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_memconfig_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val);
+/**************************************************************************//**
+ * Set kilobytes of physical RAM left unused by the system
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_memfree_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val);
+/**************************************************************************//**
+ * Set the part of the slab that can be reclaimed such as caches measured in kilobytes
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_slab_reclaimed_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val);
+/**************************************************************************//**
+ * Set the part of the slab that cannot be reclaimed such as caches measured in kilobytes
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_slab_unreclaimable_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val);
+/**************************************************************************//**
+ * Set the total memory minus the sum of free, buffered, cached and slab memory in kilobytes
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_usedup_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val);
+/**************************************************************************//**
+ * 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_performance {
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ /*Cumulative count of broadcast packets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_bcast_packets_acc;
+ /*Count of broadcast packets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_bcast_packets_delta;
+ /*Cumulative count of discarded packets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_discarded_packets_acc;
+ /*Count of discarded packets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_discarded_packets_delta;
+ /*Cumulative count of error packets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_error_packets_acc;
+ /*Count of error packets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_error_packets_delta;
+ /*Cumulative count of multicast packets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_mcast_packets_acc;
+ /*Count of mcast packets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_mcast_packets_delta;
+ /*Cumulative count of octets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_octets_acc;
+ /*Count of octets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_octets_delta;
+ /*Cumulative count of all packets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_total_packets_acc;
+ /*Count of all packets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_total_packets_delta;
+ /*Cumulative count of unicast packets received as read at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_ucast_packets_acc;
+ /*Count of unicast packets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE recvd_ucast_packets_delta;
+ /*Cumulative count of transmitted broadcast packets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_bcast_packets_acc;
+ /*Count of transmitted broadcast packets within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_bcast_packets_delta;
+ /*Cumulative count of transmit discarded packets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_discarded_packets_acc;
+ /*Count of transmit discarded packets within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_discarded_packets_delta;
+ /*Cumulative count of transmit error packets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_error_packets_acc;
+ /*Count of transmit error packets within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_error_packets_delta;
+ /*Cumulative count of transmit multicast packets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_mcast_packets_acc;
+ /*Count of transmit multicast packets within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_mcast_packets_delta;
+ /*Cumulative count of transmit octets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_octets_acc;
+ /*Count of transmit octets received within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_octets_delta;
+ /*Cumulative count of all transmit packets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_total_packets_acc;
+ /*Count of transmit packets within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_total_packets_delta;
+ /*Cumulative count of all transmit unicast packets at the end of
+ the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_ucast_packets_acc;
+ /*Count of transmit unicast packets within the measurement interval*/
+ EVEL_OPTION_DOUBLE tx_ucast_packets_delta;
+ /* Indicates whether vNicPerformance values are likely inaccurate
+ due to counter overflow or other condtions*/
+ char *valuesaresuspect;
+ char *vnic_id;
+
+} MEASUREMENT_VNIC_PERFORMANCE;
+
+/**************************************************************************//**
+ * 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 2
+
+/**************************************************************************//**
+ * 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;
+ DLIST additional_info; /* JSON: additionalFields */
+
+ /***************************************************************************/
+ /* 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;
+
+/*****************************************************************************/
+/* Supported Other field version. */
+/*****************************************************************************/
+#define EVEL_OTHER_EVENT_MAJOR_VERSION 1
+#define EVEL_OTHER_EVENT_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Other.
+ * JSON equivalent field: otherFields
+ *****************************************************************************/
+typedef struct event_other {
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ HASHTABLE_T *namedarrays; /* HASHTABLE_T */
+ DLIST jsonobjects; /* DLIST of EVEL_JSON_OBJECT */
+ DLIST namedvalues;
+} EVENT_OTHER;
+
+/**************************************************************************//**
+ * Other Field.
+ * JSON equivalent field: otherFields
+ *****************************************************************************/
+typedef struct other_field {
+ char * name;
+ char * value;
+} OTHER_FIELD;
+
+
+/*****************************************************************************/
+/* Supported Service Events version. */
+/*****************************************************************************/
+#define EVEL_HEARTBEAT_FIELD_MAJOR_VERSION 1
+#define EVEL_HEARTBEAT_FIELD_MINOR_VERSION 1
+
+
+/*****************************************************************************/
+/* Supported Signaling version. */
+/*****************************************************************************/
+#define EVEL_SIGNALING_MAJOR_VERSION 2
+#define EVEL_SIGNALING_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Vendor VNF Name fields.
+ * JSON equivalent field: vendorVnfNameFields
+ *****************************************************************************/
+typedef struct vendor_vnfname_field {
+ char * vendorname;
+ EVEL_OPTION_STRING vfmodule;
+ EVEL_OPTION_STRING vnfname;
+} VENDOR_VNFNAME_FIELD;
+
+/**************************************************************************//**
+ * Signaling.
+ * JSON equivalent field: signalingFields
+ *****************************************************************************/
+typedef struct event_signaling {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ VENDOR_VNFNAME_FIELD vnfname_field;
+ 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 */
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING compressed_sip; /* JSON: compressedSip */
+ EVEL_OPTION_STRING summary_sip; /* JSON: summarySip */
+ DLIST additional_info;
+
+} EVENT_SIGNALING;
+
+/**************************************************************************//**
+ * Sgnaling Additional Field.
+ * JSON equivalent field: additionalFields
+ *****************************************************************************/
+typedef struct signaling_additional_field {
+ char * name;
+ char * value;
+} SIGNALING_ADDL_FIELD;
+
+/*****************************************************************************/
+/* Supported State Change version. */
+/*****************************************************************************/
+#define EVEL_STATE_CHANGE_MAJOR_VERSION 1
+#define EVEL_STATE_CHANGE_MINOR_VERSION 2
+
+/**************************************************************************//**
+ * 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;
+ double version;
+
+ /***************************************************************************/
+ /* 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 2
+
+/**************************************************************************//**
+ * 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 */
+ /***************************************************************************/
+ EVEL_OPTION_STRING additional_filters;
+ EVEL_OPTION_STRING event_source_host;
+ EVEL_OPTION_INT syslog_facility;
+ EVEL_OPTION_INT syslog_priority;
+ EVEL_OPTION_STRING syslog_proc;
+ EVEL_OPTION_INT syslog_proc_id;
+ EVEL_OPTION_STRING syslog_s_data;
+ EVEL_OPTION_STRING syslog_sdid;
+ EVEL_OPTION_STRING syslog_severity;
+ double syslog_fver;
+ EVEL_OPTION_INT syslog_ver;
+
+} EVENT_SYSLOG;
+
+/**************************************************************************//**
+ * 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);
+
+/**************************************************************************//**
+ * Initialize an event instance id.
+ *
+ * @param vfield Pointer to the event vnfname field 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_vendor_field(VENDOR_VNFNAME_FIELD * const vfield,
+ const char * const vendor_name);
+
+/**************************************************************************//**
+ * Set the Vendor module property of the Vendor.
+ *
+ * @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 vfield Pointer to the Vendor field.
+ * @param module_name The module name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_vendor_field_module_set(VENDOR_VNFNAME_FIELD * const vfield,
+ const char * const module_name);
+/**************************************************************************//**
+ * Set the Vendor module property of the Vendor.
+ *
+ * @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 vfield Pointer to the Vendor field.
+ * @param module_name The module name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_vendor_field_vnfname_set(VENDOR_VNFNAME_FIELD * const vfield,
+ const char * const vnfname);
+/**************************************************************************//**
+ * Free an event instance id.
+ *
+ * @param vfield Pointer to the event vnfname_field being freed.
+ *****************************************************************************/
+void evel_free_event_vendor_field(VENDOR_VNFNAME_FIELD * const vfield);
+
+/**************************************************************************//**
+ * 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);
+
+/**************************************************************************//**
+ * Create a new heartbeat event of given name and type.
+ *
+ * @note that the heartbeat is just a "naked" commonEventHeader!
+ *
+ * @param event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ *
+ * @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_nameid(const char* ev_name, const char *ev_id);
+
+
+/**************************************************************************//**
+ * 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,const char *const eventname);
+
+/**************************************************************************//**
+ * 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);
+
+/**************************************************************************//**
+ * Set the NFC Naming code property of the event header.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param nfcnamingcode String
+ *****************************************************************************/
+void evel_nfcnamingcode_set(EVENT_HEADER * const header,
+ const char * const nfcnam);
+/**************************************************************************//**
+ * Set the NF Naming code property of the event header.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param nfnamingcode String
+ *****************************************************************************/
+void evel_nfnamingcode_set(EVENT_HEADER * const header,
+ const char * const nfnam);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* FAULT */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * 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 event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @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.
+ * @param ev_source_type Source of Alarm event
+ * @param version fault version
+ * @param status status of Virtual Function
+ * @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* ev_name, const char *ev_id,
+ const char * const condition,
+ const char * const specific_problem,
+ EVEL_EVENT_PRIORITIES priority,
+ EVEL_SEVERITIES severity,
+ EVEL_SOURCE_TYPES ev_source_type,
+ EVEL_VF_STATUSES status);
+
+/**************************************************************************//**
+ * 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 Fault Category 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 category Category : license, link, routing, security, signaling.
+ * ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_category_set(EVENT_FAULT * fault,
+ const char * const category);
+
+/**************************************************************************//**
+ * 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
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ *
+ * @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,const char* ev_name, const char *ev_id);
+
+/**************************************************************************//**
+ * 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 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.
+ *****************************************************************************/
+MEASUREMENT_CPU_USE * evel_measurement_new_cpu_use_add(EVENT_MEASUREMENT * measurement, char * id, double usage);
+
+/**************************************************************************//**
+ * Set the CPU Idle value in measurement interval
+ * percentage of CPU time spent in the idle task
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_idle_set(MEASUREMENT_CPU_USE *const cpu_use,
+ const double val);
+
+/**************************************************************************//**
+ * Set the percentage of time spent servicing interrupts
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_interrupt_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+
+/**************************************************************************//**
+ * Set the percentage of time spent running user space processes that have been niced
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_nice_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+
+/**************************************************************************//**
+ * Set the percentage of time spent handling soft irq interrupts
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_softirq_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+/**************************************************************************//**
+ * Set the percentage of time spent in involuntary wait
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_steal_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+/**************************************************************************//**
+ * Set the percentage of time spent on system tasks running the kernel
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_system_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+/**************************************************************************//**
+ * Set the percentage of time spent running un-niced user space processes
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_usageuser_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+/**************************************************************************//**
+ * Set the percentage of CPU time spent waiting for I/O operations to complete
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_wait_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val);
+
+/**************************************************************************//**
+ * 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,
+ double block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ double 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 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,
+ int 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_PERFORMANCE 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_PERFORMANCE has immutable
+ * properties.
+ *
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param val_suspect True or false confidence in data.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_PERFORMANCE.
+ * If the structure is not used it must be released using
+ * ::evel_measurement_free_vnic_performance.
+ * @retval NULL Failed to create the vNIC Use.
+ *****************************************************************************/
+MEASUREMENT_VNIC_PERFORMANCE * evel_measurement_new_vnic_performance(char * const vnic_id, char * const val_suspect);
+
+/**************************************************************************//**
+ * Free a vNIC Use.
+ *
+ * Free off the ::MEASUREMENT_VNIC_PERFORMANCE 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_measurement_free_vnic_performance(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance);
+
+/**************************************************************************//**
+ * Set the Accumulated Broadcast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_bcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_bcast_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Broadcast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_bcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_bcast_packets_delta);
+/**************************************************************************//**
+ * Set the Discarded Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_discard_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_discard_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_discard_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Discarded Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_discard_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_discard_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_discard_packets_delta);
+/**************************************************************************//**
+ * Set the Error Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_error_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_error_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Error Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_error_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_error_packets_delta);
+/**************************************************************************//**
+ * Set the Accumulated Multicast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_mcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_mcast_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Multicast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_mcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_mcast_packets_delta);
+/**************************************************************************//**
+ * Set the Accumulated Octets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_octets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_octets_acc);
+/**************************************************************************//**
+ * Set the Delta Octets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_octets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_octets_delta);
+/**************************************************************************//**
+ * Set the Accumulated Total Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_total_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_total_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Total Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_total_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_total_packets_delta);
+/**************************************************************************//**
+ * Set the Accumulated Unicast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_ucast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_ucast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_ucast_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Unicast packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_ucast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_ucast_packets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Broadcast Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_bcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_bcast_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Broadcast packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_bcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_bcast_packets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Discarded Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_discarded_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_discarded_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_discarded_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Discarded packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_discarded_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_discarded_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_discarded_packets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Errored Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_error_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_error_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Errored packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_error_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_error_packets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Multicast Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_mcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_mcast_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Multicast packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_mcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_mcast_packets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Octets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_octets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_octets_acc);
+/**************************************************************************//**
+ * Set the Delta Octets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_octets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_octets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Total Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_total_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_total_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Total Packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_total_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_total_packets_delta);
+/**************************************************************************//**
+ * Set the Transmitted Unicast Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_ucast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_ucast_packets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_ucast_packets_acc);
+/**************************************************************************//**
+ * Set the Delta Octets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_ucast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_ucast_packets_delta);
+
+/**************************************************************************//**
+ * Add an additional vNIC Use to the specified Measurement event.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_performance Pointer to the vNIC Use to add.
+ *****************************************************************************/
+void evel_meas_vnic_performance_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance);
+
+/**************************************************************************//**
+ * 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 valset true or false confidence level
+ * @param recvd_bcast_packets_acc Recieved broadcast packets
+ * @param recvd_bcast_packets_delta Received delta broadcast packets
+ * @param recvd_discarded_packets_acc Recieved discarded packets
+ * @param recvd_discarded_packets_delta Received discarded delta packets
+ * @param recvd_error_packets_acc Received error packets
+ * @param recvd_error_packets_delta, Received delta error packets
+ * @param recvd_mcast_packets_acc Received multicast packets
+ * @param recvd_mcast_packets_delta Received delta multicast packets
+ * @param recvd_octets_acc Received octets
+ * @param recvd_octets_delta Received delta octets
+ * @param recvd_total_packets_acc Received total packets
+ * @param recvd_total_packets_delta Received delta total packets
+ * @param recvd_ucast_packets_acc Received Unicast packets
+ * @param recvd_ucast_packets_delta Received delta unicast packets
+ * @param tx_bcast_packets_acc Transmitted broadcast packets
+ * @param tx_bcast_packets_delta Transmitted delta broadcast packets
+ * @param tx_discarded_packets_acc Transmitted packets discarded
+ * @param tx_discarded_packets_delta Transmitted delta discarded packets
+ * @param tx_error_packets_acc Transmitted error packets
+ * @param tx_error_packets_delta Transmitted delta error packets
+ * @param tx_mcast_packets_acc Transmitted multicast packets accumulated
+ * @param tx_mcast_packets_delta Transmitted delta multicast packets
+ * @param tx_octets_acc Transmitted octets
+ * @param tx_octets_delta Transmitted delta octets
+ * @param tx_total_packets_acc Transmitted total packets
+ * @param tx_total_packets_delta Transmitted delta total packets
+ * @param tx_ucast_packets_acc Transmitted Unicast packets
+ * @param tx_ucast_packets_delta Transmitted delta Unicast packets
+ *****************************************************************************/
+void evel_measurement_vnic_performance_add(EVENT_MEASUREMENT * const measurement,
+ char * const vnic_id,
+ char * valset,
+ double recvd_bcast_packets_acc,
+ double recvd_bcast_packets_delta,
+ double recvd_discarded_packets_acc,
+ double recvd_discarded_packets_delta,
+ double recvd_error_packets_acc,
+ double recvd_error_packets_delta,
+ double recvd_mcast_packets_acc,
+ double recvd_mcast_packets_delta,
+ double recvd_octets_acc,
+ double recvd_octets_delta,
+ double recvd_total_packets_acc,
+ double recvd_total_packets_delta,
+ double recvd_ucast_packets_acc,
+ double recvd_ucast_packets_delta,
+ double tx_bcast_packets_acc,
+ double tx_bcast_packets_delta,
+ double tx_discarded_packets_acc,
+ double tx_discarded_packets_delta,
+ double tx_error_packets_acc,
+ double tx_error_packets_delta,
+ double tx_mcast_packets_acc,
+ double tx_mcast_packets_delta,
+ double tx_octets_acc,
+ double tx_octets_delta,
+ double tx_total_packets_acc,
+ double tx_total_packets_delta,
+ double tx_ucast_packets_acc,
+ double tx_ucast_packets_delta);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* 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
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ *
+ * @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,const char* ev_name, const char *ev_id);
+
+/**************************************************************************//**
+ * 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 event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @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* ev_name, const char *ev_id,
+ 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);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* 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 event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @param vendor_name The vendor id to encode in the event vnf field.
+ * @param module The module to encode in the event.
+ * @param vnfname The Virtual network function to encode in the event.
+ * @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* ev_name, const char *ev_id,
+ const char * const vendor_name,
+ const char * const correlator,
+ const char * const local_ip_address,
+ const char * const local_port,
+ const char * const remote_ip_address,
+ const char * const remote_port);
+
+/**************************************************************************//**
+ * 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);
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the SIP signaling.
+ *
+ * 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 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_signaling_addl_info_add(EVENT_SIGNALING * event, char * name, char * value);
+
+/**************************************************************************//**
+ * 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 Vendor module 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 modulename The module name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_vnfmodule_name_set(EVENT_SIGNALING * const event,
+ const char * const module_name);
+/**************************************************************************//**
+ * Set the Vendor module 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 vnfname The Virtual Network function to be set. ASCIIZ string.
+ * The caller does not need to preserve the value once
+ * the function returns.
+ *****************************************************************************/
+void evel_signaling_vnfname_set(EVENT_SIGNALING * const event,
+ const char * const vnfname);
+
+/**************************************************************************//**
+ * 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 event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @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 char* ev_name, const char *ev_id,
+ 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_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @param event_source_type
+ * @param syslog_msg
+ * @param syslog_tag
+ * @param version
+ *
+ * @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(const char* ev_name, const char *ev_id,
+ 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);
+
+/**************************************************************************//**
+ * Set the Structured SDID 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 sdid The Structured Data to be set. ASCIIZ string. name@number
+ * Caller does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_sdid_set(EVENT_SYSLOG * syslog, const char * const sdid);
+
+/**************************************************************************//**
+ * Set the Structured Severity 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 sdid The Structured Data to be set. ASCIIZ string.
+ * Caller does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_severity_set(EVENT_SYSLOG * syslog, const char * const severty);
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* OTHER */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new other event.
+ *
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ *
+ * @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(const char* ev_name, const char *ev_id);
+
+/**************************************************************************//**
+ * 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();
+
+/*****************************************************************************/
+/* Supported Report version. */
+/*****************************************************************************/
+#define EVEL_VOICEQ_MAJOR_VERSION 1
+#define EVEL_VOICEQ_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * End of Call Voice Quality Metrices
+ * JSON equivalent field: endOfCallVqmSummaries
+ *****************************************************************************/
+typedef struct end_of_call_vqm_summaries {
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ char* adjacencyName;
+ char* endpointDescription;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_INT endpointJitter;
+ EVEL_OPTION_INT endpointRtpOctetsDiscarded;
+ EVEL_OPTION_INT endpointRtpOctetsReceived;
+ EVEL_OPTION_INT endpointRtpOctetsSent;
+ EVEL_OPTION_INT endpointRtpPacketsDiscarded;
+ EVEL_OPTION_INT endpointRtpPacketsReceived;
+ EVEL_OPTION_INT endpointRtpPacketsSent;
+ EVEL_OPTION_INT localJitter;
+ EVEL_OPTION_INT localRtpOctetsDiscarded;
+ EVEL_OPTION_INT localRtpOctetsReceived;
+ EVEL_OPTION_INT localRtpOctetsSent;
+ EVEL_OPTION_INT localRtpPacketsDiscarded;
+ EVEL_OPTION_INT localRtpPacketsReceived;
+ EVEL_OPTION_INT localRtpPacketsSent;
+ EVEL_OPTION_INT mosCqe;
+ EVEL_OPTION_INT packetsLost;
+ EVEL_OPTION_INT packetLossPercent;
+ EVEL_OPTION_INT rFactor;
+ EVEL_OPTION_INT roundTripDelay;
+
+} END_OF_CALL_VOICE_QUALITY_METRICS;
+
+/**************************************************************************//**
+* Voice QUality.
+* JSON equivalent field: voiceQualityFields
+*****************************************************************************/
+
+typedef struct event_voiceQuality {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+
+ char *calleeSideCodec;
+ char *callerSideCodec;
+ char *correlator;
+ char *midCallRtcp;
+ VENDOR_VNFNAME_FIELD vendorVnfNameFields;
+ END_OF_CALL_VOICE_QUALITY_METRICS *endOfCallVqmSummaries;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING phoneNumber;
+ DLIST additionalInformation;
+
+} EVENT_VOICE_QUALITY;
+/**************************************************************************//**
+ * Voice Quality Additional Info.
+ * JSON equivalent field: additionalInformation
+ *****************************************************************************/
+typedef struct voice_quality_additional_info {
+ char * name;
+ char * value;
+} VOICE_QUALITY_ADDL_INFO;
+
+/**************************************************************************//**
+ * Create a new voice quality event.
+ *
+ * @note The mandatory fields on the Voice Quality 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 Voice Quality has immutable properties.
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @param calleeSideCodec Callee codec for the call.
+ * @param callerSideCodec Caller codec for the call.
+ * @param correlator Constant across all events on this call.
+ * @param midCallRtcp Base64 encoding of the binary RTCP data
+ * (excluding Eth/IP/UDP headers).
+ * @param vendorVnfNameFields Vendor, VNF and VfModule names.
+ * @returns pointer to the newly manufactured ::EVENT_VOICE_QUALITY. If the
+ * event is not used (i.e. posted) it must be released using
+ ::evel_free_voice_quality.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_VOICE_QUALITY * evel_new_voice_quality(const char* ev_name, const char *ev_id,
+ const char * const calleeSideCodec,
+ const char * const callerSideCodec, const char * const correlator,
+ const char * const midCallRtcp, const char * const vendorVnfNameFields);
+
+/**************************************************************************//**
+ * Set the Callee side codec for Call for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param calleeCodecForCall The Callee Side Codec to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_callee_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const calleeCodecForCall);
+
+/**************************************************************************//**
+ * Set the Caller side codec for Call for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param callerCodecForCall The Caller Side Codec to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_caller_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const callerCodecForCall);
+
+/**************************************************************************//**
+ * Set the correlator for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param correlator The correlator value to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_correlator_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const vCorrelator);
+
+/**************************************************************************//**
+ * Set the RTCP Call Data for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param rtcpCallData The RTCP Call Data to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_rtcp_data_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const rtcpCallData);
+
+/**************************************************************************//**
+ * Set the Vendor VNF Name fields for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param nameFields The Vendor, VNF and VfModule names to be set.
+ * ASCIIZ string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_name_fields_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const nameFields);
+
+/**************************************************************************//**
+ * Add an End of Call Voice Quality Metrices
+
+ * The adjacencyName and endpointDescription is null delimited ASCII string.
+ * The library takes a copy so the caller does not have to preserve values
+ * after the function returns.
+ *
+ * @param voiceQuality Pointer to the measurement.
+ * @param adjacencyName Adjacency name
+ * @param endpointDescription Enumeration: ‘Caller’, ‘Callee’.
+ * @param endpointJitter Endpoint jitter
+ * @param endpointRtpOctetsDiscarded Endpoint RTP octets discarded.
+ * @param endpointRtpOctetsReceived Endpoint RTP octets received.
+ * @param endpointRtpOctetsSent Endpoint RTP octets sent
+ * @param endpointRtpPacketsDiscarded Endpoint RTP packets discarded.
+ * @param endpointRtpPacketsReceived Endpoint RTP packets received.
+ * @param endpointRtpPacketsSent Endpoint RTP packets sent.
+ * @param localJitter Local jitter.
+ * @param localRtpOctetsDiscarded Local RTP octets discarded.
+ * @param localRtpOctetsReceived Local RTP octets received.
+ * @param localRtpOctetsSent Local RTP octets sent.
+ * @param localRtpPacketsDiscarded Local RTP packets discarded.
+ * @param localRtpPacketsReceived Local RTP packets received.
+ * @param localRtpPacketsSent Local RTP packets sent.
+ * @param mosCqe Decimal range from 1 to 5
+ * (1 decimal place)
+ * @param packetsLost No Packets lost
+ * @param packetLossPercent Calculated percentage packet loss
+ * @param rFactor rFactor from 0 to 100
+ * @param roundTripDelay Round trip delay in milliseconds
+ *****************************************************************************/
+void evel_voice_quality_end_metrics_add(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * adjacencyName, EVEL_SERVICE_ENDPOINT_DESC endpointDescription,
+ int endpointJitter,
+ int endpointRtpOctetsDiscarded,
+ int endpointRtpOctetsReceived,
+ int endpointRtpOctetsSent,
+ int endpointRtpPacketsDiscarded,
+ int endpointRtpPacketsReceived,
+ int endpointRtpPacketsSent,
+ int localJitter,
+ int localRtpOctetsDiscarded,
+ int localRtpOctetsReceived,
+ int localRtpOctetsSent,
+ int localRtpPacketsDiscarded,
+ int localRtpPacketsReceived,
+ int localRtpPacketsSent,
+ int mosCqe,
+ int packetsLost,
+ int packetLossPercent,
+ int rFactor,
+ int roundTripDelay);
+
+/**************************************************************************//**
+ * Free a Voice Quality.
+ *
+ * Free off the Voce Quality supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Voice Quality itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_voice_quality(EVENT_VOICE_QUALITY * voiceQuality);
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the Voice Quality.
+ *
+ * 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_voice_quality_addl_info_add(EVENT_VOICE_QUALITY * voiceQuality, char * name, char * value);
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* THRESHOLD CROSSING ALERT */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+typedef enum evel_event_action {
+ EVEL_EVENT_ACTION_CLEAR,
+ EVEL_EVENT_ACTION_CONTINUE,
+ EVEL_EVENT_ACTION_SET,
+ EVEL_MAX_EVENT_ACTION
+}EVEL_EVENT_ACTION;
+
+typedef enum evel_alert_type {
+ EVEL_CARD_ANOMALY,
+ EVEL_ELEMENT_ANOMALY,
+ EVEL_INTERFACE_ANOMALY,
+ EVEL_SERVICE_ANOMALY,
+ EVEL_MAX_ANOMALY
+}EVEL_ALERT_TYPE;
+
+
+typedef struct perf_counter {
+ char * criticality;
+ char * name;
+ char * thresholdCrossed;
+ char * value;
+}PERF_COUNTER;
+
+
+/*****************************************************************************/
+/* Supported Threshold Crossing version. */
+/*****************************************************************************/
+#define EVEL_THRESHOLD_CROSS_MAJOR_VERSION 1
+#define EVEL_THRESHOLD_CROSS_MINOR_VERSION 1
+
+/**************************************************************************//**
+ * Threshold Crossing.
+ * JSON equivalent field: Threshold Cross Fields
+ *****************************************************************************/
+typedef struct event_threshold_cross {
+ /***************************************************************************/
+ /* Header and version */
+ /***************************************************************************/
+ EVENT_HEADER header;
+ int major_version;
+ int minor_version;
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ PERF_COUNTER additionalParameters;
+ EVEL_EVENT_ACTION alertAction;
+ char * alertDescription;
+ EVEL_ALERT_TYPE alertType;
+ unsigned long long collectionTimestamp;
+ EVEL_SEVERITIES eventSeverity;
+ unsigned long long eventStartTimestamp;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ DLIST additional_info;
+ EVEL_OPTION_STRING alertValue;
+ DLIST alertidList;
+ EVEL_OPTION_STRING dataCollector;
+ EVEL_OPTION_STRING elementType;
+ EVEL_OPTION_STRING interfaceName;
+ EVEL_OPTION_STRING networkService;
+ EVEL_OPTION_STRING possibleRootCause;
+
+} EVENT_THRESHOLD_CROSS;
+
+
+/**************************************************************************//**
+ * Create a new Threshold Crossing Alert event.
+ *
+ * @note The mandatory fields on the TCA 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
+ * TCA has immutable properties.
+ *
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @param char* tcriticality Performance Counter Criticality MAJ MIN,
+ * @param char* tname Performance Counter Threshold name
+ * @param char* tthresholdCrossed Counter Threshold crossed value
+ * @param char* tvalue Counter actual value
+ * @param EVEL_EVENT_ACTION talertAction Alert set continue or clear
+ * @param char* talertDescription
+ * @param EVEL_ALERT_TYPE talertType Kind of anamoly
+ * @param unsigned long long tcollectionTimestamp time at which alert was collected
+ * @param EVEL_SEVERITIES teventSeverity Severity of Alert
+ * @param unsigned long long teventStartTimestamp Time when this alert started
+ *
+ * @returns pointer to the newly manufactured ::EVENT_THRESHOLD_CROSS. If the
+ * event is not used it must be released using
+ * ::evel_free_threshold_cross
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_THRESHOLD_CROSS * evel_new_threshold_cross(
+ const char* ev_name, const char *ev_id,
+ char * tcriticality,
+ char * tname,
+ char * tthresholdCrossed,
+ char * tvalue,
+ EVEL_EVENT_ACTION talertAction,
+ char * talertDescription,
+ EVEL_ALERT_TYPE talertType,
+ unsigned long long tcollectionTimestamp,
+ EVEL_SEVERITIES teventSeverity,
+ unsigned long long teventStartTimestamp);
+
+/**************************************************************************//**
+ * Free a Threshold cross event.
+ *
+ * Free off the Threshold crossing event supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Threshold Cross itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_threshold_cross(EVENT_THRESHOLD_CROSS * const tcp);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Threshold Cross.
+ *
+ * @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 tcp Pointer to the ::EVENT_THRESHOLD_CROSS.
+ * @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_threshold_cross_type_set(EVENT_THRESHOLD_CROSS * const tcp, char * type);
+
+/**************************************************************************//**
+ * Add an optional additional alertid value to Alert.
+ *
+ * @param alertid Adds Alert ID
+ *****************************************************************************/
+void evel_threshold_cross_alertid_add(EVENT_THRESHOLD_CROSS * const event,char * alertid);
+
+ /**************************************************************************//**
+ * Set the TCA probable Root cause.
+ *
+ * @param sheader Possible root cause to Threshold
+ *****************************************************************************/
+ void evel_threshold_cross_possible_rootcause_set(EVENT_THRESHOLD_CROSS * const event, char * sheader);
+ /**************************************************************************//**
+ * Set the TCA networking cause.
+ *
+ * @param sheader Possible networking service value to Threshold
+ *****************************************************************************/
+ void evel_threshold_cross_networkservice_set(EVENT_THRESHOLD_CROSS * const event, char * sheader);
+ /**************************************************************************//**
+ * Set the TCA Interface name.
+ *
+ * @param sheader Interface name to threshold
+ *****************************************************************************/
+ void evel_threshold_cross_interfacename_set(EVENT_THRESHOLD_CROSS * const event,char * sheader);
+ /**************************************************************************//**
+ * Set the TCA Data element type.
+ *
+ * @param sheader element type of Threshold
+ *****************************************************************************/
+ void evel_threshold_cross_data_elementtype_set(EVENT_THRESHOLD_CROSS * const event,char * sheader);
+ /**************************************************************************//**
+ * Set the TCA Data collector value.
+ *
+ * @param sheader Data collector value
+ *****************************************************************************/
+ void evel_threshold_cross_data_collector_set(EVENT_THRESHOLD_CROSS * const event,char * sheader);
+ /**************************************************************************//**
+ * Set the TCA alert value.
+ *
+ * @param sheader Possible alert value
+ *****************************************************************************/
+ void evel_threshold_cross_alertvalue_set(EVENT_THRESHOLD_CROSS * const event,char * sheader);
+
+/**************************************************************************//**
+ * Add an additional field name/value pair to the THRESHOLD CROSS event.
+ *
+ * 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_THRESHOLD_CROSS.
+ * @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_threshold_cross_addl_info_add(EVENT_THRESHOLD_CROSS * const tcp,
+ const char * const name,
+ const char * const value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c
new file mode 100644
index 0000000..ced29b2
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c
@@ -0,0 +1,755 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Event Headers - since
+ * Heartbeats only contain the Event Header, the Heartbeat factory function is
+ * here too.
+ *****************************************************************************/
+
+#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 of given name and type.
+ *
+ * @note that the heartbeat is just a "naked" commonEventHeader!
+ *
+ * @param event_name Unique Event Name: in format
+ * {DomainAbbreviation}_{AsdcModel or ApplicationPlatform}_{DescriptionOfInfoBeingConveyed}
+ * @param event_id Uniquely identify event for correlation and analysis
+ *
+ * @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_nameid(const char* ev_name, const char *ev_id)
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ENTER();
+
+ assert(ev_name != NULL);
+ assert(ev_id != NULL);
+
+ /***************************************************************************/
+ /* 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_nameid(heartbeat,ev_name,ev_id);
+
+exit_label:
+ EVEL_EXIT();
+ return heartbeat;
+}
+
+/**************************************************************************//**
+ * 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,"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,const char *const eventname)
+{
+ 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);
+ if( eventname == NULL )
+ header->event_name = strdup(functional_role);
+ else
+ header->event_name = strdup(eventname);
+ 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_init_option_string(&header->nfcnaming_code);
+ evel_init_option_string(&header->nfnaming_code);
+ evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid());
+ evel_force_option_string(&header->source_id, openstack_vm_uuid());
+ evel_init_option_intheader(&header->internal_field);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Initialize a newly created event header.
+ *
+ * @param header Pointer to the header being initialized.
+ *****************************************************************************/
+void evel_init_header_nameid(EVENT_HEADER * const header,const char *const eventname, const char *eventid)
+{
+ struct timeval tv;
+
+ EVEL_ENTER();
+
+ assert(header != NULL);
+ assert(eventname != NULL);
+ assert(eventid != 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;
+ header->event_id = strdup(eventid);
+ header->event_name = strdup(eventname);
+ 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_init_option_string(&header->nfcnaming_code);
+ evel_init_option_string(&header->nfnaming_code);
+ evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid());
+ evel_force_option_string(&header->source_id, openstack_vm_uuid());
+ evel_init_option_intheader(&header->internal_field);
+
+ 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 NFC Naming code property of the event header.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param nfcnamingcode String
+ *****************************************************************************/
+void evel_nfcnamingcode_set(EVENT_HEADER * const header,
+ const char * const nfcnam)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and assign the new value. */
+ /***************************************************************************/
+ assert(header != NULL);
+ assert(nfcnam != NULL);
+ evel_set_option_string(&header->nfcnaming_code, nfcnam, "NFC Naming Code");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the NF Naming code property of the event header.
+ *
+ * @param header Pointer to the ::EVENT_HEADER.
+ * @param nfnamingcode String
+ *****************************************************************************/
+void evel_nfnamingcode_set(EVENT_HEADER * const header,
+ const char * const nfnam)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and assign the new value. */
+ /***************************************************************************/
+ assert(header != NULL);
+ assert(nfnam != NULL);
+ evel_set_option_string(&header->nfnaming_code, nfnam, "NF Naming Code");
+
+ 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, "eventName", event->event_name);
+ 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_enc_kv_opt_string(jbuf, "nfcNamingCode", &event->nfcnaming_code);
+ evel_enc_kv_opt_string(jbuf, "nfNamingCode", &event->nfnaming_code);
+
+ 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->event_name);
+ evel_free_option_string(&event->reporting_entity_id);
+ free(event->reporting_entity_name);
+ evel_free_option_string(&event->source_id);
+ evel_free_option_string(&event->nfcnaming_code);
+ evel_free_option_string(&event->nfnaming_code);
+ evel_free_option_intheader(&event->internal_field);
+ 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_HEARTBEAT_FIELD:
+ evel_json_encode_hrtbt_field(jbuf, (EVENT_HEARTBEAT_FIELD *)event);
+ break;
+
+ case EVEL_DOMAIN_SIPSIGNALING:
+ 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_VOICE_QUALITY:
+ evel_json_encode_voice_quality(jbuf, (EVENT_VOICE_QUALITY *)event);
+ break;
+
+ case EVEL_DOMAIN_THRESHOLD_CROSS:
+ evel_json_encode_threshold_cross(jbuf, (EVENT_THRESHOLD_CROSS *)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 vfield Pointer to the event vnfname field 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_vendor_field(VENDOR_VNFNAME_FIELD * const vfield,
+ const char * const vendor_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vfield != NULL);
+ assert(vendor_name != NULL);
+
+ /***************************************************************************/
+ /* Store the mandatory parts. */
+ /***************************************************************************/
+ vfield->vendorname = strdup(vendor_name);
+ evel_init_option_string(&vfield->vfmodule);
+ evel_init_option_string(&vfield->vnfname);
+
+ /***************************************************************************/
+ /* Initialize the optional parts. */
+ /***************************************************************************/
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Vendor module property of the Vendor.
+ *
+ * @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 vfield Pointer to the Vendor field.
+ * @param module_name The module name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_vendor_field_module_set(VENDOR_VNFNAME_FIELD * const vfield,
+ const char * const module_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vfield != NULL);
+ assert(module_name != NULL);
+
+ evel_set_option_string(&vfield->vfmodule, module_name, "Module name set");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Vendor module property of the Vendor.
+ *
+ * @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 vfield Pointer to the Vendor field.
+ * @param module_name The module name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_vendor_field_vnfname_set(VENDOR_VNFNAME_FIELD * const vfield,
+ const char * const vnfname)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vfield != NULL);
+ assert(vnfname != NULL);
+
+ evel_set_option_string(&vfield->vnfname, vnfname, "Virtual Network Function name set");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free an event instance id.
+ *
+ * @param vfield Pointer to the event vnfname_field being freed.
+ *****************************************************************************/
+void evel_free_event_vendor_field(VENDOR_VNFNAME_FIELD * const vfield)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vfield->vendorname != NULL);
+
+ /***************************************************************************/
+ /* Free everything. */
+ /***************************************************************************/
+ evel_free_option_string(&vfield->vfmodule);
+ evel_free_option_string(&vfield->vnfname);
+ free(vfield->vendorname);
+
+ 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 vfield Pointer to the ::VENDOR_VNFNAME_FIELD to encode.
+ *****************************************************************************/
+void evel_json_encode_vendor_field(EVEL_JSON_BUFFER * jbuf,
+ VENDOR_VNFNAME_FIELD * vfield)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(jbuf->json != NULL);
+ assert(jbuf->max_size > 0);
+ assert(vfield != NULL);
+ assert(vfield->vendorname != NULL);
+
+ evel_json_open_named_object(jbuf, "vendorVnfNameFields");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "vendorName", vfield->vendorname);
+ evel_enc_kv_opt_string(jbuf, "vfModuleName", &vfield->vfmodule);
+ evel_enc_kv_opt_string(jbuf, "vnfName", &vfield->vnfname);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c
new file mode 100644
index 0000000..a96124a
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c
@@ -0,0 +1,1050 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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.
+ *
+ ****************************************************************************/
+
+#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);
+
+
+ curl_version_info_data *d = curl_version_info(CURLVERSION_NOW);
+ /* compare with the 24 bit hex number in 8 bit fields */
+ if(d->version_num >= 0x072100) {
+ /* this is libcurl 7.33.0 or later */
+ EVEL_INFO("7.33 or later Curl version %x.",d->version_num);
+ }
+ else {
+ EVEL_INFO("Old Curl version.");
+ }
+ /***************************************************************************/
+ /* 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,"EVELinternal","EVELid");
+ 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c
new file mode 100644
index 0000000..c211f60
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c
@@ -0,0 +1,367 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Fault.
+ *
+ ****************************************************************************/
+
+#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 event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @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.
+ * @param ev_source_type Source of Alarm event
+ * @param version fault version
+ * @param status status of Virtual Function
+ * @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 * ev_name,
+ const char * ev_id,
+ const char * const condition,
+ const char * const specific_problem,
+ EVEL_EVENT_PRIORITIES priority,
+ EVEL_SEVERITIES severity,
+ EVEL_SOURCE_TYPES ev_source_type,
+ EVEL_VF_STATUSES status)
+{
+ 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_nameid(&fault->header,ev_name,ev_id);
+ 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 = ev_source_type;
+ fault->vf_status = status;
+ fault->alarm_condition = strdup(condition);
+ fault->specific_problem = strdup(specific_problem);
+ evel_init_option_string(&fault->category);
+ 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 Fault Category 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 category Category : license, link, routing, security, signaling.
+ * ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_fault_category_set(EVENT_FAULT * fault,
+ const char * const category)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(fault != NULL);
+ assert(fault->header.event_domain == EVEL_DOMAIN_FAULT);
+ assert(category != NULL);
+
+ evel_set_option_string(&fault->category,
+ category,
+ "Fault Category set");
+ 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_opt_string(jbuf, "eventCategory", &event->category);
+ 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);
+ free(event->specific_problem);
+ evel_free_option_string(&event->category);
+ evel_free_option_string(&event->alarm_interface_a);
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c
new file mode 100644
index 0000000..872af1f
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c
@@ -0,0 +1,269 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Heartbeat fields.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Heartbeat fields event.
+ *
+ * @note The mandatory fields on the Heartbeat fields 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 event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @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_HEARTBEAT_FIELD. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_hrtbt_field.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_HEARTBEAT_FIELD * evel_new_heartbeat_field(int interval,const char* ev_name, const char *ev_id)
+{
+ EVENT_HEARTBEAT_FIELD * event = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(interval > 0);
+
+ /***************************************************************************/
+ /* Allocate the Heartbeat fields event. */
+ /***************************************************************************/
+ event = malloc(sizeof(EVENT_HEARTBEAT_FIELD));
+ if (event == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(event, 0, sizeof(EVENT_HEARTBEAT_FIELD));
+ EVEL_DEBUG("New Heartbeat fields event is at %lp", event);
+
+ /***************************************************************************/
+ /* Initialize the header & the Heartbeat fields fields. */
+ /***************************************************************************/
+ evel_init_header_nameid(&event->header,ev_name,ev_id);
+ event->header.event_domain = EVEL_DOMAIN_HEARTBEAT_FIELD;
+ event->major_version = EVEL_HEARTBEAT_FIELD_MAJOR_VERSION;
+ event->minor_version = EVEL_HEARTBEAT_FIELD_MINOR_VERSION;
+
+ event->heartbeat_interval = interval;
+ dlist_initialize(&event->additional_info);
+
+exit_label:
+
+ EVEL_EXIT();
+ return event;
+}
+
+/**************************************************************************//**
+ * Add a name/value pair to the Heartbeat fields, 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 Heartbeat fields 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_hrtbt_field_addl_field_add(EVENT_HEARTBEAT_FIELD * 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_HEARTBEAT_FIELD);
+ 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_info, nv_pair);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Interval property of the Heartbeat fields 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 Heartbeat fields 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_hrtbt_interval_set(EVENT_HEARTBEAT_FIELD * const event,
+ const int interval)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_set_option_string. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_HEARTBEAT_FIELD);
+ assert(interval > 0);
+
+ event->heartbeat_interval = interval;
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Encode the Heartbeat fields 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_hrtbt_field(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_HEARTBEAT_FIELD * 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_HEARTBEAT_FIELD);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "heartbeatField");
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ evel_enc_version(jbuf, "heartbeatFieldsVersion", event->major_version,event->minor_version);
+ evel_enc_kv_int(jbuf, "heartbeatInterval", event->heartbeat_interval);
+
+ /***************************************************************************/
+ /* 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, "additionalFields"))
+ {
+ bool added = false;
+
+ dlist_item = dlist_get_first(&event->additional_info);
+ 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);
+ }
+ }
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Heartbeat fields 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_hrtbt_field(EVENT_HEARTBEAT_FIELD * const event)
+{
+ OTHER_FIELD * nv_pair = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_HEARTBEAT_FIELD);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ nv_pair = dlist_pop_last(&event->additional_info);
+ 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_info);
+ }
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h
new file mode 100644
index 0000000..46f71af
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h
@@ -0,0 +1,858 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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.
+ *
+ ****************************************************************************/
+
+#ifndef EVEL_INTERNAL_INCLUDED
+#define EVEL_INTERNAL_INCLUDED
+
+#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,const char* ev_name, const char *ev_id);
+
+/**************************************************************************//**
+ * 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);
+
+/*****************************************************************************/
+/* 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 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 Heartbeat fields 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_hrtbt_field(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_HEARTBEAT_FIELD * 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);
+
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_INTHEADER_FIELDS to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ *****************************************************************************/
+void evel_init_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option);
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_INTHEADER_FIELDS.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option,
+ const void* value);
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_INTHEADER_FIELDS.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option,
+ const void * value,
+ const char * const description);
+/**************************************************************************//**
+ * Free the underlying resources of an ::EVEL_OPTION_INTHEADER_FIELDS.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ *****************************************************************************/
+void evel_free_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option);
+
+#endif
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c
new file mode 100644
index 0000000..cb56c88
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c
@@ -0,0 +1,113 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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.
+ *
+ ****************************************************************************/
+
+#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.
+ * @param event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @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,const char* ev_name, const char *ev_id)
+{
+ 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_nameid(&event->header,ev_name,ev_id);
+ 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();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c
new file mode 100644
index 0000000..b6026e2
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c
@@ -0,0 +1,870 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Source module relating to internal EVEL_JSON_BUFFER manipulation functions.
+ *
+ ****************************************************************************/
+
+#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 json object 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 json string to encode.
+ *****************************************************************************/
+void evel_enc_kv_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const char * 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\": %s",
+ 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c
new file mode 100644
index 0000000..caf1a1e
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c
@@ -0,0 +1,446 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to json_object.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "jsmn.h"
+#include "evel.h"
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Create a new json object.
+ *
+ * @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.
+ * @param name name of the object.
+ * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT.
+ * not used (i.e. posted) it must be released using ::evel_free_jsonobject.
+ * @retval NULL Failed to create the json object.
+ *****************************************************************************/
+EVEL_JSON_OBJECT * evel_new_jsonobject(const char *const name)
+{
+ EVEL_JSON_OBJECT *jobj = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(name != NULL);
+
+ /***************************************************************************/
+ /* Allocate the json object. */
+ /***************************************************************************/
+ jobj = malloc(sizeof(EVEL_JSON_OBJECT));
+ if (jobj == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(jobj, 0, sizeof(EVEL_JSON_OBJECT));
+ EVEL_DEBUG("New json object is at %lp", jobj);
+
+ /***************************************************************************/
+ /* Initialize the fields. Optional string values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ jobj->object_name = strdup(name);
+ evel_init_option_string(&jobj->objectschema);
+ evel_init_option_string(&jobj->objectschemaurl);
+ evel_init_option_string(&jobj->nfsubscribedobjname);
+ evel_init_option_string(&jobj->nfsubscriptionid);
+ dlist_initialize(&jobj->jsonobjectinstances);
+
+exit_label:
+ EVEL_EXIT();
+ return jobj;
+}
+
+
+/**************************************************************************//**
+ * Create a new json object instance.
+ *
+ * @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.
+ * @param yourjson json string.
+ * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT_INSTANCE.
+ * not used (i.e. posted) it must be released using ::evel_free_jsonobjectinstance.
+ * @retval NULL Failed to create the json object instance.
+ *****************************************************************************/
+EVEL_JSON_OBJECT_INSTANCE * evel_new_jsonobjinstance(const char *const yourjson)
+{
+ EVEL_JSON_OBJECT_INSTANCE *jobjinst = NULL;
+ jsmntok_t *key;
+ int resultCode;
+ jsmn_parser p;
+ jsmntok_t tokens[MAX_JSON_TOKENS]; // a number >= total number of tokens
+ int len=0;
+
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(yourjson != NULL);
+ len = strlen(yourjson)+1;
+ assert(len > 0);
+
+ /***************************************************************************/
+ /* Validate JSON for json object
+ /***************************************************************************/
+ jsmn_init(&p);
+ resultCode = jsmn_parse(&p, yourjson, len, tokens, sizeof(tokens)/sizeof(tokens[0]));
+ if( resultCode < 0 ){
+ log_error_state("Failed to parse json for object");
+ goto exit_label;
+ }
+
+ if (resultCode < 1 || tokens[0].type != JSMN_OBJECT) {
+ log_error_state("Error json object expected");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Allocate the json object. */
+ /***************************************************************************/
+ jobjinst = malloc(sizeof(EVEL_JSON_OBJECT_INSTANCE));
+ if (jobjinst == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(jobjinst, 0, sizeof(EVEL_JSON_OBJECT_INSTANCE));
+
+ /***************************************************************************/
+ /* Initialize the fields. Optional key values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ jobjinst->jsonstring = strdup(yourjson);
+ dlist_initialize(&jobjinst->object_keys);
+
+exit_label:
+ EVEL_EXIT();
+ return jobjinst;
+}
+
+
+/**************************************************************************//**
+ * Create a new internal key.
+ *
+ * @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.
+ * @param keyname name of the key.
+ * @returns pointer to the newly manufactured ::EVEL_INTERNAL_KEY.
+ * not used (i.e. posted) it must be released using ::evel_free_internal_key.
+ * @retval NULL Failed to create the internal key.
+ *****************************************************************************/
+EVEL_INTERNAL_KEY * evel_new_internal_key(char *keyname)
+{
+ EVEL_INTERNAL_KEY *keyinst = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(keyname != NULL);
+
+ /***************************************************************************/
+ /* Allocate the key object. */
+ /***************************************************************************/
+ keyinst = malloc(sizeof(EVEL_INTERNAL_KEY));
+ if (keyinst == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(keyinst, 0, sizeof(EVEL_INTERNAL_KEY));
+ keyinst->keyname = strdup(keyname);
+
+ /***************************************************************************/
+ /* Optional string values are uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_option_int(&keyinst->keyorder);
+ evel_init_option_string(&keyinst->keyvalue);
+
+exit_label:
+ EVEL_EXIT();
+ return keyinst;
+}
+
+/**************************************************************************//**
+ * Set the keyorder of the internal key instance.
+ *
+ * @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 int keyorder
+ *****************************************************************************/
+void evel_internal_key_keyorder_set(EVEL_INTERNAL_KEY * pinst, const int keyorder)
+{
+ assert (pinst != NULL);
+ evel_set_option_int(&pinst->keyorder,keyorder,"Key order");
+}
+
+/**************************************************************************//**
+ * Set the keyvalue of the internal key instance.
+ *
+ * @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 string keyvalue
+ *****************************************************************************/
+void evel_internal_key_keyvalue_set(EVEL_INTERNAL_KEY * pinst, const char * const keyval)
+{
+ assert (pinst != NULL);
+ evel_set_option_string(&pinst->keyvalue,keyval,"Key Value");
+}
+
+/**************************************************************************//**
+ * Set the string values of json object
+ *
+ * @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 string object schema
+ *****************************************************************************/
+void evel_jsonobject_objectschema_set(EVEL_JSON_OBJECT * pinst, const char * const objectschema)
+{
+ assert (pinst != NULL);
+ evel_set_option_string(&pinst->objectschema,objectschema,"Object Schema");
+}
+
+/**************************************************************************//**
+ * Set the string values of json object
+ *
+ * @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 string object schema url
+ *****************************************************************************/
+void evel_jsonobject_objectschemaurl_set(EVEL_JSON_OBJECT * pinst, const char * const objectschemaurl)
+{
+ assert (pinst != NULL);
+ evel_set_option_string(&pinst->objectschemaurl,objectschemaurl,"Object Schema URL");
+}
+
+/**************************************************************************//**
+ * Set the string values of json object
+ *
+ * @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 string NF Subscribed object name
+ *****************************************************************************/
+void evel_jsonobject_nfsubscribedobjname_set(EVEL_JSON_OBJECT * pinst, const char * const nfsubscribedobjname)
+{
+ assert (pinst != NULL);
+ evel_set_option_string(&pinst->nfsubscribedobjname,nfsubscribedobjname,"NF Subscribed Object Name");
+}
+
+/**************************************************************************//**
+ * Set the string values of json object
+ *
+ * @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 string NF Subscription Id
+ *****************************************************************************/
+void evel_jsonobject_nfsubscriptionid_set(EVEL_JSON_OBJECT * pinst, const char * const nfsubscriptionid)
+{
+ assert (pinst != NULL);
+ evel_set_option_string(&pinst->nfsubscriptionid,nfsubscriptionid,"NF Subscription Id");
+}
+
+/**************************************************************************//**
+ * Set the Epoch time of the json object instance.
+ *
+ * @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 unsigned long long epoch time
+ *****************************************************************************/
+void evel_epoch_microsec_set(EVEL_JSON_OBJECT_INSTANCE * pinst, const unsigned long long epmicrosec)
+{
+ assert(epmicrosec != 0 );
+ pinst->objinst_epoch_microsec = epmicrosec;
+}
+
+/**************************************************************************//**
+ * Add a json object instance to jsonObject list.
+ *
+ * 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 pobj Pointer to the Other.
+ * @param jinst Pointer to HashTable
+ *****************************************************************************/
+void evel_jsonobject_add_jsoninstance(EVEL_JSON_OBJECT * pobj, EVEL_JSON_OBJECT_INSTANCE *jinst)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(pobj != NULL);
+ assert(jinst != NULL);
+
+ EVEL_DEBUG("Adding json object instance");
+
+ dlist_push_last(&pobj->jsonobjectinstances, jinst);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Add a json object to jsonObject list.
+ *
+ * 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 jsonobj Pointer to json object
+ *****************************************************************************/
+void evel_jsonobjinst_add_objectkey(EVEL_JSON_OBJECT_INSTANCE * jsoninst, EVEL_INTERNAL_KEY *keyp)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jsoninst != NULL);
+ assert(keyp != NULL);
+
+ EVEL_DEBUG("Adding jsonObject instance");
+
+ dlist_push_last(&jsoninst->object_keys, keyp);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free an internal key.
+ *
+ * Free off the internal key supplied. Will free all the contained allocated memory.
+ *
+ *****************************************************************************/
+void evel_free_internal_key(EVEL_INTERNAL_KEY * keyp)
+{
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(keyp != NULL);
+
+ free(keyp->keyname);
+ evel_free_option_string(&keyp->keyvalue);
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Free an json object instance.
+ *
+ * Free off the json object instance supplied.
+ * Will free all the contained allocated memory.
+ *
+ *****************************************************************************/
+void evel_free_jsonobjinst(EVEL_JSON_OBJECT_INSTANCE * objinst)
+{
+ EVEL_INTERNAL_KEY *other_field = NULL;
+
+ EVEL_ENTER();
+ assert(objinst != NULL);
+ assert(objinst->jsonstring != NULL);
+
+ free(objinst->jsonstring);
+
+ /***************************************************************************/
+ /* Free all internal internal keys
+ /***************************************************************************/
+ other_field = dlist_pop_last(&objinst->object_keys);
+ while (other_field != NULL)
+ {
+ EVEL_DEBUG("Freeing Object Instance Field (%s)",
+ other_field->keyname);
+ evel_free_internal_key(other_field);
+ other_field = dlist_pop_last(&objinst->object_keys);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free an json object.
+ *
+ * Free off the json object instance supplied.
+ * Will free all the contained allocated memory.
+ *
+ *****************************************************************************/
+void evel_free_jsonobject(EVEL_JSON_OBJECT * jsobj)
+{
+ EVEL_JSON_OBJECT_INSTANCE *other_field = NULL;
+
+ EVEL_ENTER();
+ assert(jsobj != NULL);
+
+ free(jsobj->object_name);
+ evel_free_option_string(&jsobj->objectschema);
+ evel_free_option_string(&jsobj->objectschemaurl);
+ evel_free_option_string(&jsobj->nfsubscribedobjname);
+ evel_free_option_string(&jsobj->nfsubscriptionid);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ other_field = dlist_pop_last(&jsobj->jsonobjectinstances);
+ while (other_field != NULL)
+ {
+ EVEL_DEBUG("Freeing Object Instance Field (%s)",
+ other_field->jsonstring);
+ evel_free_jsonobjinst(other_field);
+ other_field = dlist_pop_last(&jsobj->jsonobjectinstances);
+ }
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c
new file mode 100644
index 0000000..5a44f07
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c
@@ -0,0 +1,167 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Wrapper for event logging built on syslog.
+ *
+ ****************************************************************************/
+
+#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);
+ }
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c
new file mode 100644
index 0000000..5085d6a
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c
@@ -0,0 +1,2122 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Mobile Flow.
+ *
+ ****************************************************************************/
+
+#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 event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @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* ev_name, const char *ev_id,
+ 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_nameid(&mobile_flow->header,ev_name,ev_id);
+ 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);
+ dlist_initialize(&mobile_flow->additional_info);
+
+exit_label:
+ EVEL_EXIT();
+ return mobile_flow;
+}
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the Mobile flow.
+ *
+ * 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 Mobile flow.
+ * @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_mobile_flow_addl_field_add(EVENT_MOBILE_FLOW * const event, char * name, char * value)
+{
+ OTHER_FIELD * nv_pair = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW);
+ 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_info, nv_pair);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * 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)
+{
+ OTHER_FIELD * nv_pair = NULL;
+ DLIST_ITEM * dlist_item = NULL;
+
+ 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");
+
+
+ /***************************************************************************/
+ /* 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_info);
+ 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);
+ }
+ }
+
+
+ /***************************************************************************/
+ /* 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);
+ evel_enc_version(jbuf,
+ "mobileFlowFieldsVersion",
+ event->major_version,
+ event->minor_version);
+ 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)
+{
+ OTHER_FIELD * nv_pair = 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_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);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+ nv_pair = dlist_pop_last(&event->additional_info);
+ 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_info);
+ }
+
+ 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();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c
new file mode 100644
index 0000000..7d53e8f
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c
@@ -0,0 +1,526 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Source module relating to EVEL_OPTION_ types.
+ *
+ ****************************************************************************/
+
+#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_INTHEADER_FIELDS to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ *****************************************************************************/
+void evel_init_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ option->object = NULL;
+ option->is_set = EVEL_FALSE;
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_INTHEADER_FIELDS.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option,
+ const void* value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->object = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_INTHEADER_FIELDS.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option,
+ const void * 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->object);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %llu", description, value);
+ option->object = value;
+ option->is_set = EVEL_TRUE;
+ }
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free the underlying resources of an ::EVEL_OPTION_INTHEADER_FIELDS.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS.
+ *****************************************************************************/
+void evel_free_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ free(option->object);
+ option->object = NULL;
+ option->is_set = EVEL_FALSE;
+ }
+
+ 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c
new file mode 100644
index 0000000..c7a227b
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c
@@ -0,0 +1,492 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Other.
+ *
+ ****************************************************************************/
+
+#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(const char *ev_name, const char *ev_id)
+{
+ 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_nameid(&other->header,ev_name,ev_id);
+ other->header.event_domain = EVEL_DOMAIN_OTHER;
+ other->major_version = EVEL_OTHER_EVENT_MAJOR_VERSION;
+ other->minor_version = EVEL_OTHER_EVENT_MINOR_VERSION;
+
+ other->namedarrays = NULL;
+ dlist_initialize(&other->jsonobjects);
+ dlist_initialize(&other->namedvalues);
+
+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 json object to jsonObject list.
+ *
+ * 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 size size of hashtable
+ *****************************************************************************/
+void evel_other_field_set_namedarraysize(EVENT_OTHER * other, const int size)
+{
+ OTHER_FIELD * other_field = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(other != NULL);
+ assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
+ assert(other->namedarrays == NULL);
+ assert(size > 0);
+
+ EVEL_DEBUG("Adding Named array");
+
+ other->namedarrays = ht_create(size);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Add a json object to jsonObject list.
+ *
+ * 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 size size of hashtable
+ *****************************************************************************/
+void evel_other_field_add_namedarray(EVENT_OTHER * other, const char *hashname, char * name, char *value)
+{
+ OTHER_FIELD * other_field = NULL;
+ DLIST *list = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(other != NULL);
+ assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
+ assert(other->namedarrays != NULL);
+
+ EVEL_DEBUG("Adding values to Named array");
+
+ 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);
+
+
+ list = ht_get(other->namedarrays, hashname);
+ if( list == NULL )
+ {
+ DLIST * nlist = malloc(sizeof(DLIST));
+ dlist_initialize(nlist);
+ dlist_push_last(nlist, other_field);
+ ht_set(other->namedarrays, hashname, nlist);
+ EVEL_DEBUG("Created to new table table");
+ }
+ else
+ {
+ dlist_push_last(list, other_field);
+ EVEL_DEBUG("Adding to existing table");
+ }
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Add a json object to jsonObject list.
+ *
+ * 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 jsonobj Pointer to json object
+ *****************************************************************************/
+void evel_other_field_add_jsonobj(EVENT_OTHER * other, EVEL_JSON_OBJECT *jsonobj)
+{
+ OTHER_FIELD * other_field = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(other != NULL);
+ assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
+ assert(jsonobj != NULL);
+
+ EVEL_DEBUG("Adding jsonObject");
+
+ dlist_push_last(&other->jsonobjects, jsonobj);
+
+ 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->namedvalues, 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;
+ EVEL_JSON_OBJECT * jsonobjp = NULL;
+ DLIST_ITEM * other_field_item = NULL;
+ EVEL_JSON_OBJECT_INSTANCE * jsonobjinst = NULL;
+ DLIST_ITEM * jsobj_field_item = NULL;
+ EVEL_INTERNAL_KEY * keyinst = NULL;
+ DLIST_ITEM * keyinst_field_item = NULL;
+ HASHTABLE_T *ht = NULL;
+ int i;
+ bool itm_added = false;
+ DLIST *itm_list = 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_object(jbuf, "otherFields");
+
+// iterate through hashtable and print DLIST for each entry
+
+ ht = event->namedarrays;
+ if( ht != NULL )
+ {
+ if( ht->size > 0)
+ {
+ for( i = 0; i < ht->size; i++ ) {
+ if( ht->table[i] != NULL)
+ {
+ itm_added = true;
+ }
+ }
+ if( itm_added == true)
+ {
+
+ if (evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays"))
+ {
+ for( i = 0; i < ht->size; i++ ) {
+ if( ht->table[i] != NULL)
+ {
+ itm_list = ht->table[i];
+
+ if(evel_json_open_opt_named_list(jbuf, ht->table[i]->key))
+ {
+ other_field_item = dlist_get_first(&itm_list);
+ while (other_field_item != NULL)
+ {
+ other_field = (OTHER_FIELD *) other_field_item->item;
+ if(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_json_close_list(jbuf);
+ }
+
+
+ }
+ }
+ }
+
+ evel_json_checkpoint(jbuf);
+ if(evel_json_open_opt_named_list(jbuf, "jsonObjects"))
+ {
+ bool item_added = false;
+ other_field_item = dlist_get_first(&event->jsonobjects);
+ while (other_field_item != NULL)
+ {
+ jsonobjp = (EVEL_JSON_OBJECT *) other_field_item->item;
+ if(jsonobjp != NULL);
+ {
+ evel_json_open_object(jbuf);
+
+ if( evel_json_open_opt_named_list(jbuf, "objectInstances"))
+ {
+ bool item_added2 = false;
+ jsobj_field_item = dlist_get_first(&jsonobjp->jsonobjectinstances);
+ while (jsobj_field_item != NULL)
+ {
+ jsonobjinst = (EVEL_JSON_OBJECT_INSTANCE *) jsobj_field_item->item;
+ if( jsonobjinst != NULL )
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring);
+ evel_enc_kv_ull(jbuf, "objectInstanceEpochMicrosec", jsonobjinst->objinst_epoch_microsec);
+ //evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "objectKeys"))
+ {
+ bool item_added3 = false;
+
+ keyinst_field_item = dlist_get_first(&jsonobjinst->object_keys);
+ while (keyinst_field_item != NULL)
+ {
+ keyinst = (EVEL_INTERNAL_KEY *)keyinst_field_item->item;
+ if(keyinst != NULL)
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "keyName", keyinst->keyname);
+ evel_enc_kv_opt_int(jbuf, "keyOrder", &keyinst->keyorder);
+ evel_enc_kv_opt_string(jbuf, "keyValue", &keyinst->keyvalue);
+ evel_json_close_object(jbuf);
+ item_added3 = false;
+ }
+ keyinst_field_item = dlist_get_next(keyinst_field_item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ //if (!item_added3)
+ //{
+ // evel_json_rewind(jbuf);
+ //}
+ }
+ evel_json_close_object(jbuf);
+ }
+ item_added2 = true;
+ jsobj_field_item = dlist_get_next(jsobj_field_item);
+ }
+ evel_json_close_list(jbuf);
+ if( !item_added2 )
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ evel_enc_kv_string(jbuf, "objectName", jsonobjp->object_name);
+ evel_enc_kv_opt_string(jbuf, "objectSchema", &jsonobjp->objectschema);
+ evel_enc_kv_opt_string(jbuf, "objectSchemaUrl", &jsonobjp->objectschemaurl);
+ evel_enc_kv_opt_string(jbuf, "nfSubscribedObjectName", &jsonobjp->nfsubscribedobjname);
+ evel_enc_kv_opt_string(jbuf, "nfSubscriptionId", &jsonobjp->nfsubscriptionid);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ other_field_item = dlist_get_next(other_field_item);
+ }
+ evel_json_close_list(jbuf);
+
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+
+ }
+
+ if( evel_json_open_opt_named_list(jbuf, "nameValuePairs"))
+ {
+ other_field_item = dlist_get_first(&event->namedvalues);
+ 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_enc_version(jbuf, "otherFieldsVersion", event->major_version,event->minor_version);
+
+ evel_json_close_object(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->namedvalues);
+ 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->namedvalues);
+ }
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c
new file mode 100644
index 0000000..36c34da
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c
@@ -0,0 +1,437 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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.
+ ****************************************************************************/
+
+#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
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc
+ * @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,const char *ev_name, const char *ev_id)
+{
+ 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_nameid(&report->header,ev_name,ev_id);
+ 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->minor_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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c
new file mode 100644
index 0000000..b3e73c9
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c
@@ -0,0 +1,3716 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Measurement.
+ *
+ ****************************************************************************/
+
+#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
+ * @param event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ *
+ * @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, const char* ev_name, const char *ev_id)
+{
+ 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_nameid(&measurement->header,ev_name,ev_id);
+ measurement->header.event_domain = EVEL_DOMAIN_MEASUREMENT;
+ measurement->measurement_interval = measurement_interval;
+ dlist_initialize(&measurement->additional_info);
+ dlist_initialize(&measurement->additional_measurements);
+ dlist_initialize(&measurement->additional_objects);
+ dlist_initialize(&measurement->cpu_usage);
+ dlist_initialize(&measurement->disk_usage);
+ dlist_initialize(&measurement->mem_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);
+ evel_init_option_double(&measurement->mean_request_latency);
+ evel_init_option_int(&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();
+}
+
+/**************************************************************************//**
+ * Add an additional 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 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_measurement_addl_info_add(EVENT_MEASUREMENT * measurement, char * name, char * value)
+{
+ OTHER_FIELD * addl_info = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ addl_info = malloc(sizeof(OTHER_FIELD));
+ assert(addl_info != NULL);
+ memset(addl_info, 0, sizeof(OTHER_FIELD));
+ addl_info->name = strdup(name);
+ addl_info->value = strdup(value);
+ assert(addl_info->name != NULL);
+ assert(addl_info->value != NULL);
+
+ dlist_push_last(&measurement->additional_info, addl_info);
+
+ 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 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.
+ *****************************************************************************/
+MEASUREMENT_CPU_USE *evel_measurement_new_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;
+ evel_init_option_double(&cpu_use->idle);
+ evel_init_option_double(&cpu_use->intrpt);
+ evel_init_option_double(&cpu_use->nice);
+ evel_init_option_double(&cpu_use->softirq);
+ evel_init_option_double(&cpu_use->steal);
+ evel_init_option_double(&cpu_use->sys);
+ evel_init_option_double(&cpu_use->user);
+ evel_init_option_double(&cpu_use->wait);
+
+ dlist_push_last(&measurement->cpu_usage, cpu_use);
+
+ EVEL_EXIT();
+ return cpu_use;
+}
+
+/**************************************************************************//**
+ * Set the CPU Idle value in measurement interval
+ * percentage of CPU time spent in the idle task
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_idle_set(MEASUREMENT_CPU_USE *const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->idle, val, "CPU idle time");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the percentage of time spent servicing interrupts
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_interrupt_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->intrpt, val, "CPU interrupt value");
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the percentage of time spent running user space processes that have been niced
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_nice_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->nice, val, "CPU nice value");
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the percentage of time spent handling soft irq interrupts
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_softirq_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->softirq, val, "CPU Soft IRQ value");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the percentage of time spent in involuntary wait
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_steal_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->steal, val, "CPU involuntary wait");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the percentage of time spent on system tasks running the kernel
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_system_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->sys, val, "CPU System load");
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the percentage of time spent running un-niced user space processes
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_usageuser_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->user, val, "CPU User load value");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the percentage of CPU time spent waiting for I/O operations to complete
+ *
+ * @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 cpu_use Pointer to the CPU Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_cpu_use_wait_set(MEASUREMENT_CPU_USE * const cpu_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&cpu_use->wait, val, "CPU Wait IO value");
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Add an additional Memory 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 Memory identifier.
+ * @param vmidentifier ASCIIZ string with the VM's identifier.
+ * @param membuffsz Memory Size.
+ *
+ * @return Returns pointer to memory use structure in measurements
+ *****************************************************************************/
+MEASUREMENT_MEM_USE * evel_measurement_new_mem_use_add(EVENT_MEASUREMENT * measurement,
+ char * id, char *vmidentifier, double membuffsz)
+{
+ MEASUREMENT_MEM_USE * mem_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(id != NULL);
+ assert(membuffsz >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding id=%s buffer size=%lf", id, membuffsz);
+ mem_use = malloc(sizeof(MEASUREMENT_MEM_USE));
+ assert(mem_use != NULL);
+ memset(mem_use, 0, sizeof(MEASUREMENT_MEM_USE));
+ mem_use->id = strdup(id);
+ mem_use->vmid = strdup(vmidentifier);
+ mem_use->membuffsz = membuffsz;
+ evel_init_option_double(&mem_use->memcache);
+ evel_init_option_double(&mem_use->memconfig);
+ evel_init_option_double(&mem_use->memfree);
+ evel_init_option_double(&mem_use->slabrecl);
+ evel_init_option_double(&mem_use->slabunrecl);
+ evel_init_option_double(&mem_use->memused);
+
+ assert(mem_use->id != NULL);
+
+ dlist_push_last(&measurement->mem_usage, mem_use);
+
+ EVEL_EXIT();
+ return mem_use;
+}
+
+/**************************************************************************//**
+ * Set kilobytes of memory used for cache
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_memcache_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&mem_use->memcache, val, "Memory cache value");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set kilobytes of memory configured in the virtual machine on which the VNFC reporting
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_memconfig_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&mem_use->memconfig, val, "Memory configured value");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set kilobytes of physical RAM left unused by the system
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_memfree_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&mem_use->memfree, val, "Memory freely available value");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the part of the slab that can be reclaimed such as caches measured in kilobytes
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_slab_reclaimed_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&mem_use->slabrecl, val, "Memory reclaimable slab set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the part of the slab that cannot be reclaimed such as caches measured in kilobytes
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_slab_unreclaimable_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&mem_use->slabunrecl, val, "Memory unreclaimable slab set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the total memory minus the sum of free, buffered, cached and slab memory in kilobytes
+ *
+ * @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 mem_use Pointer to the Memory Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_mem_use_usedup_set(MEASUREMENT_MEM_USE * const mem_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&mem_use->memused, val, "Memory usedup total set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an additional Disk 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 Disk utilization.
+ *****************************************************************************/
+MEASUREMENT_DISK_USE * evel_measurement_new_disk_use_add(EVENT_MEASUREMENT * measurement, char * id)
+{
+ MEASUREMENT_DISK_USE * disk_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(id != NULL);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding id=%s disk usage", id);
+ disk_use = malloc(sizeof(MEASUREMENT_DISK_USE));
+ assert(disk_use != NULL);
+ memset(disk_use, 0, sizeof(MEASUREMENT_DISK_USE));
+ disk_use->id = strdup(id);
+ assert(disk_use->id != NULL);
+ dlist_push_last(&measurement->disk_usage, disk_use);
+
+ evel_init_option_double(&disk_use->iotimeavg );
+ evel_init_option_double(&disk_use->iotimelast );
+ evel_init_option_double(&disk_use->iotimemax );
+ evel_init_option_double(&disk_use->iotimemin );
+ evel_init_option_double(&disk_use->mergereadavg );
+ evel_init_option_double(&disk_use->mergereadlast );
+ evel_init_option_double(&disk_use->mergereadmax );
+ evel_init_option_double(&disk_use->mergereadmin );
+ evel_init_option_double(&disk_use->mergewriteavg );
+ evel_init_option_double(&disk_use->mergewritelast );
+ evel_init_option_double(&disk_use->mergewritemax );
+ evel_init_option_double(&disk_use->mergewritemin );
+ evel_init_option_double(&disk_use->octetsreadavg );
+ evel_init_option_double(&disk_use->octetsreadlast );
+ evel_init_option_double(&disk_use->octetsreadmax );
+ evel_init_option_double(&disk_use->octetsreadmin );
+ evel_init_option_double(&disk_use->octetswriteavg );
+ evel_init_option_double(&disk_use->octetswritelast );
+ evel_init_option_double(&disk_use->octetswritemax );
+ evel_init_option_double(&disk_use->octetswritemin );
+ evel_init_option_double(&disk_use->opsreadavg );
+ evel_init_option_double(&disk_use->opsreadlast );
+ evel_init_option_double(&disk_use->opsreadmax );
+ evel_init_option_double(&disk_use->opsreadmin );
+ evel_init_option_double(&disk_use->opswriteavg );
+ evel_init_option_double(&disk_use->opswritelast );
+ evel_init_option_double(&disk_use->opswritemax );
+ evel_init_option_double(&disk_use->opswritemin );
+ evel_init_option_double(&disk_use->pendingopsavg );
+ evel_init_option_double(&disk_use->pendingopslast );
+ evel_init_option_double(&disk_use->pendingopsmax );
+ evel_init_option_double(&disk_use->pendingopsmin );
+ evel_init_option_double(&disk_use->timereadavg );
+ evel_init_option_double(&disk_use->timereadlast );
+ evel_init_option_double(&disk_use->timereadmax );
+ evel_init_option_double(&disk_use->timereadmin );
+ evel_init_option_double(&disk_use->timewriteavg );
+ evel_init_option_double(&disk_use->timewritelast );
+ evel_init_option_double(&disk_use->timewritemax );
+ evel_init_option_double(&disk_use->timewritemin );
+
+ EVEL_EXIT();
+ return disk_use;
+}
+
+/**************************************************************************//**
+ * Set milliseconds spent doing input/output operations over 1 sec; treat
+ * this metric as a device load percentage where 1000ms matches 100% load;
+ * provide the average over the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_iotimeavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->iotimeavg, val, "Disk ioload set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set milliseconds spent doing input/output operations over 1 sec; treat
+ * this metric as a device load percentage where 1000ms matches 100% load;
+ * provide the last value within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_iotimelast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->iotimelast, val, "Disk ioloadlast set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set milliseconds spent doing input/output operations over 1 sec; treat
+ * this metric as a device load percentage where 1000ms matches 100% load;
+ * provide the maximum value within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_iotimemax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->iotimemax, val, "Disk ioloadmax set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set milliseconds spent doing input/output operations over 1 sec; treat
+ * this metric as a device load percentage where 1000ms matches 100% load;
+ * provide the minimum value within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_iotimemin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->iotimemin, val, "Disk ioloadmin set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of logical read operations that were merged into physical read
+ * operations, e.g., two logical reads were served by one physical disk access;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergereadavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergereadavg, val, "Disk Merged read average set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of logical read operations that were merged into physical read
+ * operations, e.g., two logical reads were served by one physical disk access;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergereadlast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergereadlast, val, "Disk mergedload last set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of logical read operations that were merged into physical read
+ * operations, e.g., two logical reads were served by one physical disk access;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergereadmax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergereadmax, val, "Disk merged loadmax set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of logical read operations that were merged into physical read
+ * operations, e.g., two logical reads were served by one physical disk access;
+ * provide the minimum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergereadmin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergereadmin, val, "Disk merged loadmin set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of logical write operations that were merged into physical read
+ * operations, e.g., two logical writes were served by one physical disk access;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergewritelast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergewritelast, val, "Disk merged writelast set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of logical write operations that were merged into physical read
+ * operations, e.g., two logical writes were served by one physical disk access;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergewritemax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergewritemax, val, "Disk writemax set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of logical write operations that were merged into physical read
+ * operations, e.g., two logical writes were served by one physical disk access;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_mergewritemin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->mergewritemin, val, "Disk writemin set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of octets per second read from a disk or partition;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetsreadavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetsreadavg, val, "Octets readavg set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of octets per second read from a disk or partition;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetsreadlast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetsreadlast, val, "Octets readlast set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of octets per second read from a disk or partition;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetsreadmax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetsreadmax, val, "Octets readmax set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of octets per second read from a disk or partition;
+ * provide the minimum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetsreadmin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetsreadmin, val, "Octets readmin set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of octets per second written to a disk or partition;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetswriteavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetswriteavg, val, "Octets writeavg set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of octets per second written to a disk or partition;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetswritelast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetswritelast, val, "Octets writelast set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of octets per second written to a disk or partition;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetswritemax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetswritemax, val, "Octets writemax set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of octets per second written to a disk or partition;
+ * provide the minimum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_octetswritemin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->octetswritemin, val, "Octets writemin set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of read operations per second issued to the disk;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opsreadavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opsreadavg, val, "Disk read operation average set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of read operations per second issued to the disk;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opsreadlast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opsreadlast, val, "Disk read operation last set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of read operations per second issued to the disk;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opsreadmax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opsreadmax, val, "Disk read operation maximum set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of read operations per second issued to the disk;
+ * provide the minimum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opsreadmin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opsreadmin, val, "Disk read operation minimum set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of write operations per second issued to the disk;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opswriteavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opswriteavg, val, "Disk write operation average set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of write operations per second issued to the disk;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opswritelast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opswritelast, val, "Disk write operation last set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set number of write operations per second issued to the disk;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opswritemax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opswritemax, val, "Disk write operation maximum set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set number of write operations per second issued to the disk;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_opswritemin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->opswritemin, val, "Disk write operation minimum set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set queue size of pending I/O operations per second;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_pendingopsavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->pendingopsavg, val, "Disk pending operation average set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set queue size of pending I/O operations per second;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_pendingopslast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->pendingopslast, val, "Disk pending operation last set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set queue size of pending I/O operations per second;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_pendingopsmax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->pendingopsmax, val, "Disk pending operation maximum set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set queue size of pending I/O operations per second;
+ * provide the minimum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_pendingopsmin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->pendingopsmin, val, "Disk pending operation min set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set milliseconds a read operation took to complete;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timereadavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timereadavg, val, "Disk read time average set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set milliseconds a read operation took to complete;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timereadlast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timereadlast, val, "Disk read time last set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set milliseconds a read operation took to complete;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timereadmax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timereadmax, val, "Disk read time maximum set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set milliseconds a read operation took to complete;
+ * provide the minimum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timereadmin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timereadmin, val, "Disk read time minimum set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set milliseconds a write operation took to complete;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timewriteavg_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timewriteavg, val, "Disk write time average set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set milliseconds a write operation took to complete;
+ * provide the last measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timewritelast_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timewritelast, val, "Disk write time last set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set milliseconds a write operation took to complete;
+ * provide the maximum measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timewritemax_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timewritemax, val, "Disk write time max set");
+ EVEL_EXIT();
+}
+/**************************************************************************//**
+ * Set milliseconds a write operation took to complete;
+ * provide the average measurement within the measurement interval
+ *
+ * @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 disk_use Pointer to the Disk Use.
+ * @param val double
+ *****************************************************************************/
+void evel_measurement_disk_use_timewritemin_set(MEASUREMENT_DISK_USE * const disk_use,
+ const double val)
+{
+ EVEL_ENTER();
+ evel_set_option_double(&disk_use->timewritemin, val, "Disk write time min set");
+ 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,
+ double block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ double 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.0);
+ assert(ephemeral_configured >= 0.0);
+ assert(ephemeral_used >= 0.0);
+ assert(ephemeral_iops >= 0.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 = ephemeral_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 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,
+ int 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_int(&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_PERFORMANCE 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_PERFORMANCE has immutable
+ * properties.
+ *
+ * @param vnic_id ASCIIZ string with the vNIC's ID.
+ * @param val_suspect True or false confidence in data.
+ *
+ * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_PERFORMANCE.
+ * If the structure is not used it must be released using
+ * ::evel_measurement_free_vnic_performance.
+ * @retval NULL Failed to create the vNIC Use.
+ *****************************************************************************/
+MEASUREMENT_VNIC_PERFORMANCE * evel_measurement_new_vnic_performance(char * const vnic_id,
+ char * const val_suspect)
+{
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_performance;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vnic_id != NULL);
+ assert(!strcmp(val_suspect,"true") || !strcmp(val_suspect,"false"));
+
+ /***************************************************************************/
+ /* Allocate, then set Mandatory Parameters. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding VNIC ID=%s", vnic_id);
+ vnic_performance = malloc(sizeof(MEASUREMENT_VNIC_PERFORMANCE));
+ assert(vnic_performance != NULL);
+ vnic_performance->vnic_id = strdup(vnic_id);
+ vnic_performance->valuesaresuspect = strdup(val_suspect);
+
+ /***************************************************************************/
+ /* Initialize Optional Parameters. */
+ /***************************************************************************/
+ evel_init_option_double(&vnic_performance-> recvd_bcast_packets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_bcast_packets_delta);
+ evel_init_option_double(&vnic_performance-> recvd_discarded_packets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_discarded_packets_delta);
+ evel_init_option_double(&vnic_performance-> recvd_error_packets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_error_packets_delta);
+ evel_init_option_double(&vnic_performance-> recvd_mcast_packets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_mcast_packets_delta);
+ evel_init_option_double(&vnic_performance-> recvd_octets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_octets_delta);
+ evel_init_option_double(&vnic_performance-> recvd_total_packets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_total_packets_delta);
+ evel_init_option_double(&vnic_performance-> recvd_ucast_packets_acc);
+ evel_init_option_double(&vnic_performance-> recvd_ucast_packets_delta);
+ evel_init_option_double(&vnic_performance-> tx_bcast_packets_acc);
+ evel_init_option_double(&vnic_performance-> tx_bcast_packets_delta);
+ evel_init_option_double(&vnic_performance-> tx_discarded_packets_acc);
+ evel_init_option_double(&vnic_performance-> tx_discarded_packets_delta);
+ evel_init_option_double(&vnic_performance-> tx_error_packets_acc);
+ evel_init_option_double(&vnic_performance-> tx_error_packets_delta);
+ evel_init_option_double(&vnic_performance-> tx_mcast_packets_acc);
+ evel_init_option_double(&vnic_performance-> tx_mcast_packets_delta);
+ evel_init_option_double(&vnic_performance-> tx_octets_acc);
+ evel_init_option_double(&vnic_performance-> tx_octets_delta);
+ evel_init_option_double(&vnic_performance-> tx_total_packets_acc);
+ evel_init_option_double(&vnic_performance-> tx_total_packets_delta);
+ evel_init_option_double(&vnic_performance-> tx_ucast_packets_acc);
+ evel_init_option_double(&vnic_performance-> tx_ucast_packets_delta);
+
+ EVEL_EXIT();
+
+ return vnic_performance;
+}
+
+/**************************************************************************//**
+ * Free a vNIC Use.
+ *
+ * Free off the ::MEASUREMENT_VNIC_PERFORMANCE 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_measurement_free_vnic_performance(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vnic_performance != NULL);
+ assert(vnic_performance->vnic_id != NULL);
+ assert(vnic_performance->valuesaresuspect != NULL);
+
+ /***************************************************************************/
+ /* Free the duplicated string. */
+ /***************************************************************************/
+ free(vnic_performance->vnic_id);
+ free(vnic_performance->valuesaresuspect);
+ vnic_performance->vnic_id = NULL;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Accumulated Broadcast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_bcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_bcast_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_bcast_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_bcast_packets_acc,
+ recvd_bcast_packets_acc,
+ "Broadcast Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Broadcast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_bcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_bcast_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_bcast_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_bcast_packets_delta,
+ recvd_bcast_packets_delta,
+ "Delta Broadcast Packets recieved");
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the Discarded Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_discard_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_discard_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_discard_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_discard_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_discarded_packets_acc,
+ recvd_discard_packets_acc,
+ "Discarded Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Discarded Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_discard_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_discard_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_discard_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_discard_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_discarded_packets_delta,
+ recvd_discard_packets_delta,
+ "Delta Discarded Packets recieved");
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the Error Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_error_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_error_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_error_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_error_packets_acc,
+ recvd_error_packets_acc,
+ "Error Packets received accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Error Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_error_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_error_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_error_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_error_packets_delta,
+ recvd_error_packets_delta,
+ "Delta Error Packets recieved");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Accumulated Multicast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_mcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_mcast_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_mcast_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_mcast_packets_acc,
+ recvd_mcast_packets_acc,
+ "Multicast Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Multicast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_mcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_mcast_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_mcast_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_mcast_packets_delta,
+ recvd_mcast_packets_delta,
+ "Delta Multicast Packets recieved");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Accumulated Octets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_octets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_octets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_octets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_octets_acc,
+ recvd_octets_acc,
+ "Octets received accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Octets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_octets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_octets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_octets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_octets_delta,
+ recvd_octets_delta,
+ "Delta Octets recieved");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Accumulated Total Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_total_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_total_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_total_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_total_packets_acc,
+ recvd_total_packets_acc,
+ "Total Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Total Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_total_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_total_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_total_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_total_packets_delta,
+ recvd_total_packets_delta,
+ "Delta Total Packets recieved");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Accumulated Unicast Packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_ucast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_rx_ucast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_ucast_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_ucast_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_ucast_packets_acc,
+ recvd_ucast_packets_acc,
+ "Unicast Packets received accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Unicast packets Received in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param recvd_ucast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_rx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double recvd_ucast_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(recvd_ucast_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->recvd_ucast_packets_delta,
+ recvd_ucast_packets_delta,
+ "Delta Unicast packets recieved");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Transmitted Broadcast Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_bcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_bcast_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_bcast_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_bcast_packets_acc,
+ tx_bcast_packets_acc,
+ "Transmitted Broadcast Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Broadcast packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_bcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_bcast_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_bcast_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_bcast_packets_delta,
+ tx_bcast_packets_delta,
+ "Delta Transmitted Broadcast packets ");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Transmitted Discarded Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_discarded_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_discarded_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_discarded_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_discarded_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_discarded_packets_acc,
+ tx_discarded_packets_acc,
+ "Transmitted Discarded Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Discarded packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_discarded_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_discarded_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_discarded_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_discarded_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_discarded_packets_delta,
+ tx_discarded_packets_delta,
+ "Delta Transmitted Discarded packets ");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Transmitted Errored Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_error_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_error_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_error_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_error_packets_acc,
+ tx_error_packets_acc,
+ "Transmitted Error Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Errored packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_error_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_error_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_error_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_error_packets_delta,
+ tx_error_packets_delta,
+ "Delta Transmitted Error packets ");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Transmitted Multicast Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_mcast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_mcast_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_mcast_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_mcast_packets_acc,
+ tx_mcast_packets_acc,
+ "Transmitted Multicast Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Multicast packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_mcast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_mcast_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_mcast_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_mcast_packets_delta,
+ tx_mcast_packets_delta,
+ "Delta Transmitted Multicast packets ");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Transmitted Octets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_octets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_octets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_octets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_octets_acc,
+ tx_octets_acc,
+ "Transmitted Octets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Octets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_octets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_octets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_octets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_octets_delta,
+ tx_octets_delta,
+ "Delta Transmitted Octets ");
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the Transmitted Total Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_total_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_total_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_total_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_total_packets_acc,
+ tx_total_packets_acc,
+ "Transmitted Total Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Total Packets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_total_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_total_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_total_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_total_packets_delta,
+ tx_total_packets_delta,
+ "Delta Transmitted Total Packets ");
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the Transmitted Unicast Packets in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_ucast_packets_acc
+ *****************************************************************************/
+void evel_vnic_performance_tx_ucast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_ucast_packets_acc)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_ucast_packets_acc >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_ucast_packets_acc,
+ tx_ucast_packets_acc,
+ "Transmitted Unicast Packets accumulated");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Delta Octets Transmitted in measurement interval
+ * property of the vNIC performance.
+ *
+ * @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_performance Pointer to the vNIC Use.
+ * @param tx_ucast_packets_delta
+ *****************************************************************************/
+void evel_vnic_performance_tx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance,
+ const double tx_ucast_packets_delta)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(tx_ucast_packets_delta >= 0.0);
+
+ evel_set_option_double(&vnic_performance->tx_ucast_packets_delta,
+ tx_ucast_packets_delta,
+ "Delta Transmitted Unicast Packets ");
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Add an additional vNIC Use to the specified Measurement event.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param vnic_performance Pointer to the vNIC Use to add.
+ *****************************************************************************/
+void evel_meas_vnic_performance_add(EVENT_MEASUREMENT * const measurement,
+ MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(vnic_performance != NULL);
+
+ dlist_push_last(&measurement->vnic_usage, vnic_performance);
+
+ 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 valset true or false confidence level
+ * @param recvd_bcast_packets_acc Recieved broadcast packets
+ * @param recvd_bcast_packets_delta Received delta broadcast packets
+ * @param recvd_discarded_packets_acc Recieved discarded packets
+ * @param recvd_discarded_packets_delta Received discarded delta packets
+ * @param recvd_error_packets_acc Received error packets
+ * @param recvd_error_packets_delta, Received delta error packets
+ * @param recvd_mcast_packets_acc Received multicast packets
+ * @param recvd_mcast_packets_delta Received delta multicast packets
+ * @param recvd_octets_acc Received octets
+ * @param recvd_octets_delta Received delta octets
+ * @param recvd_total_packets_acc Received total packets
+ * @param recvd_total_packets_delta Received delta total packets
+ * @param recvd_ucast_packets_acc Received Unicast packets
+ * @param recvd_ucast_packets_delta Received delta unicast packets
+ * @param tx_bcast_packets_acc Transmitted broadcast packets
+ * @param tx_bcast_packets_delta Transmitted delta broadcast packets
+ * @param tx_discarded_packets_acc Transmitted packets discarded
+ * @param tx_discarded_packets_delta Transmitted delta discarded packets
+ * @param tx_error_packets_acc Transmitted error packets
+ * @param tx_error_packets_delta Transmitted delta error packets
+ * @param tx_mcast_packets_acc Transmitted multicast packets accumulated
+ * @param tx_mcast_packets_delta Transmitted delta multicast packets
+ * @param tx_octets_acc Transmitted octets
+ * @param tx_octets_delta Transmitted delta octets
+ * @param tx_total_packets_acc Transmitted total packets
+ * @param tx_total_packets_delta Transmitted delta total packets
+ * @param tx_ucast_packets_acc Transmitted Unicast packets
+ * @param tx_ucast_packets_delta Transmitted delta Unicast packets
+ *****************************************************************************/
+void evel_measurement_vnic_performance_add(EVENT_MEASUREMENT * const measurement,
+ char * const vnic_id,
+ char * valset,
+ double recvd_bcast_packets_acc,
+ double recvd_bcast_packets_delta,
+ double recvd_discarded_packets_acc,
+ double recvd_discarded_packets_delta,
+ double recvd_error_packets_acc,
+ double recvd_error_packets_delta,
+ double recvd_mcast_packets_acc,
+ double recvd_mcast_packets_delta,
+ double recvd_octets_acc,
+ double recvd_octets_delta,
+ double recvd_total_packets_acc,
+ double recvd_total_packets_delta,
+ double recvd_ucast_packets_acc,
+ double recvd_ucast_packets_delta,
+ double tx_bcast_packets_acc,
+ double tx_bcast_packets_delta,
+ double tx_discarded_packets_acc,
+ double tx_discarded_packets_delta,
+ double tx_error_packets_acc,
+ double tx_error_packets_delta,
+ double tx_mcast_packets_acc,
+ double tx_mcast_packets_delta,
+ double tx_octets_acc,
+ double tx_octets_delta,
+ double tx_total_packets_acc,
+ double tx_total_packets_delta,
+ double tx_ucast_packets_acc,
+ double tx_ucast_packets_delta)
+{
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Trust the assertions in the underlying methods. */
+ /***************************************************************************/
+ vnic_performance = evel_measurement_new_vnic_performance(vnic_id, valset);
+
+ evel_vnic_performance_rx_bcast_pkt_acc_set(vnic_performance, recvd_bcast_packets_acc);
+ evel_vnic_performance_rx_bcast_pkt_delta_set(vnic_performance, recvd_bcast_packets_delta);
+ evel_vnic_performance_rx_discard_pkt_acc_set(vnic_performance, recvd_discarded_packets_acc);
+ evel_vnic_performance_rx_discard_pkt_delta_set(vnic_performance, recvd_discarded_packets_delta);
+ evel_vnic_performance_rx_error_pkt_acc_set(vnic_performance, recvd_error_packets_acc);
+ evel_vnic_performance_rx_error_pkt_delta_set(vnic_performance, recvd_error_packets_delta);
+ evel_vnic_performance_rx_mcast_pkt_acc_set(vnic_performance, recvd_mcast_packets_acc);
+ evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, recvd_mcast_packets_delta);
+ evel_vnic_performance_rx_octets_acc_set(vnic_performance, recvd_octets_acc);
+ evel_vnic_performance_rx_octets_delta_set(vnic_performance, recvd_octets_delta);
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, recvd_total_packets_acc);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, recvd_total_packets_delta);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_performance, recvd_ucast_packets_acc);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_performance, recvd_ucast_packets_delta);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_performance, tx_bcast_packets_acc);
+ evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_performance, tx_bcast_packets_delta);
+ evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_performance, tx_discarded_packets_acc);
+ evel_vnic_performance_tx_discarded_pkt_delta_set(vnic_performance, tx_discarded_packets_delta);
+ evel_vnic_performance_tx_error_pkt_acc_set(vnic_performance, tx_error_packets_acc);
+ evel_vnic_performance_tx_error_pkt_delta_set(vnic_performance, tx_error_packets_delta);
+ evel_vnic_performance_tx_mcast_pkt_acc_set(vnic_performance, tx_mcast_packets_acc);
+ evel_vnic_performance_tx_mcast_pkt_delta_set(vnic_performance, tx_mcast_packets_delta);
+ evel_vnic_performance_tx_octets_acc_set(vnic_performance, tx_octets_acc);
+ evel_vnic_performance_tx_octets_delta_set(vnic_performance, tx_octets_delta);
+ evel_vnic_performance_tx_total_pkt_acc_set(vnic_performance, tx_total_packets_acc);
+ evel_vnic_performance_tx_total_pkt_delta_set(vnic_performance, tx_total_packets_delta);
+ evel_vnic_performance_tx_ucast_pkt_acc_set(vnic_performance, tx_ucast_packets_acc);
+ evel_vnic_performance_tx_ucast_pkt_delta_set(vnic_performance, tx_ucast_packets_delta);
+ evel_meas_vnic_performance_add(measurement, vnic_performance);
+}
+
+/**************************************************************************//**
+ * 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_MEM_USE * mem_use = NULL;
+ MEASUREMENT_DISK_USE * disk_use = NULL;
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = 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;
+ DLIST_ITEM * addl_info_item = NULL;
+ OTHER_FIELD *addl_info = 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_int(jbuf, "measurementInterval", event->measurement_interval);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ // additional fields
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
+ {
+ bool item_added = false;
+
+ addl_info_item = dlist_get_first(&event->additional_info);
+ while (addl_info_item != NULL)
+ {
+ addl_info = (OTHER_FIELD*) addl_info_item->item;
+ assert(addl_info != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalFields",
+ 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);
+ }
+ }
+
+ // TBD additional json objects
+ 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_opt_double(jbuf, "cpuIdle", &cpu_use->idle);
+ evel_enc_kv_opt_double(jbuf, "cpuUsageInterrupt", &cpu_use->intrpt);
+ evel_enc_kv_opt_double(jbuf, "cpuUsageNice", &cpu_use->nice);
+ evel_enc_kv_opt_double(jbuf, "cpuUsageSoftIrq", &cpu_use->softirq);
+ evel_enc_kv_opt_double(jbuf, "cpuUsageSteal", &cpu_use->steal);
+ evel_enc_kv_opt_double(jbuf, "cpuUsageSystem", &cpu_use->sys);
+ evel_enc_kv_opt_double(jbuf, "cpuUsageUser", &cpu_use->user);
+ evel_enc_kv_opt_double(jbuf, "cpuWait", &cpu_use->wait);
+ 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);
+ }
+ }
+
+
+ /***************************************************************************/
+ /* Disk Use list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "diskUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->disk_usage);
+ while (item != NULL)
+ {
+ disk_use = (MEASUREMENT_DISK_USE*) item->item;
+ assert(disk_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "diskUsageArray",
+ disk_use->id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "diskIdentifier", disk_use->id);
+ evel_enc_kv_opt_double(jbuf, "diskIoTimeAvg", &disk_use->iotimeavg);
+ evel_enc_kv_opt_double(jbuf, "diskIoTimeLast", &disk_use->iotimelast);
+ evel_enc_kv_opt_double(jbuf, "diskIoTimeMax", &disk_use->iotimemax);
+ evel_enc_kv_opt_double(jbuf, "diskIoTimeMin", &disk_use->iotimemin);
+ evel_enc_kv_opt_double(jbuf, "diskMergedReadAvg", &disk_use->mergereadavg);
+ evel_enc_kv_opt_double(jbuf, "diskMergedReadLast", &disk_use->mergereadlast);
+ evel_enc_kv_opt_double(jbuf, "diskMergedReadMax", &disk_use->mergereadmax);
+ evel_enc_kv_opt_double(jbuf, "diskMergedReadMin", &disk_use->mergereadmin);
+ evel_enc_kv_opt_double(jbuf, "diskMergedWriteAvg", &disk_use->mergewriteavg);
+ evel_enc_kv_opt_double(jbuf, "diskMergedWriteLast", &disk_use->mergewritelast);
+ evel_enc_kv_opt_double(jbuf, "diskMergedWriteMax", &disk_use->mergewritemax);
+ evel_enc_kv_opt_double(jbuf, "diskMergedWriteMin", &disk_use->mergewritemin);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsReadAvg", &disk_use->octetsreadavg);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsReadLast", &disk_use->octetsreadlast);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsReadMax", &disk_use->octetsreadmax);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsReadMin", &disk_use->octetsreadmin);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsWriteAvg", &disk_use->octetswriteavg);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsWriteLast", &disk_use->octetswritelast);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsWriteMax", &disk_use->octetswritemax);
+ evel_enc_kv_opt_double(jbuf, "diskOctetsWriteMin", &disk_use->octetswritemin);
+ evel_enc_kv_opt_double(jbuf, "diskOpsReadAvg", &disk_use->opsreadavg);
+ evel_enc_kv_opt_double(jbuf, "diskOpsReadLast", &disk_use->opsreadlast);
+ evel_enc_kv_opt_double(jbuf, "diskOpsReadMax", &disk_use->opsreadmax);
+ evel_enc_kv_opt_double(jbuf, "diskOpsReadMin", &disk_use->opsreadmin);
+ evel_enc_kv_opt_double(jbuf, "diskOpsWriteAvg", &disk_use->opswriteavg);
+ evel_enc_kv_opt_double(jbuf, "diskOpsWriteLast", &disk_use->opswritelast);
+ evel_enc_kv_opt_double(jbuf, "diskOpsWriteMax", &disk_use->opswritemax);
+ evel_enc_kv_opt_double(jbuf, "diskOpsWriteMin", &disk_use->opswritemin);
+ evel_enc_kv_opt_double(jbuf, "diskPendingOperationsAvg", &disk_use->pendingopsavg);
+ evel_enc_kv_opt_double(jbuf, "diskPendingOperationsLast", &disk_use->pendingopslast);
+ evel_enc_kv_opt_double(jbuf, "diskPendingOperationsMax", &disk_use->pendingopsmax);
+ evel_enc_kv_opt_double(jbuf, "diskPendingOperationsMin", &disk_use->pendingopsmin);
+ evel_enc_kv_opt_double(jbuf, "diskTimeReadAvg", &disk_use->timereadavg);
+ evel_enc_kv_opt_double(jbuf, "diskTimeReadLast", &disk_use->timereadlast);
+ evel_enc_kv_opt_double(jbuf, "diskTimeReadMax", &disk_use->timereadmax);
+ evel_enc_kv_opt_double(jbuf, "diskTimeReadMin", &disk_use->timereadmin);
+ evel_enc_kv_opt_double(jbuf, "diskTimeWriteAvg", &disk_use->timewriteavg);
+ evel_enc_kv_opt_double(jbuf, "diskTimeWriteLast", &disk_use->timewritelast);
+ evel_enc_kv_opt_double(jbuf, "diskTimeWriteMax", &disk_use->timewritemax);
+ evel_enc_kv_opt_double(jbuf, "diskTimeWriteMin", &disk_use->timewritemin);
+ 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_string(jbuf, "filesystemName", fsys_use->filesystem_name);
+ evel_enc_kv_double(
+ jbuf, "blockConfigured", fsys_use->block_configured);
+ evel_enc_kv_double(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_double(jbuf, "ephemeralIops", fsys_use->ephemeral_iops);
+ evel_enc_kv_double(jbuf, "ephemeralUsed", fsys_use->ephemeral_used);
+ 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_int(jbuf, "requestRate", &event->request_rate);
+
+ /***************************************************************************/
+ /* vNIC Usage TBD Performance array */
+ /***************************************************************************/
+ 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_performance = (MEASUREMENT_VNIC_PERFORMANCE *) item->item;
+ assert(vnic_performance != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "vNicPerformanceArray",
+ vnic_performance->vnic_id))
+ {
+ evel_json_open_object(jbuf);
+
+ /*********************************************************************/
+ /* Optional fields. */
+ /*********************************************************************/
+ evel_enc_kv_opt_double( jbuf,
+ "receivedBroadcastPacketsAccumulated", &vnic_performance->recvd_bcast_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedBroadcastPacketsDelta", &vnic_performance->recvd_bcast_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedDiscardedPacketsAccumulated", &vnic_performance->recvd_discarded_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedDiscardedPacketsDelta", &vnic_performance->recvd_discarded_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedErrorPacketsAccumulated", &vnic_performance->recvd_error_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedErrorPacketsDelta", &vnic_performance->recvd_error_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedMulticastPacketsAccumulated", &vnic_performance->recvd_mcast_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedMulticastPacketsDelta", &vnic_performance->recvd_mcast_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedOctetsAccumulated", &vnic_performance->recvd_octets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedOctetsDelta", &vnic_performance->recvd_octets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedTotalPacketsAccumulated", &vnic_performance->recvd_total_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedTotalPacketsDelta", &vnic_performance->recvd_total_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedUnicastPacketsAccumulated", &vnic_performance->recvd_ucast_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "receivedUnicastPacketsDelta", &vnic_performance->recvd_ucast_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedBroadcastPacketsAccumulated", &vnic_performance->tx_bcast_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedBroadcastPacketsDelta", &vnic_performance->tx_bcast_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedDiscardedPacketsAccumulated", &vnic_performance->tx_discarded_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedDiscardedPacketsDelta", &vnic_performance->tx_discarded_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedErrorPacketsAccumulated", &vnic_performance->tx_error_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedErrorPacketsDelta", &vnic_performance->tx_error_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedMulticastPacketsAccumulated", &vnic_performance->tx_mcast_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedMulticastPacketsDelta", &vnic_performance->tx_mcast_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedOctetsAccumulated", &vnic_performance->tx_octets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedOctetsDelta", &vnic_performance->tx_octets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedTotalPacketsAccumulated", &vnic_performance->tx_total_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedTotalPacketsDelta", &vnic_performance->tx_total_packets_delta);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedUnicastPacketsAccumulated", &vnic_performance->tx_ucast_packets_acc);
+ evel_enc_kv_opt_double( jbuf,
+ "transmittedUnicastPacketsDelta", &vnic_performance->tx_ucast_packets_delta);
+
+ /*********************************************************************/
+ /* Mandatory fields. */
+ /*********************************************************************/
+ evel_enc_kv_string(jbuf, "valuesAreSuspect", vnic_performance->valuesaresuspect);
+ evel_enc_kv_string(jbuf, "vNicIdentifier", vnic_performance->vnic_id);
+
+ 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);
+ }
+ }
+
+
+ /***************************************************************************/
+ /* Memory Use list. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "memoryUsageArray"))
+ {
+ bool item_added = false;
+
+ item = dlist_get_first(&event->mem_usage);
+ while (item != NULL)
+ {
+ mem_use = (MEASUREMENT_MEM_USE*) item->item;
+ assert(mem_use != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "memoryUsageArray",
+ mem_use->id))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_double(jbuf, "memoryBuffered", mem_use->membuffsz);
+ evel_enc_kv_opt_double(jbuf, "memoryCached", &mem_use->memcache);
+ evel_enc_kv_opt_double(jbuf, "memoryConfigured", &mem_use->memconfig);
+ evel_enc_kv_opt_double(jbuf, "memoryFree", &mem_use->memfree);
+ evel_enc_kv_opt_double(jbuf, "memorySlabRecl", &mem_use->slabrecl);
+ evel_enc_kv_opt_double(jbuf, "memorySlabUnrecl", &mem_use->slabunrecl);
+ evel_enc_kv_opt_double(jbuf, "memoryUsed", &mem_use->memused);
+ evel_enc_kv_string(jbuf, "vmIdentifier", mem_use->id);
+ 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_int(
+ jbuf, "numberOfMediaPortsInUse", &event->media_ports_in_use);
+ evel_enc_kv_opt_int(
+ 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->minor_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_DISK_USE * disk_use = NULL;
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_MEM_USE * mem_use = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * measurement = NULL;
+ OTHER_FIELD *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_MEASUREMENT);
+
+ /***************************************************************************/
+ /* 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);
+ }
+
+
+
+ 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);
+ }
+ disk_use = dlist_pop_last(&event->disk_usage);
+ while (disk_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Disk use Info (%s)", disk_use->id);
+ free(disk_use->id);
+ free(disk_use);
+ disk_use = dlist_pop_last(&event->disk_usage);
+ }
+ mem_use = dlist_pop_last(&event->mem_usage);
+ while (mem_use != NULL)
+ {
+ EVEL_DEBUG("Freeing Memory use Info (%s)", mem_use->id);
+ free(mem_use->id);
+ free(mem_use->vmid);
+ free(mem_use);
+ mem_use = dlist_pop_last(&event->mem_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_performance = dlist_pop_last(&event->vnic_usage);
+ while (vnic_performance != NULL)
+ {
+ EVEL_DEBUG("Freeing vNIC performance Info (%s)", vnic_performance->vnic_id);
+ evel_measurement_free_vnic_performance(vnic_performance);
+ free(vnic_performance);
+ vnic_performance = 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c
new file mode 100644
index 0000000..45f5348
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c
@@ -0,0 +1,574 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Signaling.
+ *
+ ****************************************************************************/
+
+#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 event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @param vendor_name The vendor id to encode in the event vnf field.
+ * @param module The module to encode in the event.
+ * @param vnfname The Virtual network function to encode in the event.
+ * @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* ev_name, const char *ev_id,
+ const char * const vendor_name,
+ const char * const correlator,
+ const char * const local_ip_address,
+ const char * const local_port,
+ const char * const remote_ip_address,
+ const char * const remote_port)
+{
+ EVENT_SIGNALING * event = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(vendor_name != 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_nameid(&event->header,ev_name,ev_id);
+ event->header.event_domain = EVEL_DOMAIN_SIPSIGNALING;
+ event->major_version = EVEL_SIGNALING_MAJOR_VERSION;
+ event->minor_version = EVEL_SIGNALING_MINOR_VERSION;
+ evel_init_vendor_field(&event->vnfname_field, vendor_name);
+ evel_set_option_string(&event->correlator,correlator,"Init correlator");
+ evel_set_option_string(&event->local_ip_address,local_ip_address,"Init correlator");
+ evel_set_option_string(&event->local_port,local_port,"Init local port");
+ evel_set_option_string(&event->remote_ip_address,remote_ip_address,"Init remote ip");
+ evel_set_option_string(&event->remote_port,remote_port,"Init remote port");
+ evel_init_option_string(&event->compressed_sip);
+ evel_init_option_string(&event->summary_sip);
+ dlist_initialize(&event->additional_info);
+
+exit_label:
+
+ EVEL_EXIT();
+ return event;
+}
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the SIP signaling.
+ *
+ * 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 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_signaling_addl_info_add(EVENT_SIGNALING * event, char * name, char * value)
+{
+ FAULT_ADDL_INFO * addl_info = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ addl_info = malloc(sizeof(SIGNALING_ADDL_FIELD));
+ assert(addl_info != NULL);
+ memset(addl_info, 0, sizeof(SIGNALING_ADDL_FIELD));
+ addl_info->name = strdup(name);
+ addl_info->value = strdup(value);
+ assert(addl_info->name != NULL);
+ assert(addl_info->value != NULL);
+
+ dlist_push_last(&event->additional_info, addl_info);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * 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_SIPSIGNALING);
+ 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_SIPSIGNALING);
+ 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_SIPSIGNALING);
+ 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_SIPSIGNALING);
+ 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_SIPSIGNALING);
+ assert(remote_port != NULL);
+
+ evel_set_option_string(&event->remote_port,
+ remote_port,
+ "Remote Port");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Vendor module 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 modulename The module name to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_signaling_vnfmodule_name_set(EVENT_SIGNALING * const event,
+ const char * const module_name)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING);
+ assert(module_name != NULL);
+
+ evel_vendor_field_module_set(&event->vnfname_field, module_name);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Vendor module 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 vnfname The Virtual Network function to be set. ASCIIZ string.
+ * The caller does not need to preserve the value once
+ * the function returns.
+ *****************************************************************************/
+void evel_signaling_vnfname_set(EVENT_SIGNALING * const event,
+ const char * const vnfname)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING);
+ assert(vnfname != NULL);
+
+ evel_vendor_field_vnfname_set(&event->vnfname_field, vnfname);
+
+ 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_SIPSIGNALING);
+ 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_SIPSIGNALING);
+ assert(summary_sip != NULL);
+
+ evel_set_option_string(&event->summary_sip,
+ summary_sip,
+ "Summary SIP");
+
+ 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_SIPSIGNALING);
+ 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)
+{
+ SIGNALING_ADDL_FIELD * addl_info = NULL;
+ DLIST_ITEM * addl_info_item = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "signalingFields");
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "compressedSip", &event->compressed_sip);
+ 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_version(jbuf, "signalingFieldsVersion", event->major_version,event->minor_version);
+ evel_enc_kv_opt_string(jbuf, "summarySip", &event->summary_sip);
+ evel_json_encode_vendor_field(jbuf, &event->vnfname_field);
+
+
+ /***************************************************************************/
+ /* Checkpoint, so that we can wind back if all fields are suppressed. */
+ /***************************************************************************/
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalInformation"))
+ {
+ bool item_added = false;
+
+ addl_info_item = dlist_get_first(&event->additional_info);
+ while (addl_info_item != NULL)
+ {
+ addl_info = (SIGNALING_ADDL_FIELD*) addl_info_item->item;
+ assert(addl_info != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalInformation",
+ 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_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)
+{
+ SIGNALING_ADDL_FIELD * 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_SIPSIGNALING);
+
+ /***************************************************************************/
+ /* 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);
+ }
+
+ evel_free_event_vendor_field(&event->vnfname_field);
+ 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_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c
new file mode 100644
index 0000000..8915afa
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c
@@ -0,0 +1,286 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the State Change.
+ *
+ ****************************************************************************/
+
+#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 event_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @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 char* ev_name,
+ const char *ev_id,
+ 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_nameid(&state_change->header,ev_name,ev_id);
+ 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c
new file mode 100644
index 0000000..96db59b
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c
@@ -0,0 +1,473 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions to convert common enum types to strings.
+ *
+ ****************************************************************************/
+
+#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_HEARTBEAT_FIELD:
+ result = "heartbeat";
+ break;
+
+ case EVEL_DOMAIN_SIPSIGNALING:
+ result = "sipSignaling";
+ break;
+
+ case EVEL_DOMAIN_STATE_CHANGE:
+ result = "stateChange";
+ break;
+
+ case EVEL_DOMAIN_SYSLOG:
+ result = "syslog";
+ break;
+
+ case EVEL_DOMAIN_OTHER:
+ result = "other";
+ break;
+
+ case EVEL_DOMAIN_VOICE_QUALITY:
+ result = "voiceQuality";
+ break;
+
+ case EVEL_DOMAIN_THRESHOLD_CROSS:
+ result = "thresholdCrossingAlert";
+ 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c
new file mode 100644
index 0000000..85b0ec9
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c
@@ -0,0 +1,505 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Syslog.
+ *
+ ****************************************************************************/
+
+#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_name Unique Event Name confirming Domain AsdcModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @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(const char* ev_name, const char *ev_id,
+ 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_nameid(&syslog->header,ev_name,ev_id);
+ 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);
+ 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->additional_filters);
+ evel_init_option_string(&syslog->event_source_host);
+ evel_init_option_string(&syslog->syslog_proc);
+ evel_init_option_string(&syslog->syslog_s_data);
+ evel_init_option_string(&syslog->syslog_sdid);
+ evel_init_option_string(&syslog->syslog_severity);
+
+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_filter_set(EVENT_SYSLOG * syslog,
+ char * filter)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(filter != NULL);
+
+ evel_set_option_string(&syslog->additional_filters,
+ filter,
+ "Syslog filter string");
+
+ 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();
+}
+
+/**************************************************************************//**
+ * Set the Structured SDID 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 sdid The Structured Data to be set. ASCIIZ string. name@number
+ * Caller does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_sdid_set(EVENT_SYSLOG * syslog, const char * const sdid)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(sdid != NULL);
+
+ evel_set_option_string(&syslog->syslog_sdid,
+ sdid,
+ "SdId set");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Structured Severity 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 sdid The Structured Data to be set. ASCIIZ string.
+ * Caller does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_syslog_severity_set(EVENT_SYSLOG * syslog, const char * const severty)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(syslog != NULL);
+ assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG);
+ assert(severty != NULL);
+
+ if( !strcmp(severty,"Alert") || !strcmp(severty,"Critical") || !strcmp(severty,"Debug") ||
+ !strcmp(severty,"Emergency") || !strcmp(severty,"Error") || !strcmp(severty,"Info") ||
+ !strcmp(severty,"Notice") || !strcmp(severty,"Warning") )
+ {
+ evel_set_option_string(&syslog->syslog_severity,
+ severty,
+ "Severity set");
+ }
+ 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;
+
+ 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");
+
+ evel_enc_kv_opt_string(jbuf, "additionalFields", &event->additional_filters);
+ /***************************************************************************/
+ /* 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_enc_kv_opt_string(jbuf, "eventSourceHost", &event->event_source_host);
+ evel_enc_kv_opt_int(jbuf, "syslogFacility", &event->syslog_facility);
+ evel_enc_kv_opt_int(jbuf, "syslogPri", &event->syslog_priority);
+ 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_string(jbuf, "syslogSdId", &event->syslog_sdid);
+ evel_enc_kv_opt_string(jbuf, "syslogSev", &event->syslog_severity);
+ 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)
+{
+
+ 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. */
+ /***************************************************************************/
+
+ evel_free_option_string(&event->additional_filters);
+ 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);
+ evel_free_option_string(&event->syslog_sdid);
+ evel_free_option_string(&event->syslog_severity);
+ free(event->syslog_tag);
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c
new file mode 100644
index 0000000..f4fa620
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c
@@ -0,0 +1,531 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Threshold Cross Alerts.
+ *
+ *****************************************************************************/
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+
+/**************************************************************************//**
+ * Create a new Threshold Crossing Alert event.
+ *
+ * @note The mandatory fields on the TCA 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
+ * TCA has immutable properties.
+ *
+ * @param event_name Unique Event Name confirming Domain AsdcVnfModel Description
+ * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @param char* tcriticality Performance Counter Criticality MAJ MIN,
+ * @param char* tname Performance Counter Threshold name
+ * @param char* tthresholdCrossed Counter Threshold crossed value
+ * @param char* tvalue Counter actual value
+ * @param EVEL_EVENT_ACTION talertAction Alert set continue or clear
+ * @param char* talertDescription
+ * @param EVEL_ALERT_TYPE talertType Kind of anamoly
+ * @param unsigned long long tcollectionTimestamp time at which alert was collected
+ * @param EVEL_SEVERITIES teventSeverity Severity of Alert
+ * @param unsigned long long teventStartTimestamp Time when this alert started
+ *
+ * @returns pointer to the newly manufactured ::EVENT_THRESHOLD_CROSS. If the
+ * event is not used it must be released using
+ * ::evel_free_threshold_cross
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_THRESHOLD_CROSS * evel_new_threshold_cross(const char * ev_name, const char * ev_id,
+ char * tcriticality,
+ char * tname,
+ char * tthresholdCrossed,
+ char * tvalue,
+ EVEL_EVENT_ACTION talertAction,
+ char * talertDescription,
+ EVEL_ALERT_TYPE talertType,
+ unsigned long long tcollectionTimestamp,
+ EVEL_SEVERITIES teventSeverity,
+ unsigned long long teventStartTimestamp )
+{
+ EVENT_THRESHOLD_CROSS * event = NULL;
+ EVEL_ENTER();
+
+ assert( tcriticality!= NULL );
+ assert( tname!= NULL );
+ assert( tthresholdCrossed != NULL );
+ assert( tvalue!= NULL );
+ assert( talertDescription != NULL );
+
+
+ /***************************************************************************/
+ /* Allocate the Threshold crossing event. */
+ /***************************************************************************/
+ event = malloc(sizeof(EVENT_THRESHOLD_CROSS));
+ if (event == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(event, 0, sizeof(EVENT_THRESHOLD_CROSS));
+ EVEL_DEBUG("New Threshold Cross event is at %lp", event);
+
+ /***************************************************************************/
+ /* Initialize the header & the threshold crossing fields. */
+ /***************************************************************************/
+ evel_init_header_nameid(&event->header,ev_name,ev_id);
+ event->header.event_domain = EVEL_DOMAIN_THRESHOLD_CROSS;
+ event->major_version = EVEL_THRESHOLD_CROSS_MAJOR_VERSION;
+ event->minor_version = EVEL_THRESHOLD_CROSS_MINOR_VERSION;
+
+
+ event->additionalParameters.criticality = strdup(tcriticality);
+ event->additionalParameters.name = strdup(tname);
+ event->additionalParameters.thresholdCrossed = strdup(tthresholdCrossed);
+ event->additionalParameters.value = strdup(tvalue);
+ event->alertAction = talertAction;
+ event->alertDescription = strdup(talertDescription);
+ event->alertType = talertType;
+ event->collectionTimestamp = tcollectionTimestamp;
+ event->eventSeverity = teventSeverity;
+ event->eventStartTimestamp = teventStartTimestamp;
+
+ evel_init_option_string(&event->alertValue);
+ evel_init_option_string(&event->dataCollector);
+ evel_init_option_string(&event->elementType);
+ evel_init_option_string(&event->interfaceName);
+ evel_init_option_string(&event->networkService);
+ evel_init_option_string(&event->possibleRootCause);
+ dlist_initialize(&event->additional_info);
+ dlist_initialize(&event->alertidList);
+
+exit_label:
+
+ EVEL_EXIT();
+ return event;
+
+}
+
+
+/**************************************************************************//**
+ * Set the Event Type property of the TC Alert.
+ *
+ * @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 type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_threshold_cross_type_set(EVENT_THRESHOLD_CROSS * const event,char * type)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions and call evel_header_type_set. */
+ /***************************************************************************/
+ assert(type!=NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ evel_header_type_set(&event->header, type);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an optional additional alertid value to Alert.
+ *
+ *****************************************************************************/
+void evel_threshold_cross_alertid_add(EVENT_THRESHOLD_CROSS * const event,char * alertid)
+{
+ char *alid=NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(alertid != NULL);
+
+ EVEL_DEBUG("Adding AlertId=%s", alertid);
+ alid = strdup(alertid);
+ assert(alid != NULL);
+
+ dlist_push_last(&event->alertidList, alid);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an optional additional value name/value pair to the Alert.
+ *
+ * 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 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_threshold_cross_addl_info_add(EVENT_THRESHOLD_CROSS * const event, const char * name, const char * value)
+{
+ OTHER_FIELD * nv_pair = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ 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_info, nv_pair);
+
+ 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_threshold_cross(EVENT_THRESHOLD_CROSS * const event)
+{
+ OTHER_FIELD * addl_info = NULL;
+ char *ptr;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the API. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+
+ /***************************************************************************/
+ /* 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);
+ }
+ ptr = dlist_pop_last(&event->alertidList);
+ while (ptr != NULL)
+ {
+ free(ptr);
+ ptr = dlist_pop_last(&event->alertidList);
+ }
+
+ free(event->additionalParameters.criticality);
+ free(event->additionalParameters.name);
+ free(event->additionalParameters.thresholdCrossed);
+ free(event->additionalParameters.value);
+ free(event->alertDescription);
+
+ evel_free_option_string(&event->alertValue);
+ evel_free_option_string(&event->dataCollector);
+ evel_free_option_string(&event->elementType);
+ evel_free_option_string(&event->interfaceName);
+ evel_free_option_string(&event->networkService);
+ evel_free_option_string(&event->possibleRootCause);
+ evel_free_header(&event->header);
+
+ EVEL_EXIT();
+}
+
+ /**************************************************************************//**
+ * Set the TCA probable Root cause.
+ *
+ * @param sheader Possible root cause to Threshold
+ *****************************************************************************/
+ void evel_threshold_cross_possible_rootcause_set(EVENT_THRESHOLD_CROSS * const event, char * sheader)
+ {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(sheader != NULL);
+
+ evel_set_option_string(&event->possibleRootCause,
+ sheader,
+ "Rootcause value");
+
+ EVEL_EXIT();
+ }
+
+ /**************************************************************************//**
+ * Set the TCA networking cause.
+ *
+ * @param sheader Possible networking service value to Threshold
+ *****************************************************************************/
+ void evel_threshold_cross_networkservice_set(EVENT_THRESHOLD_CROSS * const event, char * sheader)
+ {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(sheader != NULL);
+
+ evel_set_option_string(&event->networkService,
+ sheader,
+ "Networking service value");
+
+ EVEL_EXIT();
+ }
+
+ /**************************************************************************//**
+ * Set the TCA Interface name.
+ *
+ * @param sheader Interface name to threshold
+ *****************************************************************************/
+ void evel_threshold_cross_interfacename_set(EVENT_THRESHOLD_CROSS * const event,char * sheader)
+ {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(sheader != NULL);
+
+ evel_set_option_string(&event->interfaceName,
+ sheader,
+ "TCA Interface name");
+ EVEL_EXIT();
+ }
+
+ /**************************************************************************//**
+ * Set the TCA Data element type.
+ *
+ * @param sheader element type of Threshold
+ *****************************************************************************/
+ void evel_threshold_cross_data_elementtype_set(EVENT_THRESHOLD_CROSS * const event,char * sheader)
+ {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(sheader != NULL);
+
+ evel_set_option_string(&event->elementType,
+ sheader,
+ "TCA Element type value");
+ EVEL_EXIT();
+ }
+
+ /**************************************************************************//**
+ * Set the TCA Data collector value.
+ *
+ * @param sheader Data collector value
+ *****************************************************************************/
+ void evel_threshold_cross_data_collector_set(EVENT_THRESHOLD_CROSS * const event,char * sheader)
+ {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(sheader != NULL);
+
+ evel_set_option_string(&event->dataCollector,
+ sheader,
+ "Datacollector value");
+ EVEL_EXIT();
+ }
+
+
+
+ /**************************************************************************//**
+ * Set the TCA alert value.
+ *
+ * @param sheader Possible alert value
+ *****************************************************************************/
+ void evel_threshold_cross_alertvalue_set(EVENT_THRESHOLD_CROSS * const event,char * sheader)
+ {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS);
+ assert(sheader != NULL);
+
+ evel_set_option_string(&event->alertValue,
+ sheader,
+ "Alert value");
+ 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_perf_counter( EVEL_JSON_BUFFER * jbuf, PERF_COUNTER *pcounter)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(pcounter != NULL);
+
+ evel_json_open_named_object(jbuf, "additionalParameters");
+
+ /***************************************************************************/
+ /* Mandatory parameters. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "criticality", pcounter->criticality);
+ evel_enc_kv_string(jbuf, "name", pcounter->name);
+ evel_enc_kv_string(jbuf, "thresholdCrossed", pcounter->name);
+ evel_enc_kv_string(jbuf, "value", pcounter->value);
+
+ evel_json_close_object(jbuf);
+
+ 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_threshold_cross(EVEL_JSON_BUFFER * const jbuf,
+ EVENT_THRESHOLD_CROSS * 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_THRESHOLD_CROSS);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "thresholdCrossingAlert");
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /***************************************************************************/
+ evel_json_encode_perf_counter(jbuf, &event->additionalParameters);
+ evel_enc_kv_int(jbuf, "alertAction", event->alertAction);
+ evel_enc_kv_string(jbuf, "alertDescription", event->alertDescription);
+ evel_enc_kv_int(jbuf, "alertType", event->alertType);
+ evel_enc_kv_ull(
+ jbuf, "collectionTimestamp", event->collectionTimestamp);
+ evel_enc_kv_int(jbuf, "eventSeverity", event->eventSeverity);
+ evel_enc_kv_ull(
+ jbuf, "eventStartTimestamp", event->eventStartTimestamp);
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "alertValue", &event->alertValue);
+ evel_enc_kv_opt_string(jbuf, "dataCollector", &event->dataCollector);
+ evel_enc_kv_opt_string(jbuf, "elementType", &event->elementType);
+ evel_enc_kv_opt_string(jbuf, "interfaceName", &event->interfaceName);
+ evel_enc_kv_opt_string(jbuf, "networkService", &event->networkService);
+ evel_enc_kv_opt_string(jbuf, "possibleRootCause", &event->possibleRootCause);
+
+ /***************************************************************************/
+ /* 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_info);
+ 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);
+ }
+ }
+ evel_enc_version(jbuf,
+ "thresholdCrossingFieldsVersion",
+ event->major_version,
+ event->minor_version);
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c
new file mode 100644
index 0000000..6327741
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c
@@ -0,0 +1,2103 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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.
+ *
+ ****************************************************************************/
+
+#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"
+ "voiceQuality",
+ "maxDomain"
+};
+
+/*****************************************************************************/
+/* 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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h
new file mode 100644
index 0000000..c97b3c3
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h
@@ -0,0 +1,214 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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.
+ *
+ ****************************************************************************/
+
+#ifndef EVEL_THROTTLE_INCLUDED
+#define EVEL_THROTTLE_INCLUDED
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c
new file mode 100644
index 0000000..cf2ec87
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c
@@ -0,0 +1,640 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Voice Quality.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new voice quality event.
+ *
+ * @note The mandatory fields on the Voice Quality 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 Voice Quality has immutable properties.
+ * @param event_name Unique Event Name
+ * @param event_id A universal identifier of the event for analysis etc.
+ * @param calleeSideCodec Callee codec for the call.
+ * @param callerSideCodec Caller codec for the call.
+ * @param correlator Constant across all events on this call.
+ * @param midCallRtcp Base64 encoding of the binary RTCP data
+ * (excluding Eth/IP/UDP headers).
+ * @param vendorVnfNameFields Vendor, VNF and VfModule names.
+ * @returns pointer to the newly manufactured ::EVENT_VOICE_QUALITY. If the
+ * event is not used (i.e. posted) it must be released using
+ ::evel_free_voice_quality.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_VOICE_QUALITY * evel_new_voice_quality(const char* ev_name, const char *ev_id,
+ const char * const calleeSideCodec,
+ const char * const callerSideCodec, const char * const correlator,
+ const char * const midCallRtcp, const char * const vendorName) {
+
+ bool inError = false;
+ EVENT_VOICE_QUALITY *voiceQuality = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(calleeSideCodec != NULL);
+ assert(callerSideCodec != NULL);
+ assert(correlator != NULL);
+ assert(midCallRtcp != NULL);
+ assert(vendorName != NULL);
+
+ /***************************************************************************/
+ /* Allocate the Voice Quality. */
+ /***************************************************************************/
+ voiceQuality = malloc(sizeof(EVENT_VOICE_QUALITY));
+
+ if (voiceQuality == NULL)
+ {
+ log_error_state("Out of memory");
+ inError = true;
+ }
+
+ //Only in case of successful allocation initialize data.
+ if (inError == false) {
+ memset(voiceQuality, 0, sizeof(EVENT_VOICE_QUALITY));
+ EVEL_DEBUG("New Voice Quality is at %lp", voiceQuality);
+
+ /***************************************************************************/
+ /* Initialize the header & the fault fields. Optional integer values are */
+ /* initialized as 0. */
+ /***************************************************************************/
+ evel_init_header_nameid(&voiceQuality->header,ev_name,ev_id);
+ voiceQuality->header.event_domain = EVEL_DOMAIN_VOICE_QUALITY;
+ voiceQuality->major_version = EVEL_VOICEQ_MAJOR_VERSION;
+ voiceQuality->minor_version = EVEL_VOICEQ_MINOR_VERSION;
+
+ voiceQuality->calleeSideCodec = strdup(calleeSideCodec);
+ voiceQuality->callerSideCodec = strdup(callerSideCodec);
+ voiceQuality->correlator = strdup(correlator);
+ voiceQuality->midCallRtcp = strdup(midCallRtcp);
+ evel_init_vendor_field(&voiceQuality->vendorVnfNameFields, vendorName);
+ dlist_initialize(&voiceQuality->additionalInformation);
+ voiceQuality->endOfCallVqmSummaries = NULL;
+ evel_init_option_string(&voiceQuality->phoneNumber);
+ }
+
+ EVEL_EXIT();
+ return voiceQuality;
+
+}
+
+/**************************************************************************//**
+ * Add an additional value name/value pair to the Voice Quality.
+ *
+ * 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_voice_quality_addl_info_add(EVENT_VOICE_QUALITY * voiceQ, char * name, char * value) {
+ VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQ != NULL);
+ assert(voiceQ->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ EVEL_DEBUG("Adding name=%s value=%s", name, value);
+ addlInfo = malloc(sizeof(VOICE_QUALITY_ADDL_INFO));
+ assert(addlInfo != NULL);
+ memset(addlInfo, 0, sizeof(VOICE_QUALITY_ADDL_INFO));
+ addlInfo->name = strdup(name);
+ addlInfo->value = strdup(value);
+ assert(addlInfo->name != NULL);
+ assert(addlInfo->value != NULL);
+
+ dlist_push_last(&voiceQ->additionalInformation, addlInfo);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Callee side codec for Call for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param calleeCodecForCall The Callee Side Codec to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_callee_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const calleeCodecForCall) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(calleeCodecForCall != NULL);
+
+ voiceQuality->calleeSideCodec = strdup(calleeCodecForCall);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Caller side codec for Call for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param callerCodecForCall The Caller Side Codec to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_caller_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const callerCodecForCall) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(callerCodecForCall != NULL);
+
+ voiceQuality->calleeSideCodec = strdup(callerCodecForCall);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the correlator for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param correlator The correlator value to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_correlator_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const vCorrelator) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(vCorrelator != NULL);
+
+ voiceQuality->correlator = strdup(vCorrelator);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the RTCP Call Data for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param rtcpCallData The RTCP Call Data to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_rtcp_data_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const rtcpCallData) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(rtcpCallData != NULL);
+
+ voiceQuality->midCallRtcp = strdup(rtcpCallData);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Vendor VNF Name fields for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param modulename The Vendor, VNF and VfModule names to be set.
+ * ASCIIZ string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_vnfmodule_name_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const module_name) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(module_name != NULL);
+
+ evel_vendor_field_module_set(&voiceQuality->vendorVnfNameFields, module_name);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Vendor VNF Name fields for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param modulename The Vendor, VNF and VfModule names to be set.
+ * ASCIIZ string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_vnfname_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const vnfname) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(vnfname != NULL);
+
+ evel_vendor_field_vnfname_set(&voiceQuality->vendorVnfNameFields, vnfname);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the Phone Number associated with the Correlator for domain Voice Quality
+ *
+ * @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 voiceQuality Pointer to the Voice Quality Event.
+ * @param calleeCodecForCall The Phone Number to be set. ASCIIZ
+ * string. The caller does not need to
+ * preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_voice_quality_phone_number_set(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * const phoneNumber) {
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(phoneNumber != NULL);
+
+ evel_set_option_string(&voiceQuality->phoneNumber, phoneNumber, "Phone_Number");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add an End of Call Voice Quality Metrices
+
+ * The adjacencyName and endpointDescription is null delimited ASCII string.
+ * The library takes a copy so the caller does not have to preserve values
+ * after the function returns.
+ *
+ * @param voiceQuality Pointer to the measurement.
+ * @param adjacencyName Adjacency name
+ * @param endpointDescription Enumeration: ‘Caller’, ‘Callee’.
+ * @param endpointJitter Endpoint jitter
+ * @param endpointRtpOctetsDiscarded Endpoint RTP octets discarded.
+ * @param endpointRtpOctetsReceived Endpoint RTP octets received.
+ * @param endpointRtpOctetsSent Endpoint RTP octets sent
+ * @param endpointRtpPacketsDiscarded Endpoint RTP packets discarded.
+ * @param endpointRtpPacketsReceived Endpoint RTP packets received.
+ * @param endpointRtpPacketsSent Endpoint RTP packets sent.
+ * @param localJitter Local jitter.
+ * @param localRtpOctetsDiscarded Local RTP octets discarded.
+ * @param localRtpOctetsReceived Local RTP octets received.
+ * @param localRtpOctetsSent Local RTP octets sent.
+ * @param localRtpPacketsDiscarded Local RTP packets discarded.
+ * @param localRtpPacketsReceived Local RTP packets received.
+ * @param localRtpPacketsSent Local RTP packets sent.
+ * @param mosCqe Decimal range from 1 to 5
+ * (1 decimal place)
+ * @param packetsLost No Packets lost
+ * @param packetLossPercent Calculated percentage packet loss
+ * @param rFactor rFactor from 0 to 100
+ * @param roundTripDelay Round trip delay in milliseconds
+ *****************************************************************************/
+void evel_voice_quality_end_metrics_add(EVENT_VOICE_QUALITY * voiceQuality,
+ const char * adjacencyName, EVEL_SERVICE_ENDPOINT_DESC endpointDescription,
+ int endpointJitter,
+ int endpointRtpOctetsDiscarded,
+ int endpointRtpOctetsReceived,
+ int endpointRtpOctetsSent,
+ int endpointRtpPacketsDiscarded,
+ int endpointRtpPacketsReceived,
+ int endpointRtpPacketsSent,
+ int localJitter,
+ int localRtpOctetsDiscarded,
+ int localRtpOctetsReceived,
+ int localRtpOctetsSent,
+ int localRtpPacketsDiscarded,
+ int localRtpPacketsReceived,
+ int localRtpPacketsSent,
+ int mosCqe,
+ int packetsLost,
+ int packetLossPercent,
+ int rFactor,
+ int roundTripDelay) {
+
+ END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+ assert(adjacencyName != NULL);
+ assert(endpointDescription >= 0);
+ assert(mosCqe >= 1 && mosCqe <= 5);
+ assert(rFactor >= 0 && rFactor <= 100);
+ assert(voiceQuality->endOfCallVqmSummaries == NULL);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding adjacencyName=%s endpointDescription=%d", adjacencyName, endpointDescription);
+ vQMetrices = malloc(sizeof(END_OF_CALL_VOICE_QUALITY_METRICS));
+ assert(vQMetrices != NULL);
+ memset(vQMetrices, 0, sizeof(END_OF_CALL_VOICE_QUALITY_METRICS));
+
+ vQMetrices->adjacencyName = strdup(adjacencyName);
+ vQMetrices->endpointDescription = evel_service_endpoint_desc(endpointDescription);
+
+ evel_set_option_int(&vQMetrices->endpointJitter, endpointJitter, "Endpoint jitter");
+ evel_set_option_int(&vQMetrices->endpointRtpOctetsDiscarded, endpointRtpOctetsDiscarded, "Endpoint RTP octets discarded");
+ evel_set_option_int(&vQMetrices->endpointRtpOctetsReceived, endpointRtpOctetsReceived, "Endpoint RTP octets received");
+ evel_set_option_int(&vQMetrices->endpointRtpOctetsSent, endpointRtpOctetsSent, "Endpoint RTP octets sent");
+ evel_set_option_int(&vQMetrices->endpointRtpPacketsDiscarded, endpointRtpPacketsDiscarded, "Endpoint RTP packets discarded");
+ evel_set_option_int(&vQMetrices->endpointRtpPacketsReceived, endpointRtpPacketsReceived, "Endpoint RTP packets received");
+ evel_set_option_int(&vQMetrices->endpointRtpPacketsSent, endpointRtpPacketsSent, "Endpoint RTP packets sent");
+ evel_set_option_int(&vQMetrices->localJitter, localJitter, "Local jitter");
+ evel_set_option_int(&vQMetrices->localRtpOctetsDiscarded, localRtpOctetsDiscarded, "Local RTP octets discarded");
+ evel_set_option_int(&vQMetrices->localRtpOctetsReceived, localRtpOctetsReceived, "Local RTP octets received");
+ evel_set_option_int(&vQMetrices->localRtpOctetsSent, localRtpOctetsSent, "Local RTP octets sent");
+ evel_set_option_int(&vQMetrices->localRtpPacketsDiscarded, localRtpPacketsDiscarded, "Local RTP packets discarded");
+ evel_set_option_int(&vQMetrices->localRtpPacketsReceived, localRtpPacketsReceived, "Local RTP packets received");
+ evel_set_option_int(&vQMetrices->localRtpPacketsSent, localRtpPacketsSent, "Local RTP packets sent");
+ evel_set_option_int(&vQMetrices->mosCqe, mosCqe, "Decimal range from 1 to 5 (1 decimal place)");
+ evel_set_option_int(&vQMetrices->packetsLost, packetsLost, "Packets lost");
+ evel_set_option_int(&vQMetrices->packetLossPercent, packetLossPercent, "Calculated percentage packet loss");
+ evel_set_option_int(&vQMetrices->rFactor, rFactor, "rFactor ");
+ evel_set_option_int(&vQMetrices->roundTripDelay, roundTripDelay, "Round trip delay in milliseconds ");
+
+ voiceQuality->endOfCallVqmSummaries = vQMetrices;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode the Voce Quality in JSON according to AT&T's schema for the voice
+ * quality 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_voice_quality(EVEL_JSON_BUFFER * jbuf,
+ EVENT_VOICE_QUALITY * event)
+{
+ VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
+ DLIST_ITEM * addlInfoItem = NULL;
+
+ END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrics = NULL;
+ DLIST_ITEM * vQMetricsItem = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+ assert(event->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+
+ evel_json_encode_header(jbuf, &event->header);
+ evel_json_open_named_object(jbuf, "voiceQualityFields");
+
+ /***************************************************************************/
+ /* Mandatory fields. */
+ /***************************************************************************/
+ evel_enc_kv_string(jbuf, "calleeSideCodec", event->calleeSideCodec);
+ evel_enc_kv_string(jbuf, "callerSideCodec", event->callerSideCodec);
+ evel_enc_kv_string(jbuf, "correlator", event->correlator);
+ evel_enc_kv_string(jbuf, "midCallRtcp", event->midCallRtcp);
+ evel_json_encode_vendor_field(jbuf, &event->vendorVnfNameFields);
+ evel_enc_version(
+ jbuf, "voiceQualityFieldsVersion", event->major_version, event->minor_version);
+
+ /***************************************************************************/
+ /* Optional fields. */
+ /***************************************************************************/
+ evel_enc_kv_opt_string(jbuf, "phoneNumber", &event->phoneNumber);
+ /***************************************************************************/
+ /* Checkpoint, so that we can wind back if all fields are suppressed. */
+ /***************************************************************************/
+ //additionalInformation for Voice Quality
+ bool item_added = false;
+
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "additionalInformation"))
+ {
+
+ addlInfoItem = dlist_get_first(&event->additionalInformation);
+ while (addlInfoItem != NULL)
+ {
+ addlInfo = (VOICE_QUALITY_ADDL_INFO*)addlInfoItem->item;
+ assert(addlInfo != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "additionalInformation",
+ addlInfo->name))
+ {
+ evel_json_open_object(jbuf);
+ evel_enc_kv_string(jbuf, "name", addlInfo->name);
+ evel_enc_kv_string(jbuf, "value", addlInfo->value);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ addlInfoItem = dlist_get_next(addlInfoItem);
+ }
+ 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);
+ }
+ }
+
+ //endOfCallVqmSummaries
+ if( event->endOfCallVqmSummaries != NULL )
+ {
+ evel_json_open_named_object(jbuf, "endOfCallVqmSummaries");
+ vQMetrics = event->endOfCallVqmSummaries;
+ assert(vQMetrics != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "endOfCallVqmSummaries", vQMetrics->adjacencyName))
+ {
+ evel_enc_kv_string(jbuf, "adjacencyName", vQMetrics->adjacencyName);
+ evel_enc_kv_string(jbuf, "endpointDescription", vQMetrics->endpointDescription);
+ evel_enc_kv_opt_int(jbuf, "endpointJitter", &vQMetrics->endpointJitter);
+ evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsDiscarded", &vQMetrics->endpointRtpOctetsDiscarded);
+ evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsReceived", &vQMetrics->endpointRtpOctetsReceived);
+ evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsSent", &vQMetrics->endpointRtpOctetsSent);
+ evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsDiscarded", &vQMetrics->endpointRtpPacketsDiscarded);
+ evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsReceived", &vQMetrics->endpointRtpPacketsReceived);
+ evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsSent", &vQMetrics->endpointRtpPacketsSent);
+ evel_enc_kv_opt_int(jbuf, "localJitter", &vQMetrics->localJitter);
+ evel_enc_kv_opt_int(jbuf, "localRtpOctetsDiscarded", &vQMetrics->localRtpOctetsDiscarded);
+ evel_enc_kv_opt_int(jbuf, "localRtpOctetsReceived", &vQMetrics->localRtpOctetsReceived);
+ evel_enc_kv_opt_int(jbuf, "localRtpOctetsSent", &vQMetrics->localRtpOctetsSent);
+ evel_enc_kv_opt_int(jbuf, "localRtpPacketsDiscarded", &vQMetrics->localRtpPacketsDiscarded);
+ evel_enc_kv_opt_int(jbuf, "localRtpPacketsReceived", &vQMetrics->localRtpPacketsReceived);
+ evel_enc_kv_opt_int(jbuf, "localRtpPacketsSent", &vQMetrics->localRtpPacketsSent);
+ evel_enc_kv_opt_int(jbuf, "mosCqe", &vQMetrics->mosCqe);
+ evel_enc_kv_opt_int(jbuf, "packetsLost", &vQMetrics->packetsLost);
+ evel_enc_kv_opt_int(jbuf, "packetLossPercent", &vQMetrics->packetLossPercent);
+ evel_enc_kv_opt_int(jbuf, "rFactor", &vQMetrics->rFactor);
+ evel_enc_kv_opt_int(jbuf, "roundTripDelay", &vQMetrics->roundTripDelay);
+
+ }
+
+ evel_json_close_object(jbuf);
+ }
+
+ evel_json_close_object(jbuf);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Free a Voice Quality.
+ *
+ * Free off the Voce Quality supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Voice Quality itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_voice_quality(EVENT_VOICE_QUALITY * voiceQuality) {
+ END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL;
+ VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. As an internal API we don't allow freeing NULL */
+ /* events as we do on the public API. */
+ /***************************************************************************/
+ assert(voiceQuality != NULL);
+ assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
+
+ /***************************************************************************/
+ /* Free all internal strings then the header itself. */
+ /***************************************************************************/
+
+ //Additional Information
+ addlInfo = dlist_pop_last(&voiceQuality->additionalInformation);
+ while (addlInfo != NULL)
+ {
+ EVEL_DEBUG("Freeing Additional Info (%s, %s)",
+ addlInfo->name,
+ addlInfo->value);
+ free(addlInfo->name);
+ free(addlInfo->value);
+ free(addlInfo);
+ addlInfo = dlist_pop_last(&voiceQuality->additionalInformation);
+ }
+
+ //Summary Information
+ if(voiceQuality->endOfCallVqmSummaries != NULL)
+ {
+ vQMetrices = voiceQuality->endOfCallVqmSummaries;
+ EVEL_DEBUG("Freeing End of Call Voice Measurements Info (%s, %s)",
+ vQMetrices->adjacencyName,
+ vQMetrices->endpointDescription);
+ free(vQMetrices->adjacencyName);
+ free(vQMetrices);
+ }
+
+ //Members
+ free(voiceQuality->calleeSideCodec);
+ free(voiceQuality->callerSideCodec);
+ free(voiceQuality->correlator);
+ free(voiceQuality->midCallRtcp);
+ evel_free_option_string(&voiceQuality->phoneNumber);
+ evel_free_event_vendor_field(&voiceQuality->vendorVnfNameFields);
+
+ //header
+ evel_free_header(&voiceQuality->header);
+
+ EVEL_EXIT();
+}
+
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c
new file mode 100644
index 0000000..0e2f764
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c
@@ -0,0 +1,222 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * A simple Hashtable.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ ****************************************************************************/
+
+#include <limits.h>
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "hashtable.h"
+
+/**************************************************************************//**
+ * Hashtable initialization.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param size Size of hashtable
+
+ * @returns Hashtable pointer
+******************************************************************************/
+/* Create a new hashtable. */
+HASHTABLE_T *ht_create( size_t size ) {
+
+ HASHTABLE_T *hashtable = NULL;
+ size_t i;
+
+ if( size < 1 ) return NULL;
+
+ /* Allocate the table itself. */
+ if( ( hashtable = malloc( sizeof( HASHTABLE_T ) ) ) == NULL ) {
+ return NULL;
+ }
+
+ /* Allocate pointers to the head nodes. */
+ if( ( hashtable->table = malloc( sizeof( ENTRY_T * ) * size ) ) == NULL ) {
+ return NULL;
+ }
+ for( i = 0; i < size; i++ ) {
+ hashtable->table[i] = NULL;
+ }
+
+ hashtable->size = size;
+
+ return hashtable;
+}
+
+/**************************************************************************//**
+ * Hash a string for a particular hash table.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param hashtable Pointer to the hashtable
+ * @param key String
+
+ * @returns hashvalue
+******************************************************************************/
+size_t ht_hash( HASHTABLE_T *hashtable, char *key )
+{
+
+ size_t hash, i;
+
+#ifdef HASHTABLE_USE_SIMPLE_HASH
+ for ( hash = i = 0; i < strlen(key); hash = hash << 8, hash += key[ i++ ] );
+#else /* Use: Jenkins' "One At a Time Hash" === Perl "Like" Hashing */
+ // http://en.wikipedia.org/wiki/Jenkins_hash_function
+ for ( hash = i = 0; i < strlen(key); ++i ) {
+ hash += key[i], hash += ( hash << 10 ), hash ^= ( hash >> 6 );
+ }
+ hash += ( hash << 3 ), hash ^= ( hash >> 11 ), hash += ( hash << 15 );
+#endif
+
+ return hash % hashtable->size;
+
+}
+
+/**************************************************************************//**
+ * Create a key-value pair.
+ *
+ * @param key key string
+ * @param value value string
+ *
+ * @returns hashtable entry
+******************************************************************************/
+ENTRY_T *ht_newpair( char *key, void *value )
+{
+ ENTRY_T *newpair;
+
+ if( ( newpair = malloc( sizeof( ENTRY_T ) ) ) == NULL ) {
+ return NULL;
+ }
+
+ if( ( newpair->key = strdup( key ) ) == NULL ) {
+ return NULL;
+ }
+
+ if( ( newpair->value = value ) == NULL ) {
+ return NULL;
+ }
+
+ newpair->next = NULL;
+
+ return newpair;
+}
+
+/**************************************************************************//**
+ * Insert a key-value pair into a hash table.
+ *
+ * @param key key string
+ * @param value value string
+ *
+ * @returns Nothing
+******************************************************************************/
+void ht_set( HASHTABLE_T *hashtable, char *key, void *value ) {
+ size_t bin = 0;
+ ENTRY_T *newpair = NULL;
+ ENTRY_T *next = NULL;
+ ENTRY_T *last = NULL;
+
+ bin = ht_hash( hashtable, key );
+
+ next = hashtable->table[ bin ];
+
+ while( next != NULL && next->key != NULL && strcmp( key, next->key ) > 0 ) {
+ last = next;
+ next = next->next;
+ }
+
+ /* There's already a pair. Let's replace that string. */
+ if( next != NULL && next->key != NULL && strcmp( key, next->key ) == 0 ) {
+
+ free( next->value );
+ next->value = value ;
+
+ /* Nope, could't find it. Time to grow a pair. */
+ } else {
+ newpair = ht_newpair( key, value );
+
+ /* We're at the start of the linked list in this bin. */
+ if( next == hashtable->table[ bin ] ) {
+ newpair->next = next;
+ hashtable->table[ bin ] = newpair;
+
+ /* We're at the end of the linked list in this bin. */
+ } else if ( next == NULL ) {
+ last->next = newpair;
+
+ /* We're in the middle of the list. */
+ } else {
+ newpair->next = next;
+ last->next = newpair;
+ }
+ }
+}
+
+/**************************************************************************//**
+ * Retrieve a key-value pair from a hash table.
+ *
+ * @param key key string
+ *
+ * @returns value string
+******************************************************************************/
+void *ht_get( HASHTABLE_T *hashtable, char *key ) {
+ size_t bin = 0;
+ ENTRY_T *pair;
+
+ bin = ht_hash( hashtable, key );
+
+ /* Step through the bin, looking for our value. */
+ pair = hashtable->table[ bin ];
+ while( pair != NULL && pair->key != NULL && strcmp( key, pair->key ) > 0 ) {
+ pair = pair->next;
+ }
+
+ /* Did we actually find anything? */
+ if( pair == NULL || pair->key == NULL || strcmp( key, pair->key ) != 0 ) {
+ return NULL;
+
+ } else {
+ return pair->value;
+ }
+
+}
+
+/*
+int main( int argc, char **argv ) {
+
+ HASHTABLE_T *hashtable = ht_create( 65536 );
+
+ ht_set( hashtable, "key1", "inky" );
+ ht_set( hashtable, "key2", "pinky" );
+ ht_set( hashtable, "key3", "blinky" );
+ ht_set( hashtable, "key4", "floyd" );
+
+ printf( "%s\n", ht_get( hashtable, "key1" ) );
+ printf( "%s\n", ht_get( hashtable, "key2" ) );
+ printf( "%s\n", ht_get( hashtable, "key3" ) );
+ printf( "%s\n", ht_get( hashtable, "key4" ) );
+
+ return 0;
+}
+*/
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h
new file mode 100644
index 0000000..8be17dc
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h
@@ -0,0 +1,97 @@
+#ifndef HASHTABLE_INCLUDED
+#define HASHTABLE_INCLUDED
+
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * A simple hashtable.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+*****************************************************************************/
+
+typedef struct entry_s {
+ char *key;
+ void *value;
+ struct entry_s *next;
+} ENTRY_T;
+
+/**************************************************************************//**
+ * Hashtable structure
+ *****************************************************************************/
+
+typedef struct hashtable_s {
+ size_t size;
+ struct entry_s **table;
+} HASHTABLE_T;
+
+/**************************************************************************//**
+ * Hashtable initialization.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param size Size of hashtable
+
+ * @returns Hashtable pointer
+******************************************************************************/
+/* Create a new hashtable. */
+HASHTABLE_T *ht_create( size_t size );
+
+/**************************************************************************//**
+ * Hash a string for a particular hash table.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param hashtable Pointer to the hashtable
+ * @param key String
+
+ * @returns hashvalue
+******************************************************************************/
+size_t ht_hash( HASHTABLE_T *hashtable, char *key );
+
+/**************************************************************************//**
+ * Create a key-value pair.
+ *
+ * @param key key string
+ * @param value value string
+ *
+ * @returns hashtable entry
+******************************************************************************/
+ENTRY_T *ht_newpair( char *key, void *value );
+
+/**************************************************************************//**
+ * Insert a key-value pair into a hash table.
+ *
+ * @param key key string
+ * @param value value string
+ *
+ * @returns Nothing
+******************************************************************************/
+void ht_set( HASHTABLE_T *hashtable, char *key, void *value );
+
+/**************************************************************************//**
+ * Retrieve a key-value pair from a hash table.
+ *
+ * @param key key string
+ *
+ * @returns value string
+******************************************************************************/
+void *ht_get( HASHTABLE_T *hashtable, char *key );
+
+#endif
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c
new file mode 100644
index 0000000..f374a57
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c
@@ -0,0 +1,328 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h
new file mode 100644
index 0000000..4ae6d9b
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h
@@ -0,0 +1,93 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md
new file mode 100644
index 0000000..95e459a
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md
@@ -0,0 +1,81 @@
+# 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 © 2017 AT&T Intellectual Property. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+## 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.
+
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c
new file mode 100644
index 0000000..11fef1b
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c
@@ -0,0 +1,592 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ ****************************************************************************/
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h
new file mode 100644
index 0000000..1ee4409
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h
@@ -0,0 +1,58 @@
+#ifndef METADATA_INCLUDED
+#define METADATA_INCLUDED
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ *
+ ****************************************************************************/
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md
new file mode 100644
index 0000000..1c735cc
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md
new file mode 100644
index 0000000..3cf5708
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c
new file mode 100644
index 0000000..8080e02
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c
@@ -0,0 +1,192 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * A ring buffer with multi-threaded synchronization.
+ *
+ ****************************************************************************/
+
+#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/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h
new file mode 100644
index 0000000..1236b78
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h
@@ -0,0 +1,96 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#ifndef RING_BUFFER_INCLUDED
+#define RING_BUFFER_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * Ring buffer to handle message requests.
+ *
+ ****************************************************************************/
+
+#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
diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c
new file mode 100644
index 0000000..f52dc27
--- /dev/null
+++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c
@@ -0,0 +1,3484 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Unit tests for JSON encoding and throttling.
+ *
+ * This software is intended to show the essential elements of the library's
+ * use.
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#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"
+
+typedef enum {
+ SERVICE_NONE,
+ SERVICE_CODEC,
+ SERVICE_TRANSCODING,
+ SERVICE_RTCP,
+ SERVICE_EOC_VQM,
+ SERVICE_MARKER
+} SERVICE_TEST;
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void test_encode_heartbeat();
+static void test_encode_header_overrides();
+static void test_encode_fault();
+static void test_encode_fault_with_escaping();
+static void test_encode_measurement();
+static void test_encode_mobile_mand();
+static void test_encode_mobile_opts();
+static void test_encode_other();
+static void test_encode_report();
+static void test_encode_service();
+static void test_encode_service_subset(const SERVICE_TEST service_test);
+static void test_encode_signaling();
+static void test_encode_state_change();
+static void test_encode_syslog();
+static void test_json_response_junk();
+static void test_json_provide_throttle_state();
+static void test_json_measurement_interval();
+static void test_json_throttle_spec_field();
+static void test_json_throttle_spec_nv_pair();
+static void test_json_throttle_spec_two_domains();
+static void test_json_throttle_spec_bad_command_type();
+static void test_encode_fault_throttled();
+static void test_encode_measurement_throttled();
+static void test_encode_mobile_throttled();
+static void test_encode_other_throttled();
+static void test_encode_report_throttled();
+static void test_encode_service_throttled();
+static void test_encode_signaling_throttled();
+static void test_encode_state_change_throttled();
+static void test_encode_syslog_throttled();
+static void compare_strings(char * expected,
+ char * actual,
+ int max_size,
+ char * description);
+
+/**************************************************************************//**
+ * Main function.
+ *
+ * Runs all unit test cases, and fails hard on the first failure.
+ *
+ * @param[in] argc Argument count.
+ * @param[in] argv Argument vector - for usage see usage_text.
+ *****************************************************************************/
+int main(int argc, char ** argv)
+{
+ assert(argc >= 0);
+ assert(argv != NULL);
+
+ /***************************************************************************/
+ /* Fix our timezone to UTC. */
+ /***************************************************************************/
+ putenv("TZ=UTC");
+
+ /***************************************************************************/
+ /* Initialize metadata. */
+ /***************************************************************************/
+ openstack_metadata_initialize();
+
+ /***************************************************************************/
+ /* Minimal initialisation to exercise the encoders. */
+ /***************************************************************************/
+ functional_role = "UNIT TEST";
+ log_initialize(EVEL_LOG_DEBUG, "EVEL");
+
+ /***************************************************************************/
+ /* Test each encoder. */
+ /***************************************************************************/
+ test_encode_heartbeat();
+ test_encode_header_overrides();
+ test_encode_fault();
+ test_encode_measurement();
+ test_encode_mobile_mand();
+ test_encode_mobile_opts();
+ test_encode_other();
+ test_encode_report();
+ test_encode_service();
+ test_encode_signaling();
+ test_encode_state_change();
+ test_encode_syslog();
+
+ /***************************************************************************/
+ /* Test JSON Throttle. */
+ /***************************************************************************/
+ test_json_response_junk();
+ test_json_provide_throttle_state();
+ test_json_measurement_interval();
+ test_json_throttle_spec_field();
+ test_json_throttle_spec_nv_pair();
+ test_json_throttle_spec_two_domains();
+ test_json_throttle_spec_bad_command_type();
+
+ /***************************************************************************/
+ /* Test each encoder with throttling applied. */
+ /***************************************************************************/
+ test_encode_fault_throttled();
+ test_encode_measurement_throttled();
+ test_encode_mobile_throttled();
+ test_encode_other_throttled();
+ test_encode_report_throttled();
+ test_encode_service_throttled();
+ test_encode_signaling_throttled();
+ test_encode_state_change_throttled();
+ test_encode_syslog_throttled();
+
+ /***************************************************************************/
+ /* Test character escaping. */
+ /***************************************************************************/
+ test_encode_fault_with_escaping();
+
+ printf ("\nAll Tests Passed\n");
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* We link with this gettimeofday so that we get a fixed result */
+/*****************************************************************************/
+int gettimeofday(struct timeval *tv,
+ struct timezone *tz __attribute__((unused)))
+{
+ tv->tv_sec = 1;
+ tv->tv_usec = 2;
+ return 0;
+}
+
+void test_encode_heartbeat()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"heartbeat\", "
+ "\"eventId\": \"121\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 121, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Autonomous heartbeat\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+
+ /***************************************************************************/
+ /* Test the VM name/uuid once. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(121);
+
+ EVENT_HEADER * heartbeat = evel_new_heartbeat();
+ assert(heartbeat != NULL);
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) heartbeat);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Heartbeat");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(heartbeat);
+}
+
+void test_encode_header_overrides()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"heartbeat\", "
+ "\"eventId\": \"121\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"entity_name_override\", "
+ "\"sequence\": 121, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1001, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Autonomous heartbeat\", "
+ "\"reportingEntityId\": \"entity_id_override\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+
+ /***************************************************************************/
+ /* Test the VM name/uuid once. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(121);
+
+ EVENT_HEADER * heartbeat = evel_new_heartbeat();
+ assert(heartbeat != NULL);
+
+ evel_start_epoch_set(heartbeat, 1001);
+ evel_last_epoch_set(heartbeat, 1000);
+ evel_reporting_entity_name_set(heartbeat, "entity_name_override");
+ evel_reporting_entity_id_set(heartbeat, "entity_id_override");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) heartbeat);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Heartbeat");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(heartbeat);
+}
+
+void test_encode_fault()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"fault\", "
+ "\"eventId\": \"122\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 122, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Bad things happen...\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"faultFields\": {"
+ "\"alarmCondition\": \"My alarm condition\", "
+ "\"eventSeverity\": \"MAJOR\", "
+ "\"eventSourceType\": \"other\", "
+ "\"specificProblem\": \"It broke very badly\", "
+ "\"eventCategory\": \"link\", "
+ "\"vfStatus\": \"Active\", "
+ "\"faultFieldsVersion\": 1.1, "
+ "\"alarmAdditionalInformation\": ["
+ "{\"name\": \"name1\", "
+ "\"value\": \"value1\"}, "
+ "{\"name\": \"name2\", "
+ "\"value\": \"value2\"}], "
+ "\"alarmInterfaceA\": \"My Interface Card\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(122);
+ EVENT_FAULT * fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_HOST,
+ EVEL_VF_STATUS_PREP_TERMINATE);
+ assert(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");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(fault);
+}
+
+void test_encode_measurement()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfScaling\", "
+ "\"eventId\": \"123\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 3000, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"entity_name\", "
+ "\"sequence\": 123, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 2000, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Perf management...\", "
+ "\"reportingEntityId\": \"entity_id\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"measurementsForVfScalingFields\": "
+ "{"
+ "\"measurementInterval\": 5.500000, "
+ "\"concurrentSessions\": 1, "
+ "\"configuredEntities\": 2, "
+ "\"cpuUsageArray\": ["
+ "{\"cpuIdentifier\": \"cpu1\", "
+ "\"percentUsage\": 11.110000}, "
+ "{\"cpuIdentifier\": \"cpu2\", "
+ "\"percentUsage\": 22.220000}], "
+ "\"filesystemUsageArray\": ["
+ "{\"blockConfigured\": 100.110000, "
+ "\"blockIops\": 33, "
+ "\"blockUsed\": 100.220000, "
+ "\"ephemeralConfigured\": 100.110000, "
+ "\"ephemeralIops\": 44, "
+ "\"ephemeralUsed\": 200.220000, "
+ "\"filesystemName\": \"00-11-22\"}, "
+ "{\"blockConfigured\": 300.110000, "
+ "\"blockIops\": 55, "
+ "\"blockUsed\": 300.220000, "
+ "\"ephemeralConfigured\": 300.110000, "
+ "\"ephemeralIops\": 66, "
+ "\"ephemeralUsed\": 400.220000, "
+ "\"filesystemName\": \"33-44-55\"}], "
+ "\"latencyDistribution\": ["
+ "{\"countsInTheBucket\": 20}, "
+ "{\"lowEndOfLatencyBucket\": 10.000000, "
+ "\"highEndOfLatencyBucket\": 20.000000, "
+ "\"countsInTheBucket\": 30}], "
+ "\"meanRequestLatency\": 4.400000, "
+ "\"memoryConfigured\": 6.600000, "
+ "\"memoryUsed\": 3.300000, "
+ "\"requestRate\": 7, "
+ "\"vNicUsageArray\": ["
+ "{"
+ "\"bytesIn\": 3, "
+ "\"bytesOut\": 4, "
+ "\"packetsIn\": 100, "
+ "\"packetsOut\": 200, "
+ "\"vNicIdentifier\": \"eth0\""
+ "}, "
+ "{"
+ "\"bytesIn\": 13, "
+ "\"bytesOut\": 14, "
+ "\"packetsIn\": 110, "
+ "\"packetsOut\": 240, "
+ "\"vNicIdentifier\": \"eth1\", "
+ "\"broadcastPacketsIn\": 11, "
+ "\"broadcastPacketsOut\": 12, "
+ "\"multicastPacketsIn\": 15, "
+ "\"multicastPacketsOut\": 16, "
+ "\"unicastPacketsIn\": 17, "
+ "\"unicastPacketsOut\": 18"
+ "}"
+ "], "
+ "\"aggregateCpuUsage\": 8.800000, "
+ "\"numberOfMediaPortsInUse\": 1234, "
+ "\"vnfcScalingMetric\": 1234.567800, "
+ "\"errors\": {"
+ "\"receiveDiscards\": 1, "
+ "\"receiveErrors\": 0, "
+ "\"transmitDiscards\": 2, "
+ "\"transmitErrors\": 1}, "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}, "
+ "{\"featureIdentifier\": \"FeatureB\", "
+ "\"featureUtilization\": 567}], "
+ "\"codecUsageArray\": ["
+ "{\"codecIdentifier\": \"G711a\", "
+ "\"numberInUse\": 91}, "
+ "{\"codecIdentifier\": \"G729ab\", "
+ "\"numberInUse\": 92}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}, "
+ "{\"name\": \"Group2\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}]}], "
+ "\"measurementsForVfScalingVersion\": 1.1}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_MEASUREMENT * measurement = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL;
+ MEASUREMENT_CPU_USE *cpu_use;
+
+ /***************************************************************************/
+ /* Measurement. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(123);
+ measurement = evel_new_measurement(5.5);
+ assert(measurement != NULL);
+ evel_measurement_type_set(measurement, "Perf management...");
+ evel_measurement_conc_sess_set(measurement, 1);
+ evel_measurement_cfg_ents_set(measurement, 2);
+ evel_measurement_mean_req_lat_set(measurement, 4.4);
+ evel_measurement_request_rate_set(measurement, 7);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", 11.11);
+ evel_measurement_cpu_use_idle_set(cpu_use,22.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,99.99);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu2", 22.22);
+ evel_measurement_cpu_use_idle_set(cpu_use,12.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,19.99);
+
+
+ evel_measurement_fsys_use_add(measurement,"00-11-22",100.11, 100.22, 33,
+ 200.11, 200.22, 44);
+ evel_measurement_fsys_use_add(measurement,"33-44-55",300.11, 300.22, 55,
+ 400.11, 400.22, 66);
+ evel_start_epoch_set(&measurement->header, 2000);
+ evel_last_epoch_set(&measurement->header, 3000);
+ evel_reporting_entity_name_set(&measurement->header, "entity_name");
+ evel_reporting_entity_id_set(&measurement->header, "entity_id");
+
+ /***************************************************************************/
+ /* Latency Bucket with no optional parameters. */
+ /***************************************************************************/
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ /***************************************************************************/
+ /* Latency Bucket with all optional parameters. */
+ /***************************************************************************/
+ bucket = evel_new_meas_latency_bucket(30);
+ evel_meas_latency_bucket_low_end_set(bucket, 10.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 20.0);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ /***************************************************************************/
+ /* vNIC Use with no optional parameters. */
+ /***************************************************************************/
+ vnic_use = evel_new_measurement_vnic_use("eth0", 100, 200, 3, 4);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ /***************************************************************************/
+ /* vNIC Use with all optional parameters. */
+ /***************************************************************************/
+ vnic_use = evel_new_measurement_vnic_use("eth1", 110, 240, 13, 14);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, 11);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, 12);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, 15);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, 16);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, 17);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, 18);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ evel_measurement_errors_set(measurement, 1, 0, 2, 1);
+
+ evel_measurement_feature_use_add(measurement, "FeatureA", 123);
+ evel_measurement_feature_use_add(measurement, "FeatureB", 567);
+
+ evel_measurement_codec_use_add(measurement, "G711a", 91);
+ evel_measurement_codec_use_add(measurement, "G729ab", 92);
+
+ evel_measurement_media_port_use_set(measurement, 1234);
+
+ evel_measurement_vnfc_scaling_metric_set(measurement, 1234.5678);
+
+ evel_measurement_custom_measurement_add(measurement,
+ "Group1", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) measurement);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Measurement");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(measurement);
+}
+
+void test_encode_mobile_mand()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"mobileFlow\", "
+ "\"eventId\": \"1241\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 1241, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"mobileFlowFields\": {"
+ "\"flowDirection\": \"Outbound\", "
+ "\"gtpPerFlowMetrics\": {"
+ "\"avgBitErrorRate\": 12.300000, "
+ "\"avgPacketDelayVariation\": 3.120000, "
+ "\"avgPacketLatency\": 100, "
+ "\"avgReceiveThroughput\": 2100, "
+ "\"avgTransmitThroughput\": 500, "
+ "\"flowActivationEpoch\": 1470409421, "
+ "\"flowActivationMicrosec\": 987, "
+ "\"flowDeactivationEpoch\": 1470409431, "
+ "\"flowDeactivationMicrosec\": 11, "
+ "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:51 +0000\", "
+ "\"flowStatus\": \"Working\", "
+ "\"maxPacketDelayVariation\": 87, "
+ "\"numActivationFailures\": 3, "
+ "\"numBitErrors\": 17, "
+ "\"numBytesReceived\": 123654, "
+ "\"numBytesTransmitted\": 4561, "
+ "\"numDroppedPackets\": 0, "
+ "\"numL7BytesReceived\": 12, "
+ "\"numL7BytesTransmitted\": 10, "
+ "\"numLostPackets\": 1, "
+ "\"numOutOfOrderPackets\": 3, "
+ "\"numPacketErrors\": 7, "
+ "\"numPacketsReceivedExclRetrans\": 899, "
+ "\"numPacketsReceivedInclRetrans\": 901, "
+ "\"numPacketsTransmittedInclRetrans\": 302, "
+ "\"numRetries\": 6, "
+ "\"numTimeouts\": 2, "
+ "\"numTunneledL7BytesReceived\": 0, "
+ "\"roundTripTime\": 110, "
+ "\"timeToFirstByte\": 225"
+ "}, "
+ "\"ipProtocolType\": \"TCP\", "
+ "\"ipVersion\": \"IPv4\", "
+ "\"otherEndpointIpAddress\": \"2.3.4.1\", "
+ "\"otherEndpointPort\": 2341, "
+ "\"reportingEndpointIpAddr\": \"4.2.3.1\", "
+ "\"reportingEndpointPort\": 4321"
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+
+ /***************************************************************************/
+ /* Mobile. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(1241);
+
+ metrics = evel_new_mobile_gtp_flow_metrics(12.3,
+ 3.12,
+ 100,
+ 2100,
+ 500,
+ 1470409421,
+ 987,
+ 1470409431,
+ 11,
+ (time_t)1470409431,
+ "Working",
+ 87,
+ 3,
+ 17,
+ 123654,
+ 4561,
+ 0,
+ 12,
+ 10,
+ 1,
+ 3,
+ 7,
+ 899,
+ 901,
+ 302,
+ 6,
+ 2,
+ 0,
+ 110,
+ 225);
+ assert(metrics != NULL);
+ mobile_flow = evel_new_mobile_flow("Outbound",
+ metrics,
+ "TCP",
+ "IPv4",
+ "2.3.4.1",
+ 2341,
+ "4.2.3.1",
+ 4321);
+ assert(mobile_flow != NULL);
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(mobile_flow);
+}
+
+void test_encode_mobile_opts()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"mobileFlow\", "
+ "\"eventId\": \"1242\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 1242, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Mobile flow...\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"mobileFlowFields\": {"
+ "\"flowDirection\": \"Inbound\", "
+ "\"gtpPerFlowMetrics\": {"
+ "\"avgBitErrorRate\": 132.000100, "
+ "\"avgPacketDelayVariation\": 31.200000, "
+ "\"avgPacketLatency\": 101, "
+ "\"avgReceiveThroughput\": 2101, "
+ "\"avgTransmitThroughput\": 501, "
+ "\"flowActivationEpoch\": 1470409422, "
+ "\"flowActivationMicrosec\": 988, "
+ "\"flowDeactivationEpoch\": 1470409432, "
+ "\"flowDeactivationMicrosec\": 12, "
+ "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:52 +0000\", "
+ "\"flowStatus\": \"Inactive\", "
+ "\"maxPacketDelayVariation\": 88, "
+ "\"numActivationFailures\": 4, "
+ "\"numBitErrors\": 18, "
+ "\"numBytesReceived\": 123655, "
+ "\"numBytesTransmitted\": 4562, "
+ "\"numDroppedPackets\": 1, "
+ "\"numL7BytesReceived\": 13, "
+ "\"numL7BytesTransmitted\": 11, "
+ "\"numLostPackets\": 2, "
+ "\"numOutOfOrderPackets\": 4, "
+ "\"numPacketErrors\": 8, "
+ "\"numPacketsReceivedExclRetrans\": 900, "
+ "\"numPacketsReceivedInclRetrans\": 902, "
+ "\"numPacketsTransmittedInclRetrans\": 303, "
+ "\"numRetries\": 7, "
+ "\"numTimeouts\": 3, "
+ "\"numTunneledL7BytesReceived\": 1, "
+ "\"roundTripTime\": 111, "
+ "\"timeToFirstByte\": 226, "
+ "\"ipTosCountList\": ["
+ "[\"1\", 13], "
+ "[\"4\", 99], "
+ "[\"17\", 1]], "
+ "\"ipTosList\": [\"1\", \"4\", \"17\"], "
+ "\"tcpFlagList\": [\"CWR\", \"URG\"], "
+ "\"tcpFlagCountList\": [[\"CWR\", 10], [\"URG\", 121]], "
+ "\"mobileQciCosList\": [\"conversational\", \"65\"], "
+ "\"mobileQciCosCountList\": [[\"conversational\", 11], [\"65\", 122]], "
+ "\"durConnectionFailedStatus\": 12, "
+ "\"durTunnelFailedStatus\": 13, "
+ "\"flowActivatedBy\": \"Remote\", "
+ "\"flowActivationTime\": \"Fri, 05 Aug 2016 15:03:43 +0000\", "
+ "\"flowDeactivatedBy\": \"Remote\", "
+ "\"gtpConnectionStatus\": \"Connected\", "
+ "\"gtpTunnelStatus\": \"Not tunneling\", "
+ "\"largePacketRtt\": 80, "
+ "\"largePacketThreshold\": 600.000000, "
+ "\"maxReceiveBitRate\": 1357924680, "
+ "\"maxTransmitBitRate\": 235711, "
+ "\"numGtpEchoFailures\": 1, "
+ "\"numGtpTunnelErrors\": 4, "
+ "\"numHttpErrors\": 2"
+ "}, "
+ "\"ipProtocolType\": \"UDP\", "
+ "\"ipVersion\": \"IPv6\", "
+ "\"otherEndpointIpAddress\": \"2.3.4.2\", "
+ "\"otherEndpointPort\": 2342, "
+ "\"reportingEndpointIpAddr\": \"4.2.3.2\", "
+ "\"reportingEndpointPort\": 4322, "
+ "\"applicationType\": \"Demo application\", "
+ "\"appProtocolType\": \"GSM\", "
+ "\"appProtocolVersion\": \"1\", "
+ "\"cid\": \"65535\", "
+ "\"connectionType\": \"S1-U\", "
+ "\"ecgi\": \"e65535\", "
+ "\"gtpProtocolType\": \"GTP-U\", "
+ "\"gtpVersion\": \"1\", "
+ "\"httpHeader\": \"http://www.something.com\", "
+ "\"imei\": \"209917614823\", "
+ "\"imsi\": \"355251/05/850925/8\", "
+ "\"lac\": \"1\", "
+ "\"mcc\": \"410\", "
+ "\"mnc\": \"04\", "
+ "\"msisdn\": \"6017123456789\", "
+ "\"otherFunctionalRole\": \"MME\", "
+ "\"rac\": \"514\", "
+ "\"radioAccessTechnology\": \"LTE\", "
+ "\"sac\": \"1\", "
+ "\"samplingAlgorithm\": 1, "
+ "\"tac\": \"2099\", "
+ "\"tunnelId\": \"Tunnel 1\", "
+ "\"vlanId\": \"15\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+
+ /***************************************************************************/
+ /* Mobile. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(1242);
+
+ metrics = evel_new_mobile_gtp_flow_metrics(132.0001,
+ 31.2,
+ 101,
+ 2101,
+ 501,
+ 1470409422,
+ 988,
+ 1470409432,
+ 12,
+ (time_t)1470409432,
+ "Inactive",
+ 88,
+ 4,
+ 18,
+ 123655,
+ 4562,
+ 1,
+ 13,
+ 11,
+ 2,
+ 4,
+ 8,
+ 900,
+ 902,
+ 303,
+ 7,
+ 3,
+ 1,
+ 111,
+ 226);
+ assert(metrics != NULL);
+
+ evel_mobile_gtp_metrics_dur_con_fail_set(metrics, 12);
+ evel_mobile_gtp_metrics_dur_tun_fail_set(metrics, 13);
+ evel_mobile_gtp_metrics_act_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_act_time_set(metrics, (time_t)1470409423);
+ evel_mobile_gtp_metrics_deact_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_con_status_set(metrics, "Connected");
+ evel_mobile_gtp_metrics_tun_status_set(metrics, "Not tunneling");
+ evel_mobile_gtp_metrics_iptos_set(metrics, 1, 13);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 17, 1);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 4, 99);
+ evel_mobile_gtp_metrics_large_pkt_rtt_set(metrics, 80);
+ evel_mobile_gtp_metrics_large_pkt_thresh_set(metrics, 600.0);
+ evel_mobile_gtp_metrics_max_rcv_bit_rate_set(metrics, 1357924680);
+ evel_mobile_gtp_metrics_max_trx_bit_rate_set(metrics, 235711);
+ evel_mobile_gtp_metrics_num_echo_fail_set(metrics, 1);
+ evel_mobile_gtp_metrics_num_tun_fail_set(metrics, 4);
+ evel_mobile_gtp_metrics_num_http_errors_set(metrics, 2);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_CWR, 10);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_URG, 121);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_UMTS_CONVERSATIONAL, 11);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_LTE_65, 122);
+
+ mobile_flow = evel_new_mobile_flow("Inbound",
+ metrics,
+ "UDP",
+ "IPv6",
+ "2.3.4.2",
+ 2342,
+ "4.2.3.2",
+ 4322);
+ assert(mobile_flow != NULL);
+
+ evel_mobile_flow_type_set(mobile_flow, "Mobile flow...");
+ evel_mobile_flow_app_type_set(mobile_flow, "Demo application");
+ evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM");
+ evel_mobile_flow_app_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_cid_set(mobile_flow, "65535");
+ evel_mobile_flow_con_type_set(mobile_flow, "S1-U");
+ evel_mobile_flow_ecgi_set(mobile_flow, "e65535");
+ evel_mobile_flow_gtp_prot_type_set(mobile_flow, "GTP-U");
+ evel_mobile_flow_gtp_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_http_header_set(mobile_flow,
+ "http://www.something.com");
+ evel_mobile_flow_imei_set(mobile_flow, "209917614823");
+ evel_mobile_flow_imsi_set(mobile_flow, "355251/05/850925/8");
+ evel_mobile_flow_lac_set(mobile_flow, "1");
+ evel_mobile_flow_mcc_set(mobile_flow, "410");
+ evel_mobile_flow_mnc_set(mobile_flow, "04");
+ evel_mobile_flow_msisdn_set(mobile_flow, "6017123456789");
+ evel_mobile_flow_other_func_role_set(mobile_flow, "MME");
+ evel_mobile_flow_rac_set(mobile_flow, "514");
+ evel_mobile_flow_radio_acc_tech_set(mobile_flow, "LTE");
+ evel_mobile_flow_sac_set(mobile_flow, "1");
+ evel_mobile_flow_samp_alg_set(mobile_flow, 1);
+ evel_mobile_flow_tac_set(mobile_flow, "2099");
+ evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 1");
+ evel_mobile_flow_vlan_id_set(mobile_flow, "15");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(mobile_flow);
+}
+
+void test_encode_report()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfReporting\", "
+ "\"eventId\": \"125\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 125, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Perf reporting...\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"measurementsForVfReportingFields\": "
+ "{\"measurementInterval\": 1.100000, "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}, "
+ "{\"featureIdentifier\": \"FeatureB\", "
+ "\"featureUtilization\": 567}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}, "
+ "{\"name\": \"Group2\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}]}], "
+ "\"measurementFieldsVersion\": 1.1}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_REPORT * report = NULL;
+
+ /***************************************************************************/
+ /* Report. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(125);
+ report = evel_new_report(1.1);
+ assert(report != NULL);
+ evel_report_type_set(report, "Perf reporting...");
+ evel_report_feature_use_add(report, "FeatureA", 123);
+ evel_report_feature_use_add(report, "FeatureB", 567);
+ evel_report_custom_measurement_add(report, "Group1", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) report);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Report");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(report);
+}
+
+void test_encode_service()
+{
+ test_encode_service_subset(SERVICE_NONE);
+ test_encode_service_subset(SERVICE_CODEC);
+ test_encode_service_subset(SERVICE_TRANSCODING);
+ test_encode_service_subset(SERVICE_RTCP);
+ test_encode_service_subset(SERVICE_EOC_VQM);
+ test_encode_service_subset(SERVICE_MARKER);
+}
+
+void test_encode_service_subset(const SERVICE_TEST service_test)
+{
+ char * expected_start =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"serviceEvents\", "
+ "\"eventId\": \"2000\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2000, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Service Event\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"serviceEventsFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"serviceEventsFieldsVersion\": 1.1, "
+ "\"correlator\": \"vendor_x_correlator\", "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name1\", \"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", \"value\": \"Value2\"}, "
+ "{\"name\": \"Name3\", \"value\": \"Value3\"}, "
+ "{\"name\": \"Name4\", \"value\": \"Value4\"}]";
+ char * expected_codec =
+ ", "
+ "\"codecSelected\": {"
+ "\"codec\": \"PCMA\""
+ "}";
+ char * expected_transcoding =
+ ", "
+ "\"codecSelectedTranscoding\": {"
+ "\"calleeSideCodec\": \"PCMA\", "
+ "\"callerSideCodec\": \"G729A\""
+ "}";
+ char * expected_rtcp =
+ ", "
+ "\"midCallRtcp\": {"
+ "\"rtcpData\": \"some_rtcp_data\""
+ "}";
+ char * expected_eoc_vqm =
+ ", "
+ "\"endOfCallVqmSummaries\": {"
+ "\"adjacencyName\": \"vendor_x_adjacency\", "
+ "\"endpointDescription\": \"Caller\", "
+ "\"endpointJitter\": 66, "
+ "\"endpointRtpOctetsDiscarded\": 100, "
+ "\"endpointRtpOctetsReceived\": 200, "
+ "\"endpointRtpOctetsSent\": 300, "
+ "\"endpointRtpPacketsDiscarded\": 400, "
+ "\"endpointRtpPacketsReceived\": 500, "
+ "\"endpointRtpPacketsSent\": 600, "
+ "\"localJitter\": 99, "
+ "\"localRtpOctetsDiscarded\": 150, "
+ "\"localRtpOctetsReceived\": 250, "
+ "\"localRtpOctetsSent\": 350, "
+ "\"localRtpPacketsDiscarded\": 450, "
+ "\"localRtpPacketsReceived\": 550, "
+ "\"localRtpPacketsSent\": 650, "
+ "\"mosCqe\": 12.255000, "
+ "\"packetsLost\": 157, "
+ "\"packetLossPercent\": 0.232000, "
+ "\"rFactor\": 11, "
+ "\"roundTripDelay\": 15"
+ "}";
+ char * expected_marker =
+ ", "
+ "\"marker\": {"
+ "\"phoneNumber\": \"0888888888\""
+ "}";
+ char * expected_end =
+ "}}}";
+
+ char * expected_middle = NULL;
+ switch (service_test)
+ {
+ case SERVICE_NONE:
+ expected_middle = "";
+ break;
+ case SERVICE_CODEC:
+ expected_middle = expected_codec;
+ break;
+ case SERVICE_TRANSCODING:
+ expected_middle = expected_transcoding;
+ break;
+ case SERVICE_RTCP:
+ expected_middle = expected_rtcp;
+ break;
+ case SERVICE_EOC_VQM:
+ expected_middle = expected_eoc_vqm;
+ break;
+ case SERVICE_MARKER:
+ expected_middle = expected_marker;
+ break;
+ }
+ assert(expected_middle != NULL);
+
+ int offset = 0;
+ char expected[EVEL_MAX_JSON_BODY];
+ offset = snprintf(expected + offset,
+ EVEL_MAX_JSON_BODY - offset,
+ "%s%s%s",
+ expected_start,
+ expected_middle,
+ expected_end);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SGNALING * event = NULL;
+ evel_set_next_event_sequence(2000);
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ assert(event != NULL);
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+
+ switch (service_test)
+ {
+ case SERVICE_NONE:
+ break;
+ case SERVICE_CODEC:
+ evel_signaling_addl_info_add(event, "codec", "PCMA");
+ break;
+ case SERVICE_TRANSCODING:
+ evel_signaling_addl_info_add(event, "calleecodec", "PCMA");
+ evel_signaling_addl_info_add(event, "callercodec", "G729A");
+ break;
+ case SERVICE_RTCP:
+ evel_signaling_addl_info_add(event, "rtcpdata", "abcdefgh");
+ break;
+ case SERVICE_EOC_VQM:
+ evel_signaling_addl_info_add(event, "adjacency", "vendor_x");
+ /*evel_service_adjacency_name_set(event, "vendor_x_adjacency");
+ evel_service_endpoint_desc_set(event, EVEL_SERVICE_ENDPOINT_CALLER);
+ evel_service_endpoint_jitter_set(event, 66);
+ evel_service_endpoint_rtp_oct_disc_set(event, 100);
+ evel_service_endpoint_rtp_oct_recv_set(event, 200);
+ evel_service_endpoint_rtp_oct_sent_set(event, 300);
+ evel_service_endpoint_rtp_pkt_disc_set(event, 400);
+ evel_service_endpoint_rtp_pkt_recv_set(event, 500);
+ evel_service_endpoint_rtp_pkt_sent_set(event, 600);
+ evel_service_local_jitter_set(event, 99);
+ evel_service_local_rtp_oct_disc_set(event, 150);
+ evel_service_local_rtp_oct_recv_set(event, 250);
+ evel_service_local_rtp_oct_sent_set(event, 350);
+ evel_service_local_rtp_pkt_disc_set(event, 450);
+ evel_service_local_rtp_pkt_recv_set(event, 550);
+ evel_service_local_rtp_pkt_sent_set(event, 650);
+ evel_service_mos_cqe_set(event, 12.255);
+ evel_service_packets_lost_set(event, 157);
+ evel_service_packet_loss_percent_set(event, 0.232);
+ evel_service_r_factor_set(event, 11);
+ evel_service_round_trip_delay_set(event, 15);*/
+ break;
+ case SERVICE_MARKER:
+ evel_signaling_addl_info_add(event, "service_phone", "0888888888");
+ break;
+ }
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Service");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+}
+
+void test_encode_signaling()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"signaling\", "
+ "\"eventId\": \"2001\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2001, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Signaling\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"signalingFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"signalingFieldsVersion\": 1.1, "
+ "\"correlator\": \"vendor_x_correlator\", "
+ "\"localIpAddress\": \"1.0.3.1\", "
+ "\"localPort\": \"1031\", "
+ "\"remoteIpAddress\": \"5.3.3.0\", "
+ "\"remotePort\": \"5330\", "
+ "\"compressedSip\": \"compressed_sip\", "
+ "\"summarySip\": \"summary_sip\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SIGNALING * event = NULL;
+ evel_set_next_event_sequence(2001);
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ assert(event != NULL);
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_product_id_set(event, "vendor_x_product_id");
+ evel_signaling_subsystem_id_set(event, "vendor_x_subsystem_id");
+ evel_signaling_friendly_name_set(event, "vendor_x_frieldly_name");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_local_ip_address_set(event, "1.0.3.1");
+ evel_signaling_local_port_set(event, "1031");
+ evel_signaling_remote_ip_address_set(event, "5.3.3.0");
+ evel_signaling_remote_port_set(event, "5330");
+ evel_signaling_compressed_sip_set(event, "compressed_sip");
+ evel_signaling_summary_sip_set(event, "summary_sip");
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Signaling");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+}
+
+void test_encode_state_change()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"stateChange\", "
+ "\"eventId\": \"128\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 128, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"SC Type\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"stateChangeFields\": {"
+ "\"newState\": \"inService\", "
+ "\"oldState\": \"outOfService\", "
+ "\"stateInterface\": \"An Interface\", "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}"
+ "], "
+ "\"stateChangeFieldsVersion\": 1.1"
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_STATE_CHANGE * state_change = NULL;
+ evel_set_next_event_sequence(128);
+ state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ "An Interface");
+ assert(state_change != NULL);
+ evel_state_change_type_set(state_change, "SC Type");
+ evel_state_change_addl_field_add(state_change, "Name1", "Value1");
+ evel_state_change_addl_field_add(state_change, "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) state_change);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "StateChange");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(state_change);
+}
+
+void test_encode_syslog()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"syslog\", "
+ "\"eventId\": \"126\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 126, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"SL Type\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"syslogFields\": {"
+ "\"eventSourceType\": \"virtualNetworkFunction\", "
+ "\"syslogMsg\": \"SL Message\", "
+ "\"syslogTag\": \"SL Tag\", "
+ "\"syslogFieldsVersion\": 1.1, "
+ "\"eventSourceHost\": \"SL Host\", "
+ "\"syslogFacility\": 6, "
+ "\"syslogProc\": \"SL Proc\", "
+ "\"syslogProcId\": 2, "
+ "\"syslogSData\": \"SL SDATA\", "
+ "\"syslogVer\": 1"
+ "}}}";
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SYSLOG * syslog = NULL;
+ evel_set_next_event_sequence(126);
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION,
+ "SL Message",
+ "SL Tag");
+ assert(syslog != NULL);
+ evel_syslog_type_set(syslog, "SL Type");
+ evel_syslog_event_source_host_set(syslog, "SL Host");
+ evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LINE_PRINTER);
+ evel_syslog_proc_set(syslog, "SL Proc");
+ evel_syslog_proc_id_set(syslog, 2);
+ evel_syslog_version_set(syslog, 1);
+ evel_syslog_s_data_set(syslog, "SL SDATA");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) syslog);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Syslog");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(syslog);
+}
+
+void test_encode_other()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"other\", "
+ "\"eventId\": \"129\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 129, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Other Type\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"otherFields\": ["
+ "{\"name\": \"Other field 1\", "
+ "\"value\": \"Other value 1\"}, "
+ "{\"name\": \"Other field 2\", "
+ "\"value\": \"Other value 2\"}"
+ "]"
+ "}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_OTHER * other = NULL;
+ evel_set_next_event_sequence(129);
+ other = evel_new_other();
+ assert(other != NULL);
+ evel_other_type_set(other, "Other Type");
+ evel_other_field_add(other,
+ "Other field 1",
+ "Other value 1");
+ evel_other_field_add(other,
+ "Other field 2",
+ "Other value 2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) other);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Other");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(other);
+}
+
+void compare_strings(char * expected,
+ char * actual,
+ int max_size,
+ char * description)
+{
+ if (strncmp(expected, actual, max_size) != 0)
+ {
+ int diff = 0;
+ while (diff < max_size)
+ {
+ if (expected[diff] != actual[diff])
+ {
+ break;
+ }
+ diff++;
+ }
+
+ printf("Comparison Failure at Offset %d\n\n", diff);
+ printf("Expected:\n%s\n", expected);
+ printf("Actual:\n%s\n", actual);
+ printf("Description: %s\n", description);
+ assert(0);
+ }
+}
+
+/**************************************************************************//**
+ * Copy a json string to a ::MEMORY_CHUNK for testing.
+ *
+ * @param chunk The memory chunk.
+ * @param string The json string.
+ *****************************************************************************/
+void copy_string_to_chunk(MEMORY_CHUNK * chunk, char * string)
+{
+ int mem_size;
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(string != NULL);
+
+ mem_size = strlen(string) + 1;
+ chunk->memory = malloc(mem_size);
+ memcpy(chunk->memory, string, mem_size);
+ chunk->size = mem_size;
+}
+
+/**************************************************************************//**
+ * Copy a json string to a ::MEMORY_CHUNK for testing.
+ *
+ * @param json The JSON string.
+ * @param post Memory chunk to post a response.
+ *****************************************************************************/
+void handle_json_response(char * json, MEMORY_CHUNK * post)
+{
+ MEMORY_CHUNK chunk;
+ post->memory = NULL;
+ post->size = 0;
+ copy_string_to_chunk(&chunk, json);
+ evel_handle_event_response(&chunk, post);
+ free(chunk.memory);
+}
+
+/**************************************************************************//**
+ * Test that a non-"commandList" JSON buffer leaves the throttle state off.
+ *****************************************************************************/
+void test_json_response_junk()
+{
+ MEMORY_CHUNK post;
+ int domain;
+ char * json_junk =
+ "{"
+ "\"junk1\": ["
+ "\"1\", \"2\", \"3\"], "
+ "\"junk2\": ["
+ "\"1\", \"2\", \"3\"]"
+ "}";
+
+ evel_throttle_initialize();
+ handle_json_response(json_junk, &post);
+
+ /***************************************************************************/
+ /* Check that all domains are not throttled. */
+ /***************************************************************************/
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ /***************************************************************************/
+ /* Check that we generated no post. */
+ /***************************************************************************/
+ assert(post.memory == NULL);
+
+ evel_throttle_terminate();
+}
+
+char * json_command_list_provide =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"provideThrottlingState\""
+ "}"
+ "}"
+ "]"
+ "}";
+
+char * json_command_list_fault_clear =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\""
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+char * json_command_list_syslog_clear =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"syslog\""
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+char * expected_throttle_state_normal =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"normal\"}"
+ "}";
+
+/**************************************************************************//**
+ * Test that we can return the default throttling state.
+ *****************************************************************************/
+void test_json_provide_throttle_state()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * expected_post = expected_throttle_state_normal;
+
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_provide, &post);
+
+ /***************************************************************************/
+ /* Check that all domains are not throttled. */
+ /***************************************************************************/
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ /***************************************************************************/
+ /* Check that we generated a throttling specification post. */
+ /***************************************************************************/
+ assert(post.memory != NULL);
+ compare_strings(expected_post, post.memory, strlen(expected_post),
+ "Throttle State Normal");
+ free(post.memory);
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test the measurement interval handling and API.
+ *****************************************************************************/
+void test_json_measurement_interval()
+{
+ MEMORY_CHUNK post;
+ char * json_command_list_interval_only =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"measurementInterval\": 60"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_interval_first =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"measurementInterval\": 30, "
+ "\"commandType\": \"measurementIntervalChange\""
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_command_first =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"measurementIntervalChange\", "
+ "\"measurementInterval\": 60"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ evel_throttle_initialize();
+ assert(evel_get_measurement_interval() == EVEL_MEASUREMENT_INTERVAL_UKNOWN);
+
+ /***************************************************************************/
+ /* Check that we're not handling stuff when we shouldn't. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_interval_only, &post);
+ assert(post.memory == NULL);
+ assert(evel_get_measurement_interval() == EVEL_MEASUREMENT_INTERVAL_UKNOWN);
+
+ /***************************************************************************/
+ /* Check that we're OK with the interval coming first. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_interval_first, &post);
+ assert(post.memory == NULL);
+ assert(evel_get_measurement_interval() == 30);
+
+ /***************************************************************************/
+ /* Check that we're OK with the command type coming first. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_command_first, &post);
+ assert(post.memory == NULL);
+ assert(evel_get_measurement_interval() == 60);
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test a single domain, single field suppression.
+ *****************************************************************************/
+void test_json_throttle_spec_field()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * json_command_list_fault_single =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_fault_double =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": ["
+ "\"alarmInterfaceA\", \"alarmAdditionalInformation\"]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * expected_post_fault_single =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_post_fault_double =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": ["
+ "\"alarmInterfaceA\", \"alarmAdditionalInformation\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_fault_single, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_single,
+ post.memory,
+ strlen(expected_post_fault_single),
+ "Fault - Single Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Update a specification with two faults suppressed. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_double, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_double,
+ post.memory,
+ strlen(expected_post_fault_double),
+ "Fault - Double Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Now clear the FAULT domain. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_clear, &post);
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test a single domain, nv_pair suppression.
+ *****************************************************************************/
+void test_json_throttle_spec_nv_pair()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * json_command_list_fault_pair_single =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}"
+ "]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_fault_pair_double =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\", \"name2\"]"
+ "}"
+ "]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * expected_post_fault_pair_single =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}"
+ "]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_post_fault_pair_double =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\", \"name2\"]"
+ "}"
+ "]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single nvpair with a */
+ /* single sub-field suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_fault_pair_single, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_pair_single,
+ post.memory,
+ strlen(expected_post_fault_pair_single),
+ "Fault - Single Pair, Single Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Update a specification with a single nvpair with two sub-fields */
+ /* suppressed. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_pair_double, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_pair_double,
+ post.memory,
+ strlen(expected_post_fault_pair_double),
+ "Fault - Double Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Now clear the FAULT domain. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_clear, &post);
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test two domains, nv_pair suppression.
+ *****************************************************************************/
+void test_json_throttle_spec_two_domains()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * json_command_list_two_domains =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}, "
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"syslog\", "
+ "\"suppressedFieldNames\": [\"syslogProcId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * expected_post_two_domains =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}, "
+ "{"
+ "\"eventDomain\": \"syslog\", "
+ "\"suppressedFieldNames\": [\"syslogProcId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}"
+ "]"
+ "}"
+ "}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single nvpair with a */
+ /* single sub-field suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_two_domains, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT and SYSLOG domains are throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if ((domain != EVEL_DOMAIN_FAULT) && (domain != EVEL_DOMAIN_SYSLOG))
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_two_domains,
+ post.memory,
+ strlen(expected_post_two_domains),
+ "Fault - Two Domains");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Now clear the FAULT and SYSLOG domains. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_clear, &post);
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) == NULL);
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL);
+ handle_json_response(json_command_list_syslog_clear, &post);
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test bad command type.
+ *****************************************************************************/
+void test_json_throttle_spec_bad_command_type()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ /***************************************************************************/
+ /* Search for "dodgy" in the JSON, and you will see the dodgy bits we're */
+ /* handling in these tests. */
+ /***************************************************************************/
+ #define NUM_BAD_COMMANDS 8
+ char * json_command_list_dodgy_command =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"dodgyCommand\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_spec =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"dodgyEventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_event_domain_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"dodgyEventDomainKey\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_event_domain =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"dodgyEventDomain\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_field_names_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_pair_names_list_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"dodgySuppressedNvPairsListKey\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_pair_field_name_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"dodgyNvPairFieldNameKey\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_pair_names_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"dodgySuppressedNvPairNamesKey\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_depth =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"dodgySuppressedNvPairNamesKey\": "
+ "[\"name1\", [[[[[[[[]]]]]]]]]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * expected_throttle_state_dodgy_field_names_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_throttle_state_dodgy_pair_names_list_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_throttle_state_dodgy_pair_field_name_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_throttle_state_dodgy_pair_names_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * json_command_lists[] = {
+ json_command_list_dodgy_command,
+ json_command_list_dodgy_spec,
+ json_command_list_dodgy_event_domain_key,
+ json_command_list_dodgy_event_domain,
+ json_command_list_dodgy_depth,
+ json_command_list_dodgy_field_names_key,
+ json_command_list_dodgy_pair_names_list_key,
+ json_command_list_dodgy_pair_field_name_key,
+ json_command_list_dodgy_pair_names_key
+ };
+
+ char * expected_posts[] = {
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_dodgy_field_names_key,
+ expected_throttle_state_dodgy_pair_names_list_key,
+ expected_throttle_state_dodgy_pair_field_name_key,
+ expected_throttle_state_dodgy_pair_names_key
+ };
+
+ const int num_commands =
+ sizeof(json_command_lists) / sizeof(json_command_lists[0]);
+ const int num_posts =
+ sizeof(expected_posts) / sizeof(expected_posts[0]);
+ assert(num_commands == num_posts);
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single nvpair with a */
+ /* single sub-field suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+
+ int ii;
+ for (ii = 0; ii < num_commands; ii++)
+ {
+ EVEL_DEBUG("Testing commandList[%d] = %s\n", ii, json_command_lists[ii]);
+ handle_json_response(json_command_lists[ii], &post);
+
+ /*************************************************************************/
+ /* Check that throttling is in a normal state - because we ignored the */
+ /* command / ..... */
+ /*************************************************************************/
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ if (expected_posts[ii] == expected_throttle_state_normal)
+ {
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) == NULL);
+ }
+ else
+ {
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ }
+ assert(post.memory == NULL);
+
+ /*************************************************************************/
+ /* Request and verify the throttling state. */
+ /*************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_posts[ii],
+ post.memory,
+ strlen(expected_posts[ii]),
+ "Throttle State Normal");
+ free(post.memory);
+ post.memory = NULL;
+ }
+
+ evel_throttle_terminate();
+}
+
+void test_encode_fault_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": ["
+ "\"alarmInterfaceA\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name3\", \"name4\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"fault\", "
+ "\"eventId\": \"122\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 122, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"faultFields\": {"
+ "\"alarmCondition\": \"My alarm condition\", "
+ "\"eventSeverity\": \"MAJOR\", "
+ "\"eventSourceType\": \"other\", "
+ "\"specificProblem\": \"It broke very badly\", "
+ "\"vfStatus\": \"Active\", "
+ "\"faultFieldsVersion\": 1.1, "
+ "\"alarmAdditionalInformation\": ["
+ "{\"name\": \"name1\", "
+ "\"value\": \"value1\"}, "
+ "{\"name\": \"name2\", "
+ "\"value\": \"value2\"}]"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(122);
+ EVENT_FAULT * fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_HOST,
+ EVEL_VF_STATUS_PREP_TERMINATE);
+ assert(fault != NULL);
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+
+ /***************************************************************************/
+ /* Suppressed fields. */
+ /***************************************************************************/
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name3", "value3");
+ evel_fault_addl_info_add(fault, "name4", "value4");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(fault);
+ evel_throttle_terminate();
+}
+
+void test_encode_measurement_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"measurementsForVfScaling\", "
+ "\"suppressedFieldNames\": ["
+ "\"errors\", "
+ "\"vnfcScalingMetric\", "
+ "\"numberOfMediaPortsInUse\", "
+ "\"aggregateCpuUsage\", "
+ "\"requestRate\", "
+ "\"memoryUsed\", "
+ "\"memoryConfigured\", "
+ "\"meanRequestLatency\", "
+ "\"latencyDistribution\", "
+ "\"concurrentSessions\", "
+ "\"configuredEntities\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"cpuUsageArray\", "
+ "\"suppressedNvPairNames\": [\"cpu3\", \"cpu4\"]"
+ "}, "
+ "{"
+ "\"nvPairFieldName\": \"filesystemUsageArray\", "
+ "\"suppressedNvPairNames\": [\"00-11-22\", \"33-44-55\"]"
+ "}, "
+ "{"
+ "\"nvPairFieldName\": \"vNicUsageArray\", "
+ "\"suppressedNvPairNames\": [\"eth1\", \"eth0\"]"
+ "}, "
+ "{"
+ "\"nvPairFieldName\": \"featureUsageArray\", "
+ "\"suppressedNvPairNames\": [\"FeatureB\", \"FeatureC\"]"
+ "},"
+ "{"
+ "\"nvPairFieldName\": \"codecUsageArray\", "
+ "\"suppressedNvPairNames\": [\"G729ab\"]"
+ "},"
+ "{"
+ "\"nvPairFieldName\": \"additionalMeasurements\", "
+ "\"suppressedNvPairNames\": [\"Group2\"]"
+ "}"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfScaling\", "
+ "\"eventId\": \"123\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 123, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"measurementsForVfScalingFields\": "
+ "{"
+ "\"measurementInterval\": 5.500000, "
+ "\"cpuUsageArray\": ["
+ "{\"cpuIdentifier\": \"cpu1\", "
+ "\"percentUsage\": 11.110000}, "
+ "{\"cpuIdentifier\": \"cpu2\", "
+ "\"percentUsage\": 22.220000}], "
+ "\"filesystemUsageArray\": ["
+ "{\"blockConfigured\": 500.110000, "
+ "\"blockIops\": 77, "
+ "\"blockUsed\": 500.220000, "
+ "\"ephemeralConfigured\": 500.110000, "
+ "\"ephemeralIops\": 88, "
+ "\"ephemeralUsed\": 600.220000, "
+ "\"filesystemName\": \"66-77-88\"}], "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}], "
+ "\"codecUsageArray\": ["
+ "{\"codecIdentifier\": \"G711a\", "
+ "\"numberInUse\": 91}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}], "
+ "\"measurementsForVfScalingVersion\": 1.1}}}";
+ MEASUREMENT_CPU_USE *cpu_use;
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_MEASUREMENT) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(123);
+ EVENT_MEASUREMENT * measurement = evel_new_measurement(5.5);
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL;
+ assert(measurement != NULL);
+
+ evel_measurement_type_set(measurement, "Perf management...");
+ evel_measurement_conc_sess_set(measurement, 1);
+ evel_measurement_cfg_ents_set(measurement, 2);
+ evel_measurement_mean_req_lat_set(measurement, 4.4);
+ evel_measurement_mem_cfg_set(measurement, 6.6);
+ evel_measurement_mem_used_set(measurement, 3.3);
+ evel_measurement_request_rate_set(measurement, 7);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", 11.11);
+ evel_measurement_cpu_use_idle_set(cpu_use,22.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,99.99);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu2", 22.22);
+ evel_measurement_cpu_use_idle_set(cpu_use,12.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,19.99);
+
+ evel_measurement_fsys_use_add(measurement, "00-11-22",
+ 100.11, 100.22, 33,
+ 200.11, 200.22, 44);
+ evel_measurement_fsys_use_add(measurement, "33-44-55",
+ 300.11, 300.22, 55,
+ 400.11, 400.22, 66);
+ evel_measurement_fsys_use_add(measurement, "66-77-88",
+ 500.11, 500.22, 77,
+ 600.11, 600.22, 88);
+
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ bucket = evel_new_meas_latency_bucket(30);
+ evel_meas_latency_bucket_low_end_set(bucket, 10.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 20.0);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ vnic_use = evel_new_measurement_vnic_use("eth0", 100, 200, 3, 4);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, 1);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, 2);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, 5);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, 6);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, 7);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, 8);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ vnic_use = evel_new_measurement_vnic_use("eth1", 110, 240, 13, 14);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, 11);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, 12);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, 15);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, 16);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, 17);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, 18);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ evel_measurement_errors_set(measurement, 1, 0, 2, 1);
+ evel_measurement_feature_use_add(measurement, "FeatureA", 123);
+ evel_measurement_feature_use_add(measurement, "FeatureB", 567);
+ evel_measurement_codec_use_add(measurement, "G711a", 91);
+ evel_measurement_codec_use_add(measurement, "G729ab", 92);
+ evel_measurement_media_port_use_set(measurement, 1234);
+ evel_measurement_vnfc_scaling_metric_set(measurement, 1234.5678);
+ evel_measurement_custom_measurement_add(measurement,
+ "Group1", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) measurement);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Measurement");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(measurement);
+ evel_throttle_terminate();
+}
+
+void test_encode_mobile_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"mobileFlow\", "
+ "\"suppressedFieldNames\": ["
+ "\"applicationType\", "
+ "\"appProtocolType\", "
+ "\"appProtocolVersion\", "
+ "\"cid\", "
+ "\"connectionType\", "
+ "\"ecgi\", "
+ "\"gtpProtocolType\", "
+ "\"gtpVersion\", "
+ "\"httpHeader\", "
+ "\"imei\", "
+ "\"imsi\", "
+ "\"lac\", "
+ "\"mcc\", "
+ "\"mnc\", "
+ "\"msisdn\", "
+ "\"otherFunctionalRole\", "
+ "\"rac\", "
+ "\"radioAccessTechnology\", "
+ "\"sac\", "
+ "\"samplingAlgorithm\", "
+ "\"tac\", "
+ "\"tunnelId\", "
+ "\"vlanId\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"mobileFlow\", "
+ "\"eventId\": \"1242\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 1242, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"mobileFlowFields\": {"
+ "\"flowDirection\": \"Inbound\", "
+ "\"gtpPerFlowMetrics\": {"
+ "\"avgBitErrorRate\": 132.000100, "
+ "\"avgPacketDelayVariation\": 31.200000, "
+ "\"avgPacketLatency\": 101, "
+ "\"avgReceiveThroughput\": 2101, "
+ "\"avgTransmitThroughput\": 501, "
+ "\"flowActivationEpoch\": 1470409422, "
+ "\"flowActivationMicrosec\": 988, "
+ "\"flowDeactivationEpoch\": 1470409432, "
+ "\"flowDeactivationMicrosec\": 12, "
+ "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:52 +0000\", "
+ "\"flowStatus\": \"Inactive\", "
+ "\"maxPacketDelayVariation\": 88, "
+ "\"numActivationFailures\": 4, "
+ "\"numBitErrors\": 18, "
+ "\"numBytesReceived\": 123655, "
+ "\"numBytesTransmitted\": 4562, "
+ "\"numDroppedPackets\": 1, "
+ "\"numL7BytesReceived\": 13, "
+ "\"numL7BytesTransmitted\": 11, "
+ "\"numLostPackets\": 2, "
+ "\"numOutOfOrderPackets\": 4, "
+ "\"numPacketErrors\": 8, "
+ "\"numPacketsReceivedExclRetrans\": 900, "
+ "\"numPacketsReceivedInclRetrans\": 902, "
+ "\"numPacketsTransmittedInclRetrans\": 303, "
+ "\"numRetries\": 7, "
+ "\"numTimeouts\": 3, "
+ "\"numTunneledL7BytesReceived\": 1, "
+ "\"roundTripTime\": 111, "
+ "\"timeToFirstByte\": 226, "
+ "\"ipTosCountList\": ["
+ "[\"1\", 13], "
+ "[\"4\", 99], "
+ "[\"17\", 1]], "
+ "\"ipTosList\": [\"1\", \"4\", \"17\"], "
+ "\"tcpFlagList\": [\"CWR\", \"URG\"], "
+ "\"tcpFlagCountList\": [[\"CWR\", 10], [\"URG\", 121]], "
+ "\"mobileQciCosList\": [\"conversational\", \"65\"], "
+ "\"mobileQciCosCountList\": [[\"conversational\", 11], [\"65\", 122]], "
+ "\"durConnectionFailedStatus\": 12, "
+ "\"durTunnelFailedStatus\": 13, "
+ "\"flowActivatedBy\": \"Remote\", "
+ "\"flowActivationTime\": \"Fri, 05 Aug 2016 15:03:43 +0000\", "
+ "\"flowDeactivatedBy\": \"Remote\", "
+ "\"gtpConnectionStatus\": \"Connected\", "
+ "\"gtpTunnelStatus\": \"Not tunneling\", "
+ "\"largePacketRtt\": 80, "
+ "\"largePacketThreshold\": 600.000000, "
+ "\"maxReceiveBitRate\": 1357924680, "
+ "\"maxTransmitBitRate\": 235711, "
+ "\"numGtpEchoFailures\": 1, "
+ "\"numGtpTunnelErrors\": 4, "
+ "\"numHttpErrors\": 2"
+ "}, "
+ "\"ipProtocolType\": \"UDP\", "
+ "\"ipVersion\": \"IPv6\", "
+ "\"otherEndpointIpAddress\": \"2.3.4.2\", "
+ "\"otherEndpointPort\": 2342, "
+ "\"reportingEndpointIpAddr\": \"4.2.3.2\", "
+ "\"reportingEndpointPort\": 4322"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_MOBILE_FLOW) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+
+ /***************************************************************************/
+ /* Mobile. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(1242);
+
+ metrics = evel_new_mobile_gtp_flow_metrics(132.0001,
+ 31.2,
+ 101,
+ 2101,
+ 501,
+ 1470409422,
+ 988,
+ 1470409432,
+ 12,
+ (time_t)1470409432,
+ "Inactive",
+ 88,
+ 4,
+ 18,
+ 123655,
+ 4562,
+ 1,
+ 13,
+ 11,
+ 2,
+ 4,
+ 8,
+ 900,
+ 902,
+ 303,
+ 7,
+ 3,
+ 1,
+ 111,
+ 226);
+ assert(metrics != NULL);
+
+ evel_mobile_gtp_metrics_dur_con_fail_set(metrics, 12);
+ evel_mobile_gtp_metrics_dur_tun_fail_set(metrics, 13);
+ evel_mobile_gtp_metrics_act_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_act_time_set(metrics, (time_t)1470409423);
+ evel_mobile_gtp_metrics_deact_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_con_status_set(metrics, "Connected");
+ evel_mobile_gtp_metrics_tun_status_set(metrics, "Not tunneling");
+ evel_mobile_gtp_metrics_iptos_set(metrics, 1, 13);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 17, 1);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 4, 99);
+ evel_mobile_gtp_metrics_large_pkt_rtt_set(metrics, 80);
+ evel_mobile_gtp_metrics_large_pkt_thresh_set(metrics, 600.0);
+ evel_mobile_gtp_metrics_max_rcv_bit_rate_set(metrics, 1357924680);
+ evel_mobile_gtp_metrics_max_trx_bit_rate_set(metrics, 235711);
+ evel_mobile_gtp_metrics_num_echo_fail_set(metrics, 1);
+ evel_mobile_gtp_metrics_num_tun_fail_set(metrics, 4);
+ evel_mobile_gtp_metrics_num_http_errors_set(metrics, 2);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_CWR, 10);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_URG, 121);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_UMTS_CONVERSATIONAL, 11);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_LTE_65, 122);
+
+ mobile_flow = evel_new_mobile_flow("Inbound",
+ metrics,
+ "UDP",
+ "IPv6",
+ "2.3.4.2",
+ 2342,
+ "4.2.3.2",
+ 4322);
+ assert(mobile_flow != NULL);
+
+ evel_mobile_flow_type_set(mobile_flow, "Mobile flow...");
+ evel_mobile_flow_app_type_set(mobile_flow, "Demo application");
+ evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM");
+ evel_mobile_flow_app_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_cid_set(mobile_flow, "65535");
+ evel_mobile_flow_con_type_set(mobile_flow, "S1-U");
+ evel_mobile_flow_ecgi_set(mobile_flow, "e65535");
+ evel_mobile_flow_gtp_prot_type_set(mobile_flow, "GTP-U");
+ evel_mobile_flow_gtp_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_http_header_set(mobile_flow,
+ "http://www.something.com");
+ evel_mobile_flow_imei_set(mobile_flow, "209917614823");
+ evel_mobile_flow_imsi_set(mobile_flow, "355251/05/850925/8");
+ evel_mobile_flow_lac_set(mobile_flow, "1");
+ evel_mobile_flow_mcc_set(mobile_flow, "410");
+ evel_mobile_flow_mnc_set(mobile_flow, "04");
+ evel_mobile_flow_msisdn_set(mobile_flow, "6017123456789");
+ evel_mobile_flow_other_func_role_set(mobile_flow, "MME");
+ evel_mobile_flow_rac_set(mobile_flow, "514");
+ evel_mobile_flow_radio_acc_tech_set(mobile_flow, "LTE");
+ evel_mobile_flow_sac_set(mobile_flow, "1");
+ evel_mobile_flow_samp_alg_set(mobile_flow, 1);
+ evel_mobile_flow_tac_set(mobile_flow, "2099");
+ evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 1");
+ evel_mobile_flow_vlan_id_set(mobile_flow, "15");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(mobile_flow);
+ evel_throttle_terminate();
+}
+
+void test_encode_other_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"other\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"other\", "
+ "\"eventId\": \"129\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 129, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"otherFields\": ["
+ "{\"name\": \"Other field 1\", "
+ "\"value\": \"Other value 1\"}, "
+ "{\"name\": \"Other field 2\", "
+ "\"value\": \"Other value 2\"}"
+ "]"
+ "}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_OTHER) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_OTHER * other = NULL;
+ evel_set_next_event_sequence(129);
+ other = evel_new_other();
+ assert(other != NULL);
+ evel_other_type_set(other, "Other Type");
+ evel_other_field_add(other,
+ "Other field 1",
+ "Other value 1");
+ evel_other_field_add(other,
+ "Other field 2",
+ "Other value 2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) other);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Other");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(other);
+ evel_throttle_terminate();
+}
+
+void test_encode_report_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"report\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"featureUsageArray\", "
+ "\"suppressedNvPairNames\": [\"FeatureB\", \"FeatureC\"]"
+ "},"
+ "{"
+ "\"nvPairFieldName\": \"additionalMeasurements\", "
+ "\"suppressedNvPairNames\": [\"Group2\"]"
+ "}"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfReporting\", "
+ "\"eventId\": \"125\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 125, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"measurementsForVfReportingFields\": "
+ "{\"measurementInterval\": 1.100000, "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}], "
+ "\"measurementFieldsVersion\": 1.1}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_REPORT) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_REPORT * report = NULL;
+
+ /***************************************************************************/
+ /* Report. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(125);
+ report = evel_new_report(1.1);
+ assert(report != NULL);
+ evel_report_type_set(report, "Perf reporting...");
+ evel_report_feature_use_add(report, "FeatureA", 123);
+ evel_report_feature_use_add(report, "FeatureB", 567);
+ evel_report_custom_measurement_add(report, "Group1", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) report);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Report");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(report);
+ evel_throttle_terminate();
+}
+
+void test_encode_service_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"serviceEvents\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"correlator\", "
+ "\"codecSelected\", "
+ "\"codecSelectedTranscoding\", "
+ "\"endOfCallVqmSummaries\", "
+ "\"midCallRtcp\", "
+ "\"marker\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"Name1\", \"Name3\"]"
+ "}"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"serviceEvents\", "
+ "\"eventId\": \"2000\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2000, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"serviceEventsFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"serviceEventsFieldsVersion\": 1.1, "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name2\", \"value\": \"Value2\"}, "
+ "{\"name\": \"Name4\", \"value\": \"Value4\"}]"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SERVICE) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SERVICE * event = NULL;
+ evel_set_next_event_sequence(2000);
+ event = evel_new_service("vendor_x_id", "vendor_x_event_id");
+ assert(event != NULL);
+ evel_service_type_set(event, "Service Event");
+ evel_service_product_id_set(event, "vendor_x_product_id");
+ evel_service_subsystem_id_set(event, "vendor_x_subsystem_id");
+ evel_service_friendly_name_set(event, "vendor_x_frieldly_name");
+ evel_service_correlator_set(event, "vendor_x_correlator");
+ evel_service_codec_set(event, "PCMA");
+ evel_service_codec_set(event, "PCMA");
+ evel_service_callee_codec_set(event, "PCMA");
+ evel_service_caller_codec_set(event, "G729A");
+ evel_service_rtcp_data_set(event, "some_rtcp_data");
+ evel_service_adjacency_name_set(event, "vendor_x_adjacency");
+ evel_service_endpoint_desc_set(event, EVEL_SERVICE_ENDPOINT_CALLER);
+ evel_service_endpoint_jitter_set(event, 66);
+ evel_service_endpoint_rtp_oct_disc_set(event, 100);
+ evel_service_endpoint_rtp_oct_recv_set(event, 200);
+ evel_service_endpoint_rtp_oct_sent_set(event, 300);
+ evel_service_endpoint_rtp_pkt_disc_set(event, 400);
+ evel_service_endpoint_rtp_pkt_recv_set(event, 500);
+ evel_service_endpoint_rtp_pkt_sent_set(event, 600);
+ evel_service_local_jitter_set(event, 99);
+ evel_service_local_rtp_oct_disc_set(event, 150);
+ evel_service_local_rtp_oct_recv_set(event, 250);
+ evel_service_local_rtp_oct_sent_set(event, 350);
+ evel_service_local_rtp_pkt_disc_set(event, 450);
+ evel_service_local_rtp_pkt_recv_set(event, 550);
+ evel_service_local_rtp_pkt_sent_set(event, 650);
+ evel_service_mos_cqe_set(event, 12.255);
+ evel_service_packets_lost_set(event, 157);
+ evel_service_packet_loss_percent_set(event, 0.232);
+ evel_service_r_factor_set(event, 11);
+ evel_service_round_trip_delay_set(event, 15);
+ evel_service_phone_number_set(event, "0888888888");
+ evel_service_addl_field_add(event, "Name1", "Value1");
+ evel_service_addl_field_add(event, "Name2", "Value2");
+ evel_service_addl_field_add(event, "Name3", "Value3");
+ evel_service_addl_field_add(event, "Name4", "Value4");
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Service");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+ evel_throttle_terminate();
+}
+
+void test_encode_signaling_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"signaling\", "
+ "\"suppressedFieldNames\": ["
+ "\"correlator\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\", "
+ "\"localIpAddress\", "
+ "\"localPort\", "
+ "\"remoteIpAddress\", "
+ "\"remotePort\", "
+ "\"compressedSip\", "
+ "\"summarySip\"], "
+ "\"suppressedNvPairsList\": ["
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"signaling\", "
+ "\"eventId\": \"2001\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2001, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"signalingFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"signalingFieldsVersion\": 1.1"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SIGNALING) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SIGNALING * event = NULL;
+ evel_set_next_event_sequence(2001);
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ assert(event != NULL);
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_product_id_set(event, "vendor_x_product_id");
+ evel_signaling_subsystem_id_set(event, "vendor_x_subsystem_id");
+ evel_signaling_friendly_name_set(event, "vendor_x_frieldly_name");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_local_ip_address_set(event, "1.0.3.1");
+ evel_signaling_local_port_set(event, "1031");
+ evel_signaling_remote_ip_address_set(event, "5.3.3.0");
+ evel_signaling_remote_port_set(event, "5330");
+ evel_signaling_compressed_sip_set(event, "compressed_sip");
+ evel_signaling_summary_sip_set(event, "summary_sip");
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Signaling");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+ evel_throttle_terminate();
+}
+
+void test_encode_state_change_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"stateChange\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"Name1\"]"
+ "},"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"stateChange\", "
+ "\"eventId\": \"128\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 128, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"stateChangeFields\": {"
+ "\"newState\": \"inService\", "
+ "\"oldState\": \"outOfService\", "
+ "\"stateInterface\": \"An Interface\", "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}"
+ "], "
+ "\"stateChangeFieldsVersion\": 1.1"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_STATE_CHANGE) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_STATE_CHANGE * state_change = NULL;
+ evel_set_next_event_sequence(128);
+ state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ "An Interface");
+ assert(state_change != NULL);
+ evel_state_change_type_set(state_change, "SC Type");
+ evel_state_change_addl_field_add(state_change, "Name1", "Value1");
+ evel_state_change_addl_field_add(state_change, "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) state_change);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "StateChange");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(state_change);
+ evel_throttle_terminate();
+}
+
+void test_encode_syslog_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"syslog\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventSourceHost\", "
+ "\"syslogFacility\", "
+ "\"syslogProc\", "
+ "\"syslogProcId\", "
+ "\"syslogSData\", "
+ "\"syslogVer\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"Name2\"]"
+ "},"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"syslog\", "
+ "\"eventId\": \"126\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 126, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"syslogFields\": {"
+ "\"eventSourceType\": \"virtualNetworkFunction\", "
+ "\"syslogMsg\": \"SL Message\", "
+ "\"syslogTag\": \"SL Tag\", "
+ "\"syslogFieldsVersion\": 1.1, "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}"
+ "]"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SYSLOG * syslog = NULL;
+ evel_set_next_event_sequence(126);
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION,
+ "SL Message",
+ "SL Tag");
+ assert(syslog != NULL);
+ evel_syslog_type_set(syslog, "SL Type");
+ evel_syslog_event_source_host_set(syslog, "SL Host");
+ evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LINE_PRINTER);
+ evel_syslog_proc_set(syslog, "SL Proc");
+ evel_syslog_proc_id_set(syslog, 2);
+ evel_syslog_version_set(syslog, 1);
+ evel_syslog_s_data_set(syslog, "SL SDATA");
+ evel_syslog_addl_field_add(syslog, "Name1", "Value1");
+ evel_syslog_addl_field_add(syslog, "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) syslog);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Syslog");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(syslog);
+ evel_throttle_terminate();
+}
+
+void test_encode_fault_with_escaping()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"fault\", "
+ "\"eventId\": \"122\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 122, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Bad things happen...\\\\\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"faultFields\": {"
+ "\"alarmCondition\": \"My alarm condition\", "
+ "\"eventSeverity\": \"MAJOR\", "
+ "\"eventSourceType\": \"other\", "
+ "\"specificProblem\": \"It broke \\\"very\\\" badly\", "
+ "\"vfStatus\": \"Active\", "
+ "\"faultFieldsVersion\": 1.1, "
+ "\"alarmAdditionalInformation\": ["
+ "{\"name\": \"name1\", "
+ "\"value\": \"value1\"}, "
+ "{\"name\": \"name2\", "
+ "\"value\": \"value2\"}], "
+ "\"alarmInterfaceA\": \"My Interface Card\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(122);
+ EVENT_FAULT * fault = evel_new_fault("My alarm condition",
+ "It broke \"very\" badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_HOST,
+ EVEL_VF_STATUS_PREP_TERMINATE);
+ assert(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");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(fault);
+}