Initial VES for DANOS vRouter 09/106709/3
authorroot <root@danos-build.zbl31w4ywk4ulg0far32rd2huc.cx.internal.cloudapp.net>
Mon, 27 Apr 2020 21:53:00 +0000 (21:53 +0000)
committerMarco Platania <platania@research.att.com>
Tue, 28 Apr 2020 14:52:48 +0000 (14:52 +0000)
1. Create vpp_measurement_reporter that use DANOS configd query
   to retrieve statistics and libevel to transmit
2. Copy VES evel library to build a debian package under
   vpp_measurement_report
3. Add debian files to create a vpp_measurement_reporter + libevel
   debian package
4. Add debian install and systemctl start files
5. Add instruction to build VES reporter debian package (that will
   include libevel.so)
6. Add instructions to build DANOS ISO with VES reporter debian
   package and creating glance image

Issue-ID: INT-1566
Change-Id: If18f16525f07f1b6bae0fc105e0452263b4bf661
Signed-off-by: Brian Freeman <bf1936@att.com>
82 files changed:
.gitignore
heat/vFWCLDN/vFWSNK/MANIFEST.json [new file with mode: 0644]
heat/vFWCLDN/vFWSNK/base_vfw.env [new file with mode: 0644]
heat/vFWCLDN/vFWSNK/base_vfw.yaml [new file with mode: 0644]
heat/vFWCLDN/vPKG/MANIFEST.json [new file with mode: 0644]
heat/vFWCLDN/vPKG/base_vpkg.env [new file with mode: 0644]
heat/vFWCLDN/vPKG/base_vpkg.yaml [new file with mode: 0644]
heat/vFWCL_DANOS/vFWSNK/MANIFEST.json [new file with mode: 0644]
heat/vFWCL_DANOS/vFWSNK/base_vfw.env [new file with mode: 0644]
heat/vFWCL_DANOS/vFWSNK/base_vfw.yaml [new file with mode: 0644]
heat/vFWCL_DANOS/vPKG/MANIFEST.json [new file with mode: 0644]
heat/vFWCL_DANOS/vPKG/base_vpkg.env [new file with mode: 0644]
heat/vFWCL_DANOS/vPKG/base_vpkg.yaml [new file with mode: 0644]
preload_data/vFWCLDN/preload_data.json [new file with mode: 0644]
preload_data/vFWCL_DANOS/preload_data.json [new file with mode: 0644]
service_mapping/vFWCLDN/service_mapping.json [new file with mode: 0644]
service_mapping/vFWCL_DANOS/service_mapping.json [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/DANOS_BUILD.md [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/LICENSE.TXT [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/Makefile [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/README.md [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/dcae_collector.env [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/debian/changelog [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/debian/compat [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/debian/control [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/debian/copyright [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/debian/rules [new file with mode: 0755]
vnfs/VESreporting_vFW5.0_DANOS/debian/source/format [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/debian/vpp-measurement-reporter-danos.install [new file with mode: 0755]
vnfs/VESreporting_vFW5.0_DANOS/debian/vpp-measurement-reporter-danos.service [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/dep.xml [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/LICENSE.TXT [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/bldjobs/Makefile [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/double_list.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/double_list.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_batch.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_event.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_event_mgr.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_fault.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_heartbeat_fields.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_internal.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_internal_event.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_json_buffer.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_jsonobject.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_logging.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_mobile_flow.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_option.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_other.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_reporting_measurement.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_scaling_measurement.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_sipsignaling.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_state_change.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_strings.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_syslog.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_threshold_cross.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_throttle.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_throttle.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_voicequality.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/hashtable.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/hashtable.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/jsmn.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/jsmn.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/license.md [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/metadata.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/metadata.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/quickstart.md [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/readme.md [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/ring_buffer.c [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/ring_buffer.h [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/docs/source/evel/README [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/aarch64/libevel.a [new file with mode: 0755]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/README [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.a [new file with mode: 0755]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.so [new file with mode: 0755]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/output/x86_64/README [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/readme.md [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/log_file [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/onap-ca.crt [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/pom.xml [new file with mode: 0644]
vnfs/VESreporting_vFW5.0_DANOS/vpp-measurement-reporter-danos.c [new file with mode: 0644]

index 4c1a894..a42b48a 100644 (file)
@@ -8,3 +8,8 @@ target/
 *.iml
 .gitconfig
 .tox/
+*.o
+*.deb
+*.d
+*.tgz
+vpp_measurement_reporter
diff --git a/heat/vFWCLDN/vFWSNK/MANIFEST.json b/heat/vFWCLDN/vFWSNK/MANIFEST.json
new file mode 100644 (file)
index 0000000..4938378
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "name": "",
+    "description": "",
+    "data": [
+        {
+            "file": "base_vfw.yaml",
+            "type": "HEAT",
+            "isBase": "true",
+            "data": [
+                {
+                    "file": "base_vfw.env",
+                    "type": "HEAT_ENV"
+                }
+            ]
+        }
+    ]
+}
diff --git a/heat/vFWCLDN/vFWSNK/base_vfw.env b/heat/vFWCLDN/vFWSNK/base_vfw.env
new file mode 100644 (file)
index 0000000..cc40ce9
--- /dev/null
@@ -0,0 +1,55 @@
+parameters:
+
+  # VM_TYPE: vfw
+  vfw_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404)
+  vfw_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested)
+  vfw_int_unprotected_private_ip_0: 192.168.10.100
+  vfw_int_protected_private_ip_0: 192.168.20.100
+  vfw_onap_private_ip_0: 10.0.100.1
+  # vpg_private_ip_0: 192.168.10.200
+  # this is the private ip 0 for vpg
+  vfw_int_protected_private_floating_ip: 192.168.10.200
+  vfw_name_0: zdfw1fwl01fwl01
+
+  # VM_TYPE: vsn
+  vsn_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404)
+  vsn_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested)
+  vsn_int_protected_private_ip_0: 192.168.20.250
+  vsn_onap_private_ip_0: 10.0.100.3
+  vsn_name_0: zdfw1fwl01snk01
+
+  # NETWORK_ROLE: public
+  public_net_id: PUT THE PUBLIC NETWORK ID HERE
+
+  # NETWORK_ROLE: unprotected_private
+  int_unprotected_private_net_id: zdfw1fwl01_unprotected
+  int_unprotected_private_subnet_id: zdfw1fwl01_unprotected_sub
+  unprotected_private_net_cidr: 192.168.10.0/24
+
+  # NETWORK_ROLE: protected_private
+  int_protected_private_net_id: zdfw1fwl01_protected
+  int_protected_private_subnet_id: zdfw1fwl01_protected_sub
+  protected_private_net_cidr: 192.168.20.0/24
+
+  # NETWORK_ROLE: onap_private
+  onap_private_net_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_subnet_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_net_cidr: 10.0.0.0/16
+
+  # METADATA
+  net_prefix: vFWSNK
+  vnf_name: vFWSNK
+  vnf_id: vFirewall_demo_app
+  vf_module_id: vFirewallCL
+
+  # APP/USER_DATA
+  dcae_collector_ip: 10.0.4.1
+  # 30417 is https node port to VES
+  dcae_collector_port: 30417
+  demo_artifacts_version: 1.6.0-SNAPSHOT
+  install_script_version: 1.6.0-SNAPSHOT
+  key_name: vfw_key
+  pub_key: PUT YOUR KEY HERE
+  cloud_env: PUT openstack OR rackspace HERE
+  sec_group: PUT THE ONAP SECURITY GROUP HERE
+  nexus_artifact_repo: https://nexus.onap.org
diff --git a/heat/vFWCLDN/vFWSNK/base_vfw.yaml b/heat/vFWCLDN/vFWSNK/base_vfw.yaml
new file mode 100644 (file)
index 0000000..fb16193
--- /dev/null
@@ -0,0 +1,355 @@
+##########################################################################
+#
+#==================LICENSE_START==========================================
+#
+#
+# Copyright (c) 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.
+#
+#==================LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+##########################################################################
+
+heat_template_version: 2013-05-23
+
+description: Heat template that deploys vFirewall Closed Loop demo app (vFW and vSink) for ONAP
+
+##############
+#            #
+# PARAMETERS #
+#            #
+##############
+
+parameters:
+  vfw_image_name:
+    type: string
+    label: Image name or ID
+    description: Image to be used for compute instance
+  vfw_flavor_name:
+    type: string
+    label: Flavor
+    description: Type of instance (flavor) to be used
+  vsn_image_name:
+    type: string
+    label: Image name or ID
+    description: Image to be used for compute instance
+  vsn_flavor_name:
+    type: string
+    label: Flavor
+    description: Type of instance (flavor) to be used
+  public_net_id:
+    type: string
+    label: Public network name or ID
+    description: Public network that enables remote connection to VNF
+  int_unprotected_private_net_id:
+    type: string
+    label: Unprotected private network name or ID
+    description: Private network that connects vPacketGenerator with vFirewall
+  int_unprotected_private_subnet_id:
+    type: string
+    label: Unprotected private subnetwork name or ID
+    description: Private subnetwork of the protected network
+  unprotected_private_net_cidr:
+    type: string
+    label: Unprotected private network CIDR
+    description: The CIDR of the unprotected private network
+  int_protected_private_net_id:
+    type: string
+    label: Protected private network name or ID
+    description: Private network that connects vFirewall with vSink
+  int_protected_private_subnet_id:
+    type: string
+    label: Protected private subnetwork name or ID
+    description: Private subnetwork of the unprotected network
+  protected_private_net_cidr:
+    type: string
+    label: Protected private network CIDR
+    description: The CIDR of the protected private network
+  onap_private_net_id:
+    type: string
+    label: ONAP management network name or ID
+    description: Private network that connects ONAP components and the VNF
+  onap_private_subnet_id:
+    type: string
+    label: ONAP management sub-network name or ID
+    description: Private sub-network that connects ONAP components and the VNF
+  onap_private_net_cidr:
+    type: string
+    label: ONAP private network CIDR
+    description: The CIDR of the protected private network
+  vfw_int_unprotected_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vFirewall to communicate with the vPacketGenerator
+  vfw_int_protected_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the protected network
+    description: Private IP address that is assigned to the vFirewall to communicate with the vSink
+  vfw_onap_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the ONAP management network
+    description: Private IP address that is assigned to the vFirewall to communicate with ONAP components
+  vfw_int_protected_private_floating_ip:
+    type: string
+    label: vPacketGenerator private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vPacketGenerator to communicate with the vFirewall
+  vsn_int_protected_private_ip_0:
+    type: string
+    label: vSink private IP address towards the protected network
+    description: Private IP address that is assigned to the vSink to communicate with the vFirewall
+  vsn_onap_private_ip_0:
+    type: string
+    label: vSink private IP address towards the ONAP management network
+    description: Private IP address that is assigned to the vSink to communicate with ONAP components
+  vfw_name_0:
+    type: string
+    label: vFirewall name
+    description: Name of the vFirewall
+  vsn_name_0:
+    type: string
+    label: vSink name
+    description: Name of the vSink
+  vnf_name:
+    type: string
+    label: VNF NAME
+    description: The VNF NAME is provided by ONAP
+  net_prefix:
+    type: string
+    label: Network prefix
+    description: Prefix for private network names - Workaround for Dublin
+  vnf_id:
+    type: string
+    label: VNF ID
+    description: The VNF ID is provided by ONAP
+  vf_module_id:
+    type: string
+    label: vFirewall module ID
+    description: The vFirewall Module ID is provided by ONAP
+  dcae_collector_ip:
+    type: string
+    label: DCAE collector IP address
+    description: IP address of the DCAE collector
+  dcae_collector_port:
+    type: string
+    label: DCAE collector port
+    description: Port of the DCAE collector
+  key_name:
+    type: string
+    label: Key pair name
+    description: Public/Private key pair name
+  pub_key:
+    type: string
+    label: Public key
+    description: Public key to be installed on the compute instance
+  install_script_version:
+    type: string
+    label: Installation script version number
+    description: Version number of the scripts that install the vFW demo app
+  demo_artifacts_version:
+    type: string
+    label: Artifacts version used in demo vnfs
+    description: Artifacts (jar, tar.gz) version used in demo vnfs
+  nexus_artifact_repo:
+    type: string
+    description: Root URL for the Nexus repository for Maven artifacts.
+  cloud_env:
+    type: string
+    label: Cloud environment
+    description: Cloud environment (e.g., openstack, rackspace)
+  sec_group:
+    type: string
+    description: ONAP Security Group
+
+#############
+#           #
+# RESOURCES #
+#           #
+#############
+
+resources:
+  random-str:
+    type: OS::Heat::RandomString
+    properties:
+      length: 4
+
+  my_keypair:
+    type: OS::Nova::KeyPair
+    properties:
+      name:
+        str_replace:
+          template: vnfname_base_rand
+          params:
+            base: { get_param: key_name }
+            vnfname: { get_param: vnf_name }
+            rand: { get_resource: random-str }
+      public_key: { get_param: pub_key }
+      save_private_key: false
+
+  int_unprotected_private_network:
+    type: OS::Neutron::Net
+    properties:
+      name:
+        str_replace:
+          template: vnfname_netid
+          params:
+            netid: { get_param: int_unprotected_private_net_id }
+            vnfname: { get_param: net_prefix }
+
+  int_unprotected_private_subnet:
+    type: OS::Neutron::Subnet
+    properties:
+      name:
+        str_replace:
+          template: vnfname_subnetid
+          params:
+            subnetid: { get_param: int_unprotected_private_subnet_id }
+            vnfname: { get_param: net_prefix }
+      network: { get_resource: int_unprotected_private_network }
+      cidr: { get_param: unprotected_private_net_cidr }
+
+  int_protected_private_network:
+    type: OS::Neutron::Net
+    properties:
+      name:
+        str_replace:
+          template: vnfname_netid
+          params:
+            netid: { get_param: int_protected_private_net_id }
+            vnfname: { get_param: net_prefix }
+
+  int_protected_private_subnet:
+    type: OS::Neutron::Subnet
+    properties:
+      name:
+        str_replace:
+          template: vnfname_subnetid
+          params:
+            subnetid: { get_param: int_protected_private_subnet_id }
+            vnfname: { get_param: net_prefix }
+      network: { get_resource: int_protected_private_network }
+      cidr: { get_param: protected_private_net_cidr }
+
+  # DANOS installation as Virtual Firewall instantiation
+  vfw_0_int_unprotected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_resource: int_unprotected_private_network }
+      fixed_ips: [{"subnet": { get_resource: int_unprotected_private_subnet }, "ip_address": { get_param: vfw_int_unprotected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vfw_0_int_protected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      allowed_address_pairs: [{ "ip_address": { get_param: vfw_int_protected_private_floating_ip }}]
+      network: { get_resource: int_protected_private_network }
+      fixed_ips: [{"subnet": { get_resource: int_protected_private_subnet }, "ip_address": { get_param: vfw_int_protected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vfw_0_onap_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: onap_private_net_id }
+      fixed_ips: [{"subnet": { get_param: onap_private_subnet_id }, "ip_address": { get_param: vfw_onap_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vfw_server_0:
+    type: OS::Nova::Server
+    properties:
+      image: { get_param: vfw_image_name }
+      flavor: { get_param: vfw_flavor_name }
+      name: { get_param: vfw_name_0 }
+      key_name: { get_resource: my_keypair }
+      networks:
+        - network: { get_param: public_net_id }
+        - port: { get_resource: vfw_0_int_unprotected_private_port_0 }
+        - port: { get_resource: vfw_0_int_protected_private_port_0 }
+        - port: { get_resource: vfw_0_onap_private_port_0 }
+      metadata:
+        vnf_name: { get_param: vnf_name }
+        vnf_id: { get_param: vnf_id }
+        vf_module_id: { get_param: vf_module_id }
+
+  # Virtual Sink instantiation
+  vsn_0_int_protected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_resource: int_protected_private_network }
+      fixed_ips: [{"subnet": { get_resource: int_protected_private_subnet }, "ip_address": { get_param: vsn_int_protected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vsn_0_onap_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: onap_private_net_id }
+      fixed_ips: [{"subnet": { get_param: onap_private_subnet_id }, "ip_address": { get_param: vsn_onap_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vsn_server_0:
+    type: OS::Nova::Server
+    properties:
+      image: { get_param: vsn_image_name }
+      flavor: { get_param: vsn_flavor_name }
+      name: { get_param: vsn_name_0 }
+      key_name: { get_resource: my_keypair }
+      networks:
+        - network: { get_param: public_net_id }
+        - port: { get_resource: vsn_0_int_protected_private_port_0 }
+        - port: { get_resource: vsn_0_onap_private_port_0 }
+      metadata:
+        vnf_name: { get_param: vnf_name }
+        vnf_id: { get_param: vnf_id }
+        vf_module_id: { get_param: vf_module_id }
+      user_data_format: RAW
+      user_data:
+        str_replace:
+          params:
+            __protected_net_gw__: { get_param: vfw_int_protected_private_ip_0 }
+            __unprotected_net__: { get_param: unprotected_private_net_cidr }
+            __install_script_version__: { get_param: install_script_version }
+            __vsn_private_ip_0__: { get_param: vsn_int_protected_private_ip_0 }
+            __vsn_private_ip_1__: { get_param: vsn_onap_private_ip_0 }
+            __protected_private_net_cidr__: { get_param: protected_private_net_cidr }
+            __onap_private_net_cidr__: { get_param: onap_private_net_cidr }
+            __cloud_env__: { get_param: cloud_env }
+            __nexus_artifact_repo__: { get_param: nexus_artifact_repo }
+          template: |
+            #!/bin/bash
+
+            # Create configuration files
+            mkdir /opt/config
+            echo "__protected_net_gw__" > /opt/config/protected_net_gw.txt
+            echo "__unprotected_net__" > /opt/config/unprotected_net.txt
+            echo "__install_script_version__" > /opt/config/install_script_version.txt
+            echo "__vsn_private_ip_0__" > /opt/config/vsn_private_ip_0.txt
+            echo "__vsn_private_ip_1__" > /opt/config/vsn_private_ip_1.txt
+            echo "__protected_private_net_cidr__" > /opt/config/protected_private_net_cidr.txt
+            echo "__onap_private_net_cidr__" > /opt/config/onap_private_net_cidr.txt
+            echo "__cloud_env__" > /opt/config/cloud_env.txt
+            echo "__nexus_artifact_repo__" > /opt/config/nexus_artifact_repo.txt
+
+            # Download and run install script
+            apt-get update
+            apt-get -y install unzip
+            if [[ "__install_script_version__" =~ "SNAPSHOT" ]]; then REPO=snapshots; else REPO=releases; fi
+            curl -k -L "__nexus_artifact_repo__/service/local/artifact/maven/redirect?r=${REPO}&g=org.onap.demo.vnf.vfw&a=vfw-scripts&e=zip&v=__install_script_version__" -o /opt/vfw-scripts-__install_script_version__.zip
+            unzip -j /opt/vfw-scripts-__install_script_version__.zip -d /opt v_sink_install.sh
+            cd /opt
+            chmod +x v_sink_install.sh
+            ./v_sink_install.sh
diff --git a/heat/vFWCLDN/vPKG/MANIFEST.json b/heat/vFWCLDN/vPKG/MANIFEST.json
new file mode 100644 (file)
index 0000000..482b429
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "name": "",
+    "description": "",
+    "data": [
+        {
+            "file": "base_vpkg.yaml",
+            "type": "HEAT",
+            "isBase": "true",
+            "data": [
+                {
+                    "file": "base_vpkg.env",
+                    "type": "HEAT_ENV"
+                }
+            ]
+        }
+    ]
+}
diff --git a/heat/vFWCLDN/vPKG/base_vpkg.env b/heat/vFWCLDN/vPKG/base_vpkg.env
new file mode 100644 (file)
index 0000000..32cb92e
--- /dev/null
@@ -0,0 +1,40 @@
+parameters:
+
+  # VM_TYPE: vpg
+  vpg_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404)
+  vpg_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested)
+  vpg_unprotected_private_ip_0: 192.168.10.200
+  vpg_onap_private_ip_0: 10.0.100.2
+  vpg_name_0: zdfw1fwl01pgn01
+
+  # NETWORK_ROLE: public
+  public_net_id: PUT THE PUBLIC NETWORK ID HERE
+
+  # NETWORK_ROLE: unprotected_private
+  unprotected_private_net_id: vFWSNK_zdfw1fwl01_unprotected
+  unprotected_private_subnet_id: vFWSNK_zdfw1fwl01_unprotected_sub
+  unprotected_private_net_cidr: 192.168.10.0/24
+
+  # NETWORK_ROLE: onap_private
+  onap_private_net_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_subnet_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_net_cidr: 10.0.0.0/16
+
+  # NETWORK_ROLE: protected_private
+  protected_private_net_cidr: 192.168.20.0/24
+
+  # METADATA
+  vnf_name: vPGK
+  vnf_id: vPNG_Firewall_demo_app
+  vf_module_id: vTrafficPNG
+
+  # APP/USER_DATA
+  vfw_private_ip_0: 192.168.10.100
+  vsn_private_ip_0: 192.168.20.250
+  demo_artifacts_version: 1.6.0-SNAPSHOT
+  install_script_version: 1.6.0-SNAPSHOT
+  key_name: vfw_key
+  pub_key: PUT YOUR PUBLIC KEY HERE
+  cloud_env: PUT openstack OR rackspace HERE
+  sec_group: PUT THE ONAP SECURITY GROUP HERE
+  nexus_artifact_repo: https://nexus.onap.org
\ No newline at end of file
diff --git a/heat/vFWCLDN/vPKG/base_vpkg.yaml b/heat/vFWCLDN/vPKG/base_vpkg.yaml
new file mode 100644 (file)
index 0000000..032001c
--- /dev/null
@@ -0,0 +1,233 @@
+##########################################################################
+#
+#==================LICENSE_START==========================================
+#
+#
+# Copyright (c) 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.
+#
+#==================LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+##########################################################################
+
+heat_template_version: 2013-05-23
+
+description: Heat template that deploys the vFirewall Traffic Generator demo app for ONAP
+
+##############
+#            #
+# PARAMETERS #
+#            #
+##############
+
+parameters:
+  vpg_image_name:
+    type: string
+    label: Image name or ID
+    description: Image to be used for compute instance
+  vpg_flavor_name:
+    type: string
+    label: Flavor
+    description: Type of instance (flavor) to be used
+  public_net_id:
+    type: string
+    label: Public network name or ID
+    description: Public network that enables remote connection to VNF
+  unprotected_private_net_id:
+    type: string
+    label: Unprotected private network name or ID
+    description: Private network that connects vPacketGenerator with vFirewall
+  unprotected_private_subnet_id:
+    type: string
+    label: Unprotected private sub-network name or ID
+    description: Private subnetwork for the unprotected network
+  unprotected_private_net_cidr:
+    type: string
+    label: Unprotected private network CIDR
+    description: The CIDR of the unprotected private network
+  protected_private_net_cidr:
+    type: string
+    label: Protected private network CIDR
+    description: The CIDR of the protected private network
+  onap_private_net_id:
+    type: string
+    label: ONAP management network name or ID
+    description: Private network that connects ONAP components and the VNF
+  onap_private_subnet_id:
+    type: string
+    label: ONAP management sub-network name or ID
+    description: Private sub-network that connects ONAP components and the VNF
+  onap_private_net_cidr:
+    type: string
+    label: ONAP private network CIDR
+    description: The CIDR of the protected private network
+  vfw_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vFirewall to communicate with the vPacketGenerator
+  vsn_private_ip_0:
+    type: string
+    label: vSink private IP address towards the protected network
+    description: Private IP address that is assigned to the vSink to communicate with the vFirewall
+  vpg_unprotected_private_ip_0:
+    type: string
+    label: vPacketGenerator private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vPacketGenerator to communicate with the vFirewall
+  vpg_onap_private_ip_0:
+    type: string
+    label: vPacketGenerator private IP address towards the ONAP management network
+    description: Private IP address that is assigned to the vPacketGenerator to communicate with ONAP components
+  vpg_name_0:
+    type: string
+    label: vPacketGenerator name
+    description: Name of the vPacketGenerator
+  vnf_name:
+    type: string
+    label: VNF NAME
+    description: The VNF NAME is provided by ONAP
+  vnf_id:
+    type: string
+    label: VNF ID
+    description: The VNF ID is provided by ONAP
+  vf_module_id:
+    type: string
+    label: vPNG Traffic Generator module ID
+    description: The vPNG Module ID is provided by ONAP
+  key_name:
+    type: string
+    label: Key pair name
+    description: Public/Private key pair name
+  pub_key:
+    type: string
+    label: Public key
+    description: Public key to be installed on the compute instance
+  install_script_version:
+    type: string
+    label: Installation script version number
+    description: Version number of the scripts that install the vFW demo app
+  demo_artifacts_version:
+    type: string
+    label: Artifacts version used in demo vnfs
+    description: Artifacts (jar, tar.gz) version used in demo vnfs
+  nexus_artifact_repo:
+    type: string
+    description: Root URL for the Nexus repository for Maven artifacts.
+  cloud_env:
+    type: string
+    label: Cloud environment
+    description: Cloud environment (e.g., openstack, rackspace)
+  sec_group:
+    type: string
+    description: ONAP Security Group
+
+#############
+#           #
+# RESOURCES #
+#           #
+#############
+
+resources:
+  random-str:
+    type: OS::Heat::RandomString
+    properties:
+      length: 4
+
+  my_keypair:
+    type: OS::Nova::KeyPair
+    properties:
+      name:
+        str_replace:
+          template: vnfname_base_rand
+          params:
+            vnfname: { get_param: vnf_name }
+            base: { get_param: key_name }
+            rand: { get_resource: random-str }
+      public_key: { get_param: pub_key }
+      save_private_key: false
+
+
+  # Virtual Packet Generator instantiation
+  vpg_0_unprotected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: unprotected_private_net_id }
+      fixed_ips: [{"subnet": { get_param: unprotected_private_subnet_id }, "ip_address": { get_param: vpg_unprotected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vpg_0_onap_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: onap_private_net_id }
+      fixed_ips: [{"subnet": { get_param: onap_private_subnet_id }, "ip_address": { get_param: vpg_onap_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vpg_server_0:
+    type: OS::Nova::Server
+    properties:
+      image: { get_param: vpg_image_name }
+      flavor: { get_param: vpg_flavor_name }
+      name: { get_param: vpg_name_0 }
+      key_name: { get_resource: my_keypair }
+      networks:
+        - network: { get_param: public_net_id }
+        - port: { get_resource: vpg_0_unprotected_private_port_0 }
+        - port: { get_resource: vpg_0_onap_private_port_0 }
+      metadata:
+        vnf_name: { get_param: vnf_name }
+        vnf_id: { get_param: vnf_id }
+        vf_module_id: { get_param: vf_module_id }
+      user_data_format: RAW
+      user_data:
+        str_replace:
+          params:
+            __fw_ipaddr__: { get_param: vfw_private_ip_0 }
+            __protected_net_cidr__: { get_param: protected_private_net_cidr }
+            __sink_ipaddr__: { get_param: vsn_private_ip_0 }
+            __demo_artifacts_version__: { get_param: demo_artifacts_version }
+            __install_script_version__: { get_param: install_script_version }
+            __vpg_private_ip_0__: { get_param: vpg_unprotected_private_ip_0 }
+            __vpg_private_ip_1__: { get_param: vpg_onap_private_ip_0 }
+            __unprotected_private_net_cidr__: { get_param: unprotected_private_net_cidr }
+            __onap_private_net_cidr__: { get_param: onap_private_net_cidr }
+            __cloud_env__: { get_param: cloud_env }
+            __nexus_artifact_repo__: { get_param: nexus_artifact_repo }
+          template: |
+            #!/bin/bash
+
+            # Create configuration files
+            mkdir /opt/config
+            echo "__fw_ipaddr__" > /opt/config/fw_ipaddr.txt
+            echo "__protected_net_cidr__" > /opt/config/protected_net_cidr.txt
+            echo "__sink_ipaddr__" > /opt/config/sink_ipaddr.txt
+            echo "__demo_artifacts_version__" > /opt/config/demo_artifacts_version.txt
+            echo "__install_script_version__" > /opt/config/install_script_version.txt
+            echo "__vpg_private_ip_0__" > /opt/config/vpg_private_ip_0.txt
+            echo "__vpg_private_ip_1__" > /opt/config/vpg_private_ip_1.txt
+            echo "__unprotected_private_net_cidr__" > /opt/config/unprotected_private_net_cidr.txt
+            echo "__onap_private_net_cidr__" > /opt/config/onap_private_net_cidr.txt
+            echo "__cloud_env__" > /opt/config/cloud_env.txt
+            echo "__nexus_artifact_repo__" > /opt/config/nexus_artifact_repo.txt
+
+            # Download and run install script
+            apt-get update
+            apt-get -y install unzip
+            if [[ "__install_script_version__" =~ "SNAPSHOT" ]]; then REPO=snapshots; else REPO=releases; fi
+            curl -k -L "__nexus_artifact_repo__/service/local/artifact/maven/redirect?r=${REPO}&g=org.onap.demo.vnf.vfw&a=vfw-scripts&e=zip&v=__install_script_version__" -o /opt/vfw-scripts-__install_script_version__.zip
+            unzip -j /opt/vfw-scripts-__install_script_version__.zip -d /opt v_packetgen_install.sh
+            cd /opt
+            chmod +x v_packetgen_install.sh
+            ./v_packetgen_install.sh
diff --git a/heat/vFWCL_DANOS/vFWSNK/MANIFEST.json b/heat/vFWCL_DANOS/vFWSNK/MANIFEST.json
new file mode 100644 (file)
index 0000000..4938378
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "name": "",
+    "description": "",
+    "data": [
+        {
+            "file": "base_vfw.yaml",
+            "type": "HEAT",
+            "isBase": "true",
+            "data": [
+                {
+                    "file": "base_vfw.env",
+                    "type": "HEAT_ENV"
+                }
+            ]
+        }
+    ]
+}
diff --git a/heat/vFWCL_DANOS/vFWSNK/base_vfw.env b/heat/vFWCL_DANOS/vFWSNK/base_vfw.env
new file mode 100644 (file)
index 0000000..cc40ce9
--- /dev/null
@@ -0,0 +1,55 @@
+parameters:
+
+  # VM_TYPE: vfw
+  vfw_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404)
+  vfw_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested)
+  vfw_int_unprotected_private_ip_0: 192.168.10.100
+  vfw_int_protected_private_ip_0: 192.168.20.100
+  vfw_onap_private_ip_0: 10.0.100.1
+  # vpg_private_ip_0: 192.168.10.200
+  # this is the private ip 0 for vpg
+  vfw_int_protected_private_floating_ip: 192.168.10.200
+  vfw_name_0: zdfw1fwl01fwl01
+
+  # VM_TYPE: vsn
+  vsn_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404)
+  vsn_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested)
+  vsn_int_protected_private_ip_0: 192.168.20.250
+  vsn_onap_private_ip_0: 10.0.100.3
+  vsn_name_0: zdfw1fwl01snk01
+
+  # NETWORK_ROLE: public
+  public_net_id: PUT THE PUBLIC NETWORK ID HERE
+
+  # NETWORK_ROLE: unprotected_private
+  int_unprotected_private_net_id: zdfw1fwl01_unprotected
+  int_unprotected_private_subnet_id: zdfw1fwl01_unprotected_sub
+  unprotected_private_net_cidr: 192.168.10.0/24
+
+  # NETWORK_ROLE: protected_private
+  int_protected_private_net_id: zdfw1fwl01_protected
+  int_protected_private_subnet_id: zdfw1fwl01_protected_sub
+  protected_private_net_cidr: 192.168.20.0/24
+
+  # NETWORK_ROLE: onap_private
+  onap_private_net_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_subnet_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_net_cidr: 10.0.0.0/16
+
+  # METADATA
+  net_prefix: vFWSNK
+  vnf_name: vFWSNK
+  vnf_id: vFirewall_demo_app
+  vf_module_id: vFirewallCL
+
+  # APP/USER_DATA
+  dcae_collector_ip: 10.0.4.1
+  # 30417 is https node port to VES
+  dcae_collector_port: 30417
+  demo_artifacts_version: 1.6.0-SNAPSHOT
+  install_script_version: 1.6.0-SNAPSHOT
+  key_name: vfw_key
+  pub_key: PUT YOUR KEY HERE
+  cloud_env: PUT openstack OR rackspace HERE
+  sec_group: PUT THE ONAP SECURITY GROUP HERE
+  nexus_artifact_repo: https://nexus.onap.org
diff --git a/heat/vFWCL_DANOS/vFWSNK/base_vfw.yaml b/heat/vFWCL_DANOS/vFWSNK/base_vfw.yaml
new file mode 100644 (file)
index 0000000..686c863
--- /dev/null
@@ -0,0 +1,389 @@
+##########################################################################
+#
+#==================LICENSE_START==========================================
+#
+#
+# Copyright (c) 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.
+#
+#==================LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+##########################################################################
+
+heat_template_version: 2013-05-23
+
+description: Heat template that deploys vFirewall Closed Loop demo app (vFW and vSink) for ONAP
+
+##############
+#            #
+# PARAMETERS #
+#            #
+##############
+
+parameters:
+  vfw_image_name:
+    type: string
+    label: Image name or ID
+    description: Image to be used for compute instance
+  vfw_flavor_name:
+    type: string
+    label: Flavor
+    description: Type of instance (flavor) to be used
+  vsn_image_name:
+    type: string
+    label: Image name or ID
+    description: Image to be used for compute instance
+  vsn_flavor_name:
+    type: string
+    label: Flavor
+    description: Type of instance (flavor) to be used
+  public_net_id:
+    type: string
+    label: Public network name or ID
+    description: Public network that enables remote connection to VNF
+  int_unprotected_private_net_id:
+    type: string
+    label: Unprotected private network name or ID
+    description: Private network that connects vPacketGenerator with vFirewall
+  int_unprotected_private_subnet_id:
+    type: string
+    label: Unprotected private subnetwork name or ID
+    description: Private subnetwork of the protected network
+  unprotected_private_net_cidr:
+    type: string
+    label: Unprotected private network CIDR
+    description: The CIDR of the unprotected private network
+  int_protected_private_net_id:
+    type: string
+    label: Protected private network name or ID
+    description: Private network that connects vFirewall with vSink
+  int_protected_private_subnet_id:
+    type: string
+    label: Protected private subnetwork name or ID
+    description: Private subnetwork of the unprotected network
+  protected_private_net_cidr:
+    type: string
+    label: Protected private network CIDR
+    description: The CIDR of the protected private network
+  onap_private_net_id:
+    type: string
+    label: ONAP management network name or ID
+    description: Private network that connects ONAP components and the VNF
+  onap_private_subnet_id:
+    type: string
+    label: ONAP management sub-network name or ID
+    description: Private sub-network that connects ONAP components and the VNF
+  onap_private_net_cidr:
+    type: string
+    label: ONAP private network CIDR
+    description: The CIDR of the protected private network
+  vfw_int_unprotected_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vFirewall to communicate with the vPacketGenerator
+  vfw_int_protected_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the protected network
+    description: Private IP address that is assigned to the vFirewall to communicate with the vSink
+  vfw_onap_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the ONAP management network
+    description: Private IP address that is assigned to the vFirewall to communicate with ONAP components
+  vfw_int_protected_private_floating_ip:
+    type: string
+    label: vPacketGenerator private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vPacketGenerator to communicate with the vFirewall
+  vsn_int_protected_private_ip_0:
+    type: string
+    label: vSink private IP address towards the protected network
+    description: Private IP address that is assigned to the vSink to communicate with the vFirewall
+  vsn_onap_private_ip_0:
+    type: string
+    label: vSink private IP address towards the ONAP management network
+    description: Private IP address that is assigned to the vSink to communicate with ONAP components
+  vfw_name_0:
+    type: string
+    label: vFirewall name
+    description: Name of the vFirewall
+  vsn_name_0:
+    type: string
+    label: vSink name
+    description: Name of the vSink
+  vnf_name:
+    type: string
+    label: VNF NAME
+    description: The VNF NAME is provided by ONAP
+  net_prefix:
+    type: string
+    label: Network prefix
+    description: Prefix for private network names - Workaround for Dublin
+  vnf_id:
+    type: string
+    label: VNF ID
+    description: The VNF ID is provided by ONAP
+  vf_module_id:
+    type: string
+    label: vFirewall module ID
+    description: The vFirewall Module ID is provided by ONAP
+  dcae_collector_ip:
+    type: string
+    label: DCAE collector IP address
+    description: IP address of the DCAE collector
+  dcae_collector_port:
+    type: string
+    label: DCAE collector port
+    description: Port of the DCAE collector
+  key_name:
+    type: string
+    label: Key pair name
+    description: Public/Private key pair name
+  pub_key:
+    type: string
+    label: Public key
+    description: Public key to be installed on the compute instance
+  install_script_version:
+    type: string
+    label: Installation script version number
+    description: Version number of the scripts that install the vFW demo app
+  demo_artifacts_version:
+    type: string
+    label: Artifacts version used in demo vnfs
+    description: Artifacts (jar, tar.gz) version used in demo vnfs
+  nexus_artifact_repo:
+    type: string
+    description: Root URL for the Nexus repository for Maven artifacts.
+  cloud_env:
+    type: string
+    label: Cloud environment
+    description: Cloud environment (e.g., openstack, rackspace)
+  sec_group:
+    type: string
+    description: ONAP Security Group
+
+#############
+#           #
+# RESOURCES #
+#           #
+#############
+
+resources:
+  random-str:
+    type: OS::Heat::RandomString
+    properties:
+      length: 4
+
+  my_keypair:
+    type: OS::Nova::KeyPair
+    properties:
+      name:
+        str_replace:
+          template: vnfname_base_rand
+          params:
+            base: { get_param: key_name }
+            vnfname: { get_param: vnf_name }
+            rand: { get_resource: random-str }
+      public_key: { get_param: pub_key }
+      save_private_key: false
+
+  int_unprotected_private_network:
+    type: OS::Neutron::Net
+    properties:
+      name:
+        str_replace:
+          template: vnfname_netid
+          params:
+            netid: { get_param: int_unprotected_private_net_id }
+            vnfname: { get_param: net_prefix }
+
+  int_unprotected_private_subnet:
+    type: OS::Neutron::Subnet
+    properties:
+      name:
+        str_replace:
+          template: vnfname_subnetid
+          params:
+            subnetid: { get_param: int_unprotected_private_subnet_id }
+            vnfname: { get_param: net_prefix }
+      network: { get_resource: int_unprotected_private_network }
+      cidr: { get_param: unprotected_private_net_cidr }
+
+  int_protected_private_network:
+    type: OS::Neutron::Net
+    properties:
+      name:
+        str_replace:
+          template: vnfname_netid
+          params:
+            netid: { get_param: int_protected_private_net_id }
+            vnfname: { get_param: net_prefix }
+
+  int_protected_private_subnet:
+    type: OS::Neutron::Subnet
+    properties:
+      name:
+        str_replace:
+          template: vnfname_subnetid
+          params:
+            subnetid: { get_param: int_protected_private_subnet_id }
+            vnfname: { get_param: net_prefix }
+      network: { get_resource: int_protected_private_network }
+      cidr: { get_param: protected_private_net_cidr }
+
+  # DANOS installation as Virtual Firewall instantiation
+  vfw_0_int_unprotected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_resource: int_unprotected_private_network }
+      fixed_ips: [{"subnet": { get_resource: int_unprotected_private_subnet }, "ip_address": { get_param: vfw_int_unprotected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vfw_0_int_protected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      allowed_address_pairs: [{ "ip_address": { get_param: vfw_int_protected_private_floating_ip }}]
+      network: { get_resource: int_protected_private_network }
+      fixed_ips: [{"subnet": { get_resource: int_protected_private_subnet }, "ip_address": { get_param: vfw_int_protected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vfw_0_onap_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: onap_private_net_id }
+      fixed_ips: [{"subnet": { get_param: onap_private_subnet_id }, "ip_address": { get_param: vfw_onap_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vfw_server_0:
+    type: OS::Nova::Server
+    properties:
+      image: { get_param: vfw_image_name }
+      flavor: { get_param: vfw_flavor_name }
+      name: { get_param: vfw_name_0 }
+      key_name: { get_resource: my_keypair }
+      networks:
+        - network: { get_param: public_net_id }
+        - port: { get_resource: vfw_0_int_unprotected_private_port_0 }
+        - port: { get_resource: vfw_0_int_protected_private_port_0 }
+        - port: { get_resource: vfw_0_onap_private_port_0 }
+      metadata:
+        vnf_name: { get_param: vnf_name }
+        vnf_id: { get_param: vnf_id }
+        vf_module_id: { get_param: vf_module_id }
+      user_data_format: RAW
+      user_data:
+        str_replace:
+          params:
+            __dcae_collector_ip__: { get_param: dcae_collector_ip }
+            __dcae_collector_port__: { get_param: dcae_collector_port }
+            __demo_artifacts_version__: { get_param: demo_artifacts_version }
+            __install_script_version__: { get_param: install_script_version }
+            __vfw_private_ip_0__: { get_param: vfw_int_unprotected_private_ip_0 }
+            __vfw_private_ip_1__: { get_param: vfw_int_protected_private_ip_0 }
+            __vfw_private_ip_2__: { get_param: vfw_onap_private_ip_0 }
+            __unprotected_private_net_cidr__: { get_param: unprotected_private_net_cidr }
+            __protected_private_net_cidr__: { get_param: protected_private_net_cidr }
+            __onap_private_net_cidr__: { get_param: onap_private_net_cidr }
+            __cloud_env__: { get_param: cloud_env }
+            __nexus_artifact_repo__: { get_param: nexus_artifact_repo }
+          template: |
+            #!/bin/bash
+
+            # Create configuration files
+            mkdir /opt/config
+            echo "__dcae_collector_ip__" > /opt/config/dcae_collector_ip.txt
+            echo "__dcae_collector_port__" > /opt/config/dcae_collector_port.txt
+            echo "__demo_artifacts_version__" > /opt/config/demo_artifacts_version.txt
+            echo "__install_script_version__" > /opt/config/install_script_version.txt
+            echo "__vfw_private_ip_0__" > /opt/config/vfw_private_ip_0.txt
+            echo "__vfw_private_ip_1__" > /opt/config/vfw_private_ip_1.txt
+            echo "__vfw_private_ip_2__" > /opt/config/vfw_private_ip_2.txt
+            echo "__unprotected_private_net_cidr__" > /opt/config/unprotected_private_net_cidr.txt
+            echo "__protected_private_net_cidr__" > /opt/config/protected_private_net_cidr.txt
+            echo "__onap_private_net_cidr__" > /opt/config/onap_private_net_cidr.txt
+            echo "__cloud_env__" > /opt/config/cloud_env.txt
+            echo "__nexus_artifact_repo__" > /opt/config/nexus_artifact_repo.txt
+
+
+  # Virtual Sink instantiation
+  vsn_0_int_protected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_resource: int_protected_private_network }
+      fixed_ips: [{"subnet": { get_resource: int_protected_private_subnet }, "ip_address": { get_param: vsn_int_protected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vsn_0_onap_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: onap_private_net_id }
+      fixed_ips: [{"subnet": { get_param: onap_private_subnet_id }, "ip_address": { get_param: vsn_onap_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vsn_server_0:
+    type: OS::Nova::Server
+    properties:
+      image: { get_param: vsn_image_name }
+      flavor: { get_param: vsn_flavor_name }
+      name: { get_param: vsn_name_0 }
+      key_name: { get_resource: my_keypair }
+      networks:
+        - network: { get_param: public_net_id }
+        - port: { get_resource: vsn_0_int_protected_private_port_0 }
+        - port: { get_resource: vsn_0_onap_private_port_0 }
+      metadata:
+        vnf_name: { get_param: vnf_name }
+        vnf_id: { get_param: vnf_id }
+        vf_module_id: { get_param: vf_module_id }
+      user_data_format: RAW
+      user_data:
+        str_replace:
+          params:
+            __protected_net_gw__: { get_param: vfw_int_protected_private_ip_0 }
+            __unprotected_net__: { get_param: unprotected_private_net_cidr }
+            __install_script_version__: { get_param: install_script_version }
+            __vsn_private_ip_0__: { get_param: vsn_int_protected_private_ip_0 }
+            __vsn_private_ip_1__: { get_param: vsn_onap_private_ip_0 }
+            __protected_private_net_cidr__: { get_param: protected_private_net_cidr }
+            __onap_private_net_cidr__: { get_param: onap_private_net_cidr }
+            __cloud_env__: { get_param: cloud_env }
+            __nexus_artifact_repo__: { get_param: nexus_artifact_repo }
+          template: |
+            #!/bin/bash
+
+            # Create configuration files
+            mkdir /opt/config
+            echo "__protected_net_gw__" > /opt/config/protected_net_gw.txt
+            echo "__unprotected_net__" > /opt/config/unprotected_net.txt
+            echo "__install_script_version__" > /opt/config/install_script_version.txt
+            echo "__vsn_private_ip_0__" > /opt/config/vsn_private_ip_0.txt
+            echo "__vsn_private_ip_1__" > /opt/config/vsn_private_ip_1.txt
+            echo "__protected_private_net_cidr__" > /opt/config/protected_private_net_cidr.txt
+            echo "__onap_private_net_cidr__" > /opt/config/onap_private_net_cidr.txt
+            echo "__cloud_env__" > /opt/config/cloud_env.txt
+            echo "__nexus_artifact_repo__" > /opt/config/nexus_artifact_repo.txt
+
+            # Download and run install script
+            apt-get update
+            apt-get -y install unzip
+            if [[ "__install_script_version__" =~ "SNAPSHOT" ]]; then REPO=snapshots; else REPO=releases; fi
+            curl -k -L "__nexus_artifact_repo__/service/local/artifact/maven/redirect?r=${REPO}&g=org.onap.demo.vnf.vfw&a=vfw-scripts&e=zip&v=__install_script_version__" -o /opt/vfw-scripts-__install_script_version__.zip
+            unzip -j /opt/vfw-scripts-__install_script_version__.zip -d /opt v_sink_install.sh
+            cd /opt
+            chmod +x v_sink_install.sh
+            ./v_sink_install.sh
diff --git a/heat/vFWCL_DANOS/vPKG/MANIFEST.json b/heat/vFWCL_DANOS/vPKG/MANIFEST.json
new file mode 100644 (file)
index 0000000..482b429
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "name": "",
+    "description": "",
+    "data": [
+        {
+            "file": "base_vpkg.yaml",
+            "type": "HEAT",
+            "isBase": "true",
+            "data": [
+                {
+                    "file": "base_vpkg.env",
+                    "type": "HEAT_ENV"
+                }
+            ]
+        }
+    ]
+}
diff --git a/heat/vFWCL_DANOS/vPKG/base_vpkg.env b/heat/vFWCL_DANOS/vPKG/base_vpkg.env
new file mode 100644 (file)
index 0000000..32cb92e
--- /dev/null
@@ -0,0 +1,40 @@
+parameters:
+
+  # VM_TYPE: vpg
+  vpg_image_name: PUT THE VM IMAGE NAME HERE (UBUNTU 1404)
+  vpg_flavor_name: PUT THE VM FLAVOR NAME HERE (m1.medium suggested)
+  vpg_unprotected_private_ip_0: 192.168.10.200
+  vpg_onap_private_ip_0: 10.0.100.2
+  vpg_name_0: zdfw1fwl01pgn01
+
+  # NETWORK_ROLE: public
+  public_net_id: PUT THE PUBLIC NETWORK ID HERE
+
+  # NETWORK_ROLE: unprotected_private
+  unprotected_private_net_id: vFWSNK_zdfw1fwl01_unprotected
+  unprotected_private_subnet_id: vFWSNK_zdfw1fwl01_unprotected_sub
+  unprotected_private_net_cidr: 192.168.10.0/24
+
+  # NETWORK_ROLE: onap_private
+  onap_private_net_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_subnet_id: PUT THE ONAP PRIVATE NETWORK NAME HERE
+  onap_private_net_cidr: 10.0.0.0/16
+
+  # NETWORK_ROLE: protected_private
+  protected_private_net_cidr: 192.168.20.0/24
+
+  # METADATA
+  vnf_name: vPGK
+  vnf_id: vPNG_Firewall_demo_app
+  vf_module_id: vTrafficPNG
+
+  # APP/USER_DATA
+  vfw_private_ip_0: 192.168.10.100
+  vsn_private_ip_0: 192.168.20.250
+  demo_artifacts_version: 1.6.0-SNAPSHOT
+  install_script_version: 1.6.0-SNAPSHOT
+  key_name: vfw_key
+  pub_key: PUT YOUR PUBLIC KEY HERE
+  cloud_env: PUT openstack OR rackspace HERE
+  sec_group: PUT THE ONAP SECURITY GROUP HERE
+  nexus_artifact_repo: https://nexus.onap.org
\ No newline at end of file
diff --git a/heat/vFWCL_DANOS/vPKG/base_vpkg.yaml b/heat/vFWCL_DANOS/vPKG/base_vpkg.yaml
new file mode 100644 (file)
index 0000000..032001c
--- /dev/null
@@ -0,0 +1,233 @@
+##########################################################################
+#
+#==================LICENSE_START==========================================
+#
+#
+# Copyright (c) 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.
+#
+#==================LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+##########################################################################
+
+heat_template_version: 2013-05-23
+
+description: Heat template that deploys the vFirewall Traffic Generator demo app for ONAP
+
+##############
+#            #
+# PARAMETERS #
+#            #
+##############
+
+parameters:
+  vpg_image_name:
+    type: string
+    label: Image name or ID
+    description: Image to be used for compute instance
+  vpg_flavor_name:
+    type: string
+    label: Flavor
+    description: Type of instance (flavor) to be used
+  public_net_id:
+    type: string
+    label: Public network name or ID
+    description: Public network that enables remote connection to VNF
+  unprotected_private_net_id:
+    type: string
+    label: Unprotected private network name or ID
+    description: Private network that connects vPacketGenerator with vFirewall
+  unprotected_private_subnet_id:
+    type: string
+    label: Unprotected private sub-network name or ID
+    description: Private subnetwork for the unprotected network
+  unprotected_private_net_cidr:
+    type: string
+    label: Unprotected private network CIDR
+    description: The CIDR of the unprotected private network
+  protected_private_net_cidr:
+    type: string
+    label: Protected private network CIDR
+    description: The CIDR of the protected private network
+  onap_private_net_id:
+    type: string
+    label: ONAP management network name or ID
+    description: Private network that connects ONAP components and the VNF
+  onap_private_subnet_id:
+    type: string
+    label: ONAP management sub-network name or ID
+    description: Private sub-network that connects ONAP components and the VNF
+  onap_private_net_cidr:
+    type: string
+    label: ONAP private network CIDR
+    description: The CIDR of the protected private network
+  vfw_private_ip_0:
+    type: string
+    label: vFirewall private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vFirewall to communicate with the vPacketGenerator
+  vsn_private_ip_0:
+    type: string
+    label: vSink private IP address towards the protected network
+    description: Private IP address that is assigned to the vSink to communicate with the vFirewall
+  vpg_unprotected_private_ip_0:
+    type: string
+    label: vPacketGenerator private IP address towards the unprotected network
+    description: Private IP address that is assigned to the vPacketGenerator to communicate with the vFirewall
+  vpg_onap_private_ip_0:
+    type: string
+    label: vPacketGenerator private IP address towards the ONAP management network
+    description: Private IP address that is assigned to the vPacketGenerator to communicate with ONAP components
+  vpg_name_0:
+    type: string
+    label: vPacketGenerator name
+    description: Name of the vPacketGenerator
+  vnf_name:
+    type: string
+    label: VNF NAME
+    description: The VNF NAME is provided by ONAP
+  vnf_id:
+    type: string
+    label: VNF ID
+    description: The VNF ID is provided by ONAP
+  vf_module_id:
+    type: string
+    label: vPNG Traffic Generator module ID
+    description: The vPNG Module ID is provided by ONAP
+  key_name:
+    type: string
+    label: Key pair name
+    description: Public/Private key pair name
+  pub_key:
+    type: string
+    label: Public key
+    description: Public key to be installed on the compute instance
+  install_script_version:
+    type: string
+    label: Installation script version number
+    description: Version number of the scripts that install the vFW demo app
+  demo_artifacts_version:
+    type: string
+    label: Artifacts version used in demo vnfs
+    description: Artifacts (jar, tar.gz) version used in demo vnfs
+  nexus_artifact_repo:
+    type: string
+    description: Root URL for the Nexus repository for Maven artifacts.
+  cloud_env:
+    type: string
+    label: Cloud environment
+    description: Cloud environment (e.g., openstack, rackspace)
+  sec_group:
+    type: string
+    description: ONAP Security Group
+
+#############
+#           #
+# RESOURCES #
+#           #
+#############
+
+resources:
+  random-str:
+    type: OS::Heat::RandomString
+    properties:
+      length: 4
+
+  my_keypair:
+    type: OS::Nova::KeyPair
+    properties:
+      name:
+        str_replace:
+          template: vnfname_base_rand
+          params:
+            vnfname: { get_param: vnf_name }
+            base: { get_param: key_name }
+            rand: { get_resource: random-str }
+      public_key: { get_param: pub_key }
+      save_private_key: false
+
+
+  # Virtual Packet Generator instantiation
+  vpg_0_unprotected_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: unprotected_private_net_id }
+      fixed_ips: [{"subnet": { get_param: unprotected_private_subnet_id }, "ip_address": { get_param: vpg_unprotected_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vpg_0_onap_private_port_0:
+    type: OS::Neutron::Port
+    properties:
+      network: { get_param: onap_private_net_id }
+      fixed_ips: [{"subnet": { get_param: onap_private_subnet_id }, "ip_address": { get_param: vpg_onap_private_ip_0 }}]
+      security_groups:
+      - { get_param: sec_group }
+
+  vpg_server_0:
+    type: OS::Nova::Server
+    properties:
+      image: { get_param: vpg_image_name }
+      flavor: { get_param: vpg_flavor_name }
+      name: { get_param: vpg_name_0 }
+      key_name: { get_resource: my_keypair }
+      networks:
+        - network: { get_param: public_net_id }
+        - port: { get_resource: vpg_0_unprotected_private_port_0 }
+        - port: { get_resource: vpg_0_onap_private_port_0 }
+      metadata:
+        vnf_name: { get_param: vnf_name }
+        vnf_id: { get_param: vnf_id }
+        vf_module_id: { get_param: vf_module_id }
+      user_data_format: RAW
+      user_data:
+        str_replace:
+          params:
+            __fw_ipaddr__: { get_param: vfw_private_ip_0 }
+            __protected_net_cidr__: { get_param: protected_private_net_cidr }
+            __sink_ipaddr__: { get_param: vsn_private_ip_0 }
+            __demo_artifacts_version__: { get_param: demo_artifacts_version }
+            __install_script_version__: { get_param: install_script_version }
+            __vpg_private_ip_0__: { get_param: vpg_unprotected_private_ip_0 }
+            __vpg_private_ip_1__: { get_param: vpg_onap_private_ip_0 }
+            __unprotected_private_net_cidr__: { get_param: unprotected_private_net_cidr }
+            __onap_private_net_cidr__: { get_param: onap_private_net_cidr }
+            __cloud_env__: { get_param: cloud_env }
+            __nexus_artifact_repo__: { get_param: nexus_artifact_repo }
+          template: |
+            #!/bin/bash
+
+            # Create configuration files
+            mkdir /opt/config
+            echo "__fw_ipaddr__" > /opt/config/fw_ipaddr.txt
+            echo "__protected_net_cidr__" > /opt/config/protected_net_cidr.txt
+            echo "__sink_ipaddr__" > /opt/config/sink_ipaddr.txt
+            echo "__demo_artifacts_version__" > /opt/config/demo_artifacts_version.txt
+            echo "__install_script_version__" > /opt/config/install_script_version.txt
+            echo "__vpg_private_ip_0__" > /opt/config/vpg_private_ip_0.txt
+            echo "__vpg_private_ip_1__" > /opt/config/vpg_private_ip_1.txt
+            echo "__unprotected_private_net_cidr__" > /opt/config/unprotected_private_net_cidr.txt
+            echo "__onap_private_net_cidr__" > /opt/config/onap_private_net_cidr.txt
+            echo "__cloud_env__" > /opt/config/cloud_env.txt
+            echo "__nexus_artifact_repo__" > /opt/config/nexus_artifact_repo.txt
+
+            # Download and run install script
+            apt-get update
+            apt-get -y install unzip
+            if [[ "__install_script_version__" =~ "SNAPSHOT" ]]; then REPO=snapshots; else REPO=releases; fi
+            curl -k -L "__nexus_artifact_repo__/service/local/artifact/maven/redirect?r=${REPO}&g=org.onap.demo.vnf.vfw&a=vfw-scripts&e=zip&v=__install_script_version__" -o /opt/vfw-scripts-__install_script_version__.zip
+            unzip -j /opt/vfw-scripts-__install_script_version__.zip -d /opt v_packetgen_install.sh
+            cd /opt
+            chmod +x v_packetgen_install.sh
+            ./v_packetgen_install.sh
diff --git a/preload_data/vFWCLDN/preload_data.json b/preload_data/vFWCLDN/preload_data.json
new file mode 100644 (file)
index 0000000..a42ec90
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    "vfwsnk_preload.template": {
+        "int_unprotected_private_net_id": "vofwlsnk_unprotected${hostid}",
+        "int_unprotected_private_subnet_id": "vofwlsnk_unprotected_sub${hostid}",
+        "unprotected_private_net_cidr": "192.168.10.0/24",
+        "int_protected_private_net_id": "vofwlsnk_protected${hostid}",
+        "int_protected_private_subnet_id": "vofwlsnk_protected_sub${hostid}",
+        "protected_private_net_cidr": "192.168.20.0/24",
+        "vfw_int_unprotected_private_ip_0": "192.168.10.100",
+        "vfw_int_protected_private_floating_ip": "192.168.10.200",
+        "vfw_int_protected_private_ip_0": "192.168.20.100",
+        "vfw_onap_private_ip_0": "${GLOBAL_INJECTED_OPENSTACK_OAM_NETWORK_CIDR_PREFIX}.${ecompnet}.101",
+        "vsn_int_protected_private_ip_0": "192.168.20.250",
+        "vsn_onap_private_ip_0": "${GLOBAL_INJECTED_OPENSTACK_OAM_NETWORK_CIDR_PREFIX}.${ecompnet}.102",
+        "vfw_name_0": "vofwl01fwl${hostid}",
+        "vsn_name_0": "vofwl01snk${hostid}",
+        "vfw_image_name": "${GLOBAL_INJECTED_DANOS_IMAGE}",
+        "vfw_flavor_name": "${GLOBAL_INJECTED_DANOS_FLAVOR}",
+        "vsn_image_name": "${GLOBAL_INJECTED_UBUNTU_1404_IMAGE}",
+        "vsn_flavor_name": "${GLOBAL_INJECTED_VM_FLAVOR}"
+    },
+    "vpkg_preload.template": {
+        "unprotected_private_net_id": "vFWSNK_vofwlsnk_unprotected${hostid}",
+        "unprotected_private_subnet_id": "vFWSNK_vofwlsnk_unprotected_sub${hostid}",
+        "unprotected_private_net_cidr": "192.168.10.0/24",
+        "protected_private_net_cidr": "192.168.20.0/24",
+        "vfw_private_ip_0": "192.168.10.100",
+        "vpg_unprotected_private_ip_0": "192.168.10.200",
+        "vpg_onap_private_ip_0": "${GLOBAL_INJECTED_OPENSTACK_OAM_NETWORK_CIDR_PREFIX}.${ecompnet}.103",
+        "vsn_private_ip_0": "192.168.20.250",
+        "vpg_name_0": "vofwl01pgn${hostid}",
+        "vpg_image_name": "${GLOBAL_INJECTED_UBUNTU_1404_IMAGE}",
+        "vpg_flavor_name": "${GLOBAL_INJECTED_VM_FLAVOR}"
+    }
+}
diff --git a/preload_data/vFWCL_DANOS/preload_data.json b/preload_data/vFWCL_DANOS/preload_data.json
new file mode 100644 (file)
index 0000000..1a50b26
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    "vfwsnk_preload.template": {
+        "int_unprotected_private_net_id": "vofwlsnk_unprotected${hostid}",
+        "int_unprotected_private_subnet_id": "vofwlsnk_unprotected_sub${hostid}",
+        "unprotected_private_net_cidr": "192.168.10.0/24",
+        "int_protected_private_net_id": "vofwlsnk_protected${hostid}",
+        "int_protected_private_subnet_id": "vofwlsnk_protected_sub${hostid}",
+        "protected_private_net_cidr": "192.168.20.0/24",
+        "vfw_int_unprotected_private_ip_0": "192.168.10.100",
+        "vfw_int_protected_private_floating_ip": "192.168.10.200",
+        "vfw_int_protected_private_ip_0": "192.168.20.100",
+        "vfw_onap_private_ip_0": "${GLOBAL_INJECTED_OPENSTACK_OAM_NETWORK_CIDR_PREFIX}.${ecompnet}.101",
+        "vsn_int_protected_private_ip_0": "192.168.20.250",
+        "vsn_onap_private_ip_0": "${GLOBAL_INJECTED_OPENSTACK_OAM_NETWORK_CIDR_PREFIX}.${ecompnet}.102",
+        "vfw_name_0": "vofwl01fwl${hostid}",
+        "vsn_name_0": "vofwl01snk${hostid}",
+        "vfw_image_name": "${GLOBAL_INJECTED_DANOS_VES_IMAGE}",
+        "vfw_flavor_name": "${GLOBAL_INJECTED_DANOS_VES_FLAVOR}",
+        "vsn_image_name": "${GLOBAL_INJECTED_UBUNTU_1404_IMAGE}",
+        "vsn_flavor_name": "${GLOBAL_INJECTED_VM_FLAVOR}"
+    },
+    "vpkg_preload.template": {
+        "unprotected_private_net_id": "vFWSNK_vofwlsnk_unprotected${hostid}",
+        "unprotected_private_subnet_id": "vFWSNK_vofwlsnk_unprotected_sub${hostid}",
+        "unprotected_private_net_cidr": "192.168.10.0/24",
+        "protected_private_net_cidr": "192.168.20.0/24",
+        "vfw_private_ip_0": "192.168.10.100",
+        "vpg_unprotected_private_ip_0": "192.168.10.200",
+        "vpg_onap_private_ip_0": "${GLOBAL_INJECTED_OPENSTACK_OAM_NETWORK_CIDR_PREFIX}.${ecompnet}.103",
+        "vsn_private_ip_0": "192.168.20.250",
+        "vpg_name_0": "vofwl01pgn${hostid}",
+        "vpg_image_name": "${GLOBAL_INJECTED_UBUNTU_1404_IMAGE}",
+        "vpg_flavor_name": "${GLOBAL_INJECTED_VM_FLAVOR}"
+    }
+}
diff --git a/service_mapping/vFWCLDN/service_mapping.json b/service_mapping/vFWCLDN/service_mapping.json
new file mode 100644 (file)
index 0000000..28b52c1
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "GLOBAL_SERVICE_FOLDER_MAPPING": {
+        "vFWCLDN": [
+            "vFWCLDN/vFWSNK",
+            "vFWCLDN/vPKG"
+        ]
+    },
+    "GLOBAL_SERVICE_VNF_MAPPING": {
+        "vFWCLDN": [
+            "vFWCLDNvFWSNK",
+            "vFWCLDNvPKG"
+        ]
+    },
+    "GLOBAL_SERVICE_GEN_NEUTRON_NETWORK_MAPPING": {
+        "vFWCLDN": []
+    },
+    "GLOBAL_SERVICE_DEPLOYMENT_ARTIFACT_MAPPING": {
+        "vFWCLDN": []
+    },
+    "GLOBAL_SERVICE_TEMPLATE_MAPPING": {
+        "vFWCLDNvFWSNK": [
+            {
+                "isBase": "true",
+                "template": "vfwsnk_preload.template",
+                "vnf_index": "0",
+                "name_pattern": "base_vfw"
+            }
+        ],
+        "vFWCLDNvPKG": [
+            {
+                "isBase": "true",
+                "template": "vpkg_preload.template",
+                "vnf_index": "1",
+                "name_pattern": "base_vpkg"
+            }
+        ]
+    },
+    "GLOBAL_VALIDATE_NAME_MAPPING": {
+        "vFWCLDNvFWSNK": "vfw_name_0",
+        "vFWCLDNvPKG": "vpg_name_0"
+    }
+}
diff --git a/service_mapping/vFWCL_DANOS/service_mapping.json b/service_mapping/vFWCL_DANOS/service_mapping.json
new file mode 100644 (file)
index 0000000..b5d27fb
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "GLOBAL_SERVICE_FOLDER_MAPPING": {
+        "vFWCL_DANOS": [
+            "vFWCL_DANOS/vFWSNK",
+            "vFWCL_DANOS/vPKG"
+        ]
+    },
+    "GLOBAL_SERVICE_VNF_MAPPING": {
+        "vFWCL_DANOS": [
+            "vFWCL_DANOSvFWSNK",
+            "vFWCL_DANOSvPKG"
+        ]
+    },
+    "GLOBAL_SERVICE_GEN_NEUTRON_NETWORK_MAPPING": {
+        "vFWCL_DANOS": []
+    },
+    "GLOBAL_SERVICE_DEPLOYMENT_ARTIFACT_MAPPING": {
+        "vFWCL_DANOS": []
+    },
+    "GLOBAL_SERVICE_TEMPLATE_MAPPING": {
+        "vFWCL_DANOSvFWSNK": [
+            {
+                "isBase": "true",
+                "template": "vfwsnk_preload.template",
+                "vnf_index": "0",
+                "name_pattern": "base_vfw"
+            }
+        ],
+        "vFWCL_DANOSvPKG": [
+            {
+                "isBase": "true",
+                "template": "vpkg_preload.template",
+                "vnf_index": "1",
+                "name_pattern": "base_vpkg"
+            }
+        ]
+    },
+    "GLOBAL_VALIDATE_NAME_MAPPING": {
+        "vFWCL_DANOSvFWSNK": "vfw_name_0",
+        "vFWCL_DANOSvPKG": "vpg_name_0"
+    }
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/DANOS_BUILD.md b/vnfs/VESreporting_vFW5.0_DANOS/DANOS_BUILD.md
new file mode 100644 (file)
index 0000000..1fd6d1c
--- /dev/null
@@ -0,0 +1,61 @@
+
+A version of DANOS with the VES reporting client will be made available for download and uploading into your glance repository.
+      wget http:// .....  danos-1908-amd64-vrouter_20200425T1203-amd64.hybrid.iso
+
+Remember that a flavor for DANOS must be available in your openstack instance for 4 vcpu, 4096 MB, 8 GB since the standard 
+ubuntu flavors used for most ONAP VNF demonstrations are not the right size.
+
+
+The following instructions were used to build the custom version and can be used as well.
+
+1. Install the DANOS package build tool
+     apt install docker.io
+     git clone https://github.com/jsouthworth/danos-buildpackage
+     cd danos-buildpackage
+     go install jsouthworth.net/go/danos-buildimage/cmd/danos-buildpackage
+
+2. Change to the directory above debian 
+     cd ~/demo/vnfs/VESreporting_vFW5.0_DANOS
+
+3. Build ves library and create debian package
+
+     danos-buildpackage -version 1908
+
+     vpp-measurement-reporter-danos_0.1_amd64.deb will be created in the ~/demo/vnfs directory (..) 
+
+4. Confirm the debian package has the libevel.so and vpp_measurement_reporter_danos executables
+
+     dpkg-deb -c  vpp-measurement-reporter-danos_0.1_amd64.deb
+
+5. Create a DANOS ISO with the addition of the VES debian
+           a. Follow steps in https://danosproject.atlassian.net/wiki/spaces/DAN/pages/491554/Creating+a+DANOS+ISO+using+binary+packages
+          b. At the step:   "If any additional packages are required to be added to the DANOS image:"
+                      mkdir -p config/packages.chroot/
+                      cp  <path-to-deb>/vpp-measurement-reporter-danos_0.1_amd64.deb  config/packages.chroot/
+
+           c. Since this is a new debian for the iso  you need to add the reference to it under config/package-lists
+                      cd config/package-lists
+                      create a file:
+                               vpp-measurement-reporter-danos.list.chroot
+                      add the line to the file:
+                               vpp-measurement-reporter-danos
+           c. continue the steps include:
+                 sed -i 's/--.*distribution .*\\/--distribution '"stretch"' \\/' auto/config
+                auto/clean
+                 auto/config
+                 auto/build
+
+           d. an iso image should be built like:
+                   danos-1908-amd64-vrouter_20200425T1203-amd64.hybrid.iso
+
+
+
+6. Follow the instructions up through Step K. for installing a DANOS ISO in Openstack from 
+         https://danosproject.atlassian.net/wiki/spaces/DAN/pages/79560705/Creating+a+DANOS+Virtual+Router+VNF+in+Openstack
+
+         
+Ignore the creation of the DANOS intance from the new glance image and the traffic source and traffic sink parts since the heat template for ONAP will cover those pieces.
+         
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/LICENSE.TXT b/vnfs/VESreporting_vFW5.0_DANOS/LICENSE.TXT
new file mode 100644 (file)
index 0000000..16285cd
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP is trademark and service mark of AT&T Intellectual Property.
+ *
+ */
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/Makefile b/vnfs/VESreporting_vFW5.0_DANOS/Makefile
new file mode 100644 (file)
index 0000000..160c026
--- /dev/null
@@ -0,0 +1,54 @@
+#############################################################################
+#
+# 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.
+#
+#############################################################################
+
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+MACHINE_ARCH=$(shell uname -m)
+CODE_ROOT=$(CURDIR)
+LIBS_DIR=$(CODE_ROOT)/evel/evel-library/libs/$(MACHINE_ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/evel/evel-library/code/evel_library
+EVEL_CODE_PATH=${CODE_ROOT}/evel/evel-library/code/evel_library/
+EVEL_BUILD_PATH=${CODE_ROOT}/evel/evel-library/bldjobs
+
+#******************************************************************************
+# Standard compiler flags.                                                    *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all:   evel \
+       vpp-measurement-reporter-danos
+
+clean:
+       rm -f vpp-measurement-reporter-danos
+
+vpp-measurement-reporter-danos:        evel vpp-measurement-reporter-danos.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -o vpp-measurement-reporter-danos \
+                                    -L $(LIBS_DIR) \
+                                    -I $(INCLUDE_DIR) \
+                               vpp-measurement-reporter-danos.c \
+                              -lpthread \
+                              -level \
+                              -ljansson \
+                             -lvyatta-config \
+                              -lcurl
+       ls -l /build/src/evel/evel-library/libs/x86_64/
+
+evel:  ${EVEL_CODE_PATH}/evel.c
+       ${MAKE} -C ${EVEL_BUILD_PATH}  all
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/README.md b/vnfs/VESreporting_vFW5.0_DANOS/README.md
new file mode 100644 (file)
index 0000000..b72aef7
--- /dev/null
@@ -0,0 +1,42 @@
+
+PROJECT DESCRIPTION
+---
+This project is a port of the VES event library and reporting client to run on DANOS,  an open source virtual router. DANOS has an embedded stateless firewall that can be used to demonstrate ONAP closed loop control as an alternative to the rudimentary demonstration VNF we have with the original ONAP vFW. As a real VNF , DANOS has features that we can use for better demonstrations of ONAP capability over time so making it easier to do ONAP demosntrations with a real VNF will be beneficial.
+
+The project is meant to be used to build a customer ISO of DANOS with ves/libevel integrated into the build and then that ISO can be used to generate a glance image for ONAP testing.
+
+The project will be both the ONAP source code for the VES event reporting and the instructions on how to crate the DANOS image that could be used in a glance repository.
+
+Heat templates , environment files , preload data and service mapping will be in the normal sections of the repository for those things (demo/vnfs)
+
+Generaly after downloading this directoy you will use the DANOS package build tools to run make which will create the debian file for inclusing in a DANO ISO build.
+
+See  DANOS_BUILD.md  for details.
+
+This project contains the source code and scripts for the periodic generation of network measurement reports for the DANOS virtual router with embeded firewall. It calls the DANOS API's to pull statistics for the ONAP vFW closed loop use case and could be extended for more statistics as needed. The project also includes a systemd start script to be compatible with the DANOS run time environment. The important part of the folder are:
+
+ - README.md: this file.
+
+ - LICENSE.TXT: the license text.
+
+ - vpp_measurement_reporter_danos.c: source code that uses the ECOMP Vendor Event Listener Library (VES) to read metrics from the network interface and send periodic measurement reports to the VES collector in DCAE. The VES library used here has been cloned from the GitHub repository at https://github.com/att/evel-library on February 1, 2017.
+
+ - evel/*  source code for the Event Library that needs to be built with the vpp_measurement_reporter_danos as a shared library and included in the debian install
+
+ - debian/* debian package mandaatory files reqiured to specify the control and rules needed to build the vpp_measurement_report_danos debian file.
+
+ - Makefile: makefile that compiles libevel, vpp_measurement_reporter_danos.c and generates vpp_measurement_reporter binary.
+
+
+USAGE
+---
+
+vpp_measurement_report_danos can be started via systemctl once the DANOS Virtual Machine is instantiated.
+
+
+CONFIGURATION
+---
+Consult the onap wiki for instructions on how to use netconf to configuration the DANOS router for the vFWCL use case.
+
+[fill in url to page on wiki.onap.org ]
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/dcae_collector.env b/vnfs/VESreporting_vFW5.0_DANOS/dcae_collector.env
new file mode 100644 (file)
index 0000000..597a047
--- /dev/null
@@ -0,0 +1,6 @@
+# either onap k8 dns name or k8 host external IP
+DCAE_COLLECTOR_IP=10.1.0.4
+#  DCAE_COLLECTOR_PORT 8443 or 30417 for externa nodeport
+DCAE_COLLECTOR_PORT=30417
+#  dp0s4 for standard configuration for unprotected network from png to fw
+PORT_TO_REPORT=dp0s4
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/changelog b/vnfs/VESreporting_vFW5.0_DANOS/debian/changelog
new file mode 100644 (file)
index 0000000..8870dcb
--- /dev/null
@@ -0,0 +1,5 @@
+vpp-measurement-reporter-danos (0.1) unstable;  urgency=medium
+
+  * Initial create
+
+ -- Brian Freeman <bf1936@att.com>  Tue, 21 Apr 2020 10:57:54 +0000
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/compat b/vnfs/VESreporting_vFW5.0_DANOS/debian/compat
new file mode 100644 (file)
index 0000000..ec63514
--- /dev/null
@@ -0,0 +1 @@
+9
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/control b/vnfs/VESreporting_vFW5.0_DANOS/debian/control
new file mode 100644 (file)
index 0000000..0b28473
--- /dev/null
@@ -0,0 +1,20 @@
+Source: vpp-measurement-reporter-danos
+Section: contrib/net
+Priority: optional
+Maintainer: Brian Freeman <bf1936@att.com>
+Build-depends:
+ debhelper (>= 9),
+ dh-exec,
+ libvyatta-cfg-dev,
+ libcurl4-dev,
+ libjansson-dev,
+Standards-Version: 3.9.8
+
+Package: vpp-measurement-reporter-danos
+Architecture: any
+Depends: ${misc:Depends}, dh-exec, libvyatta-cfg1, ${shlibs:Depends}
+Pre-Depends: ${misc:Pre-Depends}
+Multi-Arch: same
+Description: ONAP VES Event Library for vFW Closed Loop Demonstration 
+ VES reporting library 
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/copyright b/vnfs/VESreporting_vFW5.0_DANOS/debian/copyright
new file mode 100644 (file)
index 0000000..83ac772
--- /dev/null
@@ -0,0 +1,19 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+
+Files: *
+Copyright: 2018-2020, AT&T Intellectual Property.
+License: Apache-2.0
+ 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.
+ .
+ On Debian systems, the complete text of the Apache version 2.0 license
+ can be found in "/usr/share/common-licenses/Apache-2.0".
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/rules b/vnfs/VESreporting_vFW5.0_DANOS/debian/rules
new file mode 100755 (executable)
index 0000000..1bd1ef4
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+DH_VERBOSE =  1
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+%:
+       dh $@ --with=systemd
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/source/format b/vnfs/VESreporting_vFW5.0_DANOS/debian/source/format
new file mode 100644 (file)
index 0000000..89ae9db
--- /dev/null
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/vpp-measurement-reporter-danos.install b/vnfs/VESreporting_vFW5.0_DANOS/debian/vpp-measurement-reporter-danos.install
new file mode 100755 (executable)
index 0000000..0d81653
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/dh-exec
+dcae_collector.env    run/VES/
+evel/evel-library/libs/x86_64/libevel.so  usr/lib/${DEB_HOST_MULTIARCH}
+onap-ca.crt  opt/VES/config
+vpp-measurement-reporter-danos opt/VES/bin/
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/debian/vpp-measurement-reporter-danos.service b/vnfs/VESreporting_vFW5.0_DANOS/debian/vpp-measurement-reporter-danos.service
new file mode 100644 (file)
index 0000000..7d5b0ba
--- /dev/null
@@ -0,0 +1,10 @@
+[Unit]
+Description=ONAP VES Reporting
+
+[Service]
+EnvironmentFile=/run/VES/dcae_collector.env
+ExecStart=/opt/VES/bin/vpp-measurement-reporter-danos   $DCAE_COLLECTOR_IP  $DCAE_COLLECTOR_PORT  $PORT_TO_REPORT
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/dep.xml b/vnfs/VESreporting_vFW5.0_DANOS/dep.xml
new file mode 100644 (file)
index 0000000..fb76f21
--- /dev/null
@@ -0,0 +1,35 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+  <id>demo</id>
+  <formats>
+    <format>tar.gz</format>
+  </formats>
+  <fileSets>
+    <fileSet>
+      <directory>.</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>*.sh</include>
+       <include>*.md</include>
+       <include>*.TXT</include>
+       <include>*.c</include>
+       <include>*.crt</include>
+       <include>evel/**</include>
+       <include>debian/*</include>
+       <include>debian/format/*</include>
+       <include>Makefile</include>
+      </includes>
+      <excludes>
+       <exclude>*.o</exclude>
+       <exclude>**/*.o</exclude>
+       <exclude>**/*.tgz</exclude>
+       <exclude>**/*.a</exclude>
+       <exclude>**/*.so</exclude>
+      </excludes>
+
+    </fileSet>
+  </fileSets>
+</assembly>
+
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/LICENSE.TXT b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/LICENSE.TXT
new file mode 100644 (file)
index 0000000..31f2520
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP are trademark and service mark of AT&T Intellectual Property.
+ *
+ */
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/bldjobs/Makefile b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/bldjobs/Makefile
new file mode 100644 (file)
index 0000000..09ae2eb
--- /dev/null
@@ -0,0 +1,297 @@
+#*************************************************************************//**
+#*
+#* 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.
+#*
+#****************************************************************************/
+
+#******************************************************************************
+# The ECOMP Vendor Event Listener (EVEL) API client library Makefile.
+#
+# Make the various targets associated with housekeeping functions as part of
+# Event Reporting library.
+#
+# NOTE: because Makefiles assign special meaning to the TAB character you
+#       will need to set tabstops to 2 characters for the layout to look OK.
+#****************************************************************************/
+
+ARCH=$(shell getconf LONG_BIT)
+MACHINE_ARCH=$(shell uname -m)
+CODE_ROOT=$(CURDIR)/..
+EVELLIB_ROOT=$(CODE_ROOT)/code/evel_library
+EVELUNIT_ROOT=$(CODE_ROOT)/code/evel_unit
+EVELTRAINING_ROOT=$(CODE_ROOT)/code
+LIBS_DIR=$(CODE_ROOT)/libs/$(MACHINE_ARCH)
+OUTPUT_DIR=$(CODE_ROOT)/output/$(MACHINE_ARCH)
+DOCS_ROOT=$(CODE_ROOT)/docs
+CC=gcc
+SCP=scp
+SSH=ssh
+JAVA=java
+DOXYGEN=doxygen
+PLANTUML=/usr/local/bin/plantuml.jar
+PLANTFLAGS=-tsvg
+
+#******************************************************************************
+# Standard compiler flags.                                                    *
+#******************************************************************************
+CPPFLAGS=-I $(EVELLIB_ROOT)
+ifeq ($(MACHINE_ARCH), aarch64)
+       CFLAGS=-Wall -Wextra -march=native -g -fPIC
+       LIBCFLAGS=-Wall -Wextra -march=native -g -shared -fPIC
+else
+       CFLAGS=-Wall -Wextra -m$(ARCH) -g -fPIC
+       LIBCFLAGS=-Wall -Wextra -m$(ARCH) -g -shared -fPIC
+endif
+
+#******************************************************************************
+# The testbed is a VM instance where we can install the EVEL example under    *
+# CentOS.                                                                     *
+#******************************************************************************
+VNF_TESTBED_CENTOS=172.18.152.180
+VNF_TESTBED_CENTOS_USER=centos
+TESTBED_CENTOS_DOWNLOAD_PATH=/home/centos/download/evel_lib
+TESTBED_CENTOS_INSTALL_PATH=/home/centos/evel
+
+#******************************************************************************
+# The testbed is a VM instance where we can install the EVEL example under    *
+# Ubuntu.                                                                     *
+#******************************************************************************
+VNF_TESTBED_UBUNTU=172.18.152.179
+VNF_TESTBED_UBUNTU_USER=ubuntu
+TESTBED_UBUNTU_DOWNLOAD_PATH=/home/ubuntu/Downloads/evel_lib
+TESTBED_UBUNTU_INSTALL_PATH=/home/ubuntu/evel
+
+#******************************************************************************
+# The test-collector is where we can send events to be consumed and checked   *
+# during tests.                                                               *
+#******************************************************************************
+VNF_COLLECTOR_HOST=172.18.152.185
+VNF_COLLECTOR_PORT=30000
+
+#******************************************************************************
+# A documentation server used by the team where we can install documentation. *
+#******************************************************************************
+TEAM_DOCS_SERVER=covlx8
+DOCS_SERVER_PATH=/var/www/html/evel
+
+#******************************************************************************
+# Implicit rule to make dependency files.  Recipe copied from Gnu docs at:    *
+# https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html *
+#******************************************************************************
+%.d: %.c
+       @echo Making dependency file $(notdir $@) for $(notdir $<)
+       @set -e; rm -f $@; \
+         $(CC) -MM -MT $(<:.c=.o) $(CPPFLAGS) $< > $@.$$$$; \
+         sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+         rm -f $@.$$$$
+
+#******************************************************************************
+# Implicit rule to make object files.                                         *
+#******************************************************************************
+%.o: %.c
+       @echo Making $(notdir $@) from $(notdir $<)
+       @$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+#******************************************************************************
+# Implicit rule to make diagram files using PlantUML.                         *
+#******************************************************************************
+%.svg : %.plantuml
+       @echo Making $(notdir $@)
+       $(JAVA) -jar $(PLANTUML) $(PLANTFLAGS) $<
+
+api:     api_library
+
+all:     api_library 
+
+clean:   api_library_clean \
+         evel_unit_clean
+
+install: evel_install_centos evel_install_ubuntu
+
+test: evel_test_centos evel_test_ubuntu
+
+docs:    docs_clean doxygen_docs
+
+
+#******************************************************************************
+# Build the EVEL libraries.                                                   *
+#******************************************************************************
+API_SOURCES=$(EVELLIB_ROOT)/evel.c \
+            $(EVELLIB_ROOT)/metadata.c \
+            $(EVELLIB_ROOT)/ring_buffer.c \
+            $(EVELLIB_ROOT)/double_list.c \
+            $(EVELLIB_ROOT)/hashtable.c \
+            $(EVELLIB_ROOT)/evel_event.c \
+            $(EVELLIB_ROOT)/evel_fault.c \
+            $(EVELLIB_ROOT)/evel_mobile_flow.c \
+            $(EVELLIB_ROOT)/evel_option.c \
+            $(EVELLIB_ROOT)/evel_jsonobject.c \
+            $(EVELLIB_ROOT)/evel_other.c \
+            $(EVELLIB_ROOT)/evel_json_buffer.c \
+            $(EVELLIB_ROOT)/evel_reporting_measurement.c \
+            $(EVELLIB_ROOT)/evel_heartbeat_fields.c \
+            $(EVELLIB_ROOT)/evel_sipsignaling.c \
+            $(EVELLIB_ROOT)/evel_scaling_measurement.c \
+            $(EVELLIB_ROOT)/evel_state_change.c \
+            $(EVELLIB_ROOT)/evel_strings.c \
+            $(EVELLIB_ROOT)/evel_syslog.c \
+            $(EVELLIB_ROOT)/evel_throttle.c \
+            $(EVELLIB_ROOT)/evel_internal_event.c \
+            $(EVELLIB_ROOT)/evel_event_mgr.c \
+            $(EVELLIB_ROOT)/evel_threshold_cross.c \
+            $(EVELLIB_ROOT)/evel_voicequality.c \
+            $(EVELLIB_ROOT)/evel_logging.c \
+            $(EVELLIB_ROOT)/evel_batch.c \
+            $(EVELLIB_ROOT)/jsmn.c
+API_OBJECTS=$(API_SOURCES:.c=.o)
+-include $(API_SOURCES:.c=.d)
+
+api_library: $(LIBS_DIR)/libevel.so \
+             $(LIBS_DIR)/libevel.a
+
+$(LIBS_DIR)/libevel.a: $(API_OBJECTS)
+       @echo   Linking API Static Library
+       @$(CC) $(LIBCFLAGS) -o $@ $+
+
+$(LIBS_DIR)/libevel.so: $(API_OBJECTS)
+       @echo   Linking API Shared Library
+       @$(CC) $(LIBCFLAGS) -L $(QLIBCLIBSDIR) -lqlibc -o $@ $+
+
+api_library_clean:
+       @echo   Cleaning API Library
+       @$(RM) $(LIBS_DIR)/libevel.so
+       @$(RM) $(API_OBJECTS)
+       @$(RM) $(EVELLIB_ROOT)/*.d
+
+#******************************************************************************
+# Build the EVEL library unit test.                                           *
+#******************************************************************************
+UNIT_SOURCES=$(EVELUNIT_ROOT)/evel_unit.c
+UNIT_OBJECTS=$(UNIT_SOURCES:.c=.o)
+-include $(UNIT_SOURCES:.c=.d)
+
+evel_unit: api_library \
+           $(OUTPUT_DIR)/evel_unit
+
+$(OUTPUT_DIR)/evel_unit: $(UNIT_OBJECTS)
+       @echo   Linking EVEL unit test
+       $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ \
+                          -L $(LIBS_DIR) \
+                          $(UNIT_OBJECTS) \
+                          -level \
+                          -lpthread \
+                          -lcurl
+
+evel_unit_clean:
+       @echo   Cleaning EVEL unit test
+       @$(RM) $(OUTPUT_DIR)/evel_unit
+       @$(RM) $(API_OBJECTS)
+       @$(RM) $(UNIT_OBJECTS)
+       @$(RM) $(EVELLIB_ROOT)/*.d
+       @$(RM) $(EVELUNIT_ROOT)/*.d
+
+
+#******************************************************************************
+# Copy the EVEL demo onto the CentOS testbed as a package and build it.       *
+#******************************************************************************
+evel_install_centos: delivery
+       @echo Installing EVEL library on CentOS testbed...
+       @$(SSH) $(VNF_TESTBED_CENTOS_USER)@$(VNF_TESTBED_CENTOS) \
+          rm -rf $(TESTBED_CENTOS_DOWNLOAD_PATH) \; \
+          mkdir -p $(TESTBED_CENTOS_DOWNLOAD_PATH) \; \
+          mkdir -p $(TESTBED_CENTOS_INSTALL_PATH)
+       @$(SCP) -r $(CODE_ROOT)/output/evel-library-package.tgz \
+           $(VNF_TESTBED_CENTOS_USER)@$(VNF_TESTBED_CENTOS):$(TESTBED_CENTOS_DOWNLOAD_PATH)
+       @$(SSH) $(VNF_TESTBED_CENTOS_USER)@$(VNF_TESTBED_CENTOS) \
+          tar zx --directory $(TESTBED_CENTOS_INSTALL_PATH) \
+                 --file $(TESTBED_CENTOS_DOWNLOAD_PATH)/evel-library-package.tgz
+       @echo Making EVEL library on testbed...
+       @$(SSH) $(VNF_TESTBED_CENTOS_USER)@$(VNF_TESTBED_CENTOS) \
+           cd $(TESTBED_CENTOS_INSTALL_PATH)/bldjobs \; \
+           make clean all
+
+#******************************************************************************
+# Copy the EVEL demo onto the Ubuntu testbed as a package and build it.       *
+#******************************************************************************
+evel_install_ubuntu: delivery
+       @echo Installing EVEL library on Ubuntu testbed...
+       @$(SSH) $(VNF_TESTBED_UBUNTU_USER)@$(VNF_TESTBED_UBUNTU) \
+          rm -rf $(TESTBED_UBUNTU_DOWNLOAD_PATH) \; \
+          mkdir -p $(TESTBED_UBUNTU_DOWNLOAD_PATH) \; \
+          mkdir -p $(TESTBED_UBUNTU_INSTALL_PATH)
+       @$(SCP) -r $(CODE_ROOT)/output/evel-library-package.tgz \
+           $(VNF_TESTBED_UBUNTU_USER)@$(VNF_TESTBED_UBUNTU):$(TESTBED_UBUNTU_DOWNLOAD_PATH)
+       @$(SSH) $(VNF_TESTBED_UBUNTU_USER)@$(VNF_TESTBED_UBUNTU) \
+          tar zx --directory $(TESTBED_UBUNTU_INSTALL_PATH) \
+                 --file $(TESTBED_UBUNTU_DOWNLOAD_PATH)/evel-library-package.tgz
+       @echo Making EVEL library on testbed...
+       @$(SSH) $(VNF_TESTBED_UBUNTU_USER)@$(VNF_TESTBED_UBUNTU) \
+           cd $(TESTBED_UBUNTU_INSTALL_PATH)/bldjobs \; \
+           make clean all
+
+#******************************************************************************
+# Make sure that the Centos platform is up to date and then run the software  *
+# against a test collector.  Validating correct operation is not presently    *
+# automated.                                                                  *
+#******************************************************************************
+evel_test_centos: evel_install_centos
+       @echo Testing EVEL Demo application on CentOS...
+       @$(SSH) $(VNF_TESTBED_CENTOS_USER)@$(VNF_TESTBED_CENTOS) \
+           source .bash_profile \; \
+           $(TESTBED_CENTOS_INSTALL_PATH)/output/$(MACHINE_ARCH)/evel_demo \
+                                                 --fqdn $(VNF_COLLECTOR_HOST) \
+                                                 --port $(VNF_COLLECTOR_PORT) \
+                                                 --verbose
+
+#******************************************************************************
+# Make sure that the Ubuntu platform is up to date and then run the software  *
+# against a test collector.  Validating correct operation is not presently    *
+# automated.                                                                  *
+#******************************************************************************
+evel_test_ubuntu: evel_install_ubuntu
+       @echo Testing EVEL Demo application on Ubuntu...
+       @$(SSH) $(VNF_TESTBED_UBUNTU_USER)@$(VNF_TESTBED_UBUNTU) \
+           source .profile \; \
+           $(TESTBED_UBUNTU_INSTALL_PATH)/output/$(MACHINE_ARCH)/evel_demo \
+                                                 --fqdn $(VNF_COLLECTOR_HOST) \
+                                                 --port $(VNF_COLLECTOR_PORT) \
+                                                 --verbose
+
+#******************************************************************************
+# Making a clean delivery has some very specific dependencies which are order *
+# dependent, so we recursively make a series of targets to do a clean  build  *
+# of all of the required deliverables and then finally zipping up.            *
+#******************************************************************************
+delivery:
+       @$(MAKE) -s delivery_baseline
+       @$(MAKE) -s package
+
+delivery_baseline:     docs
+
+#******************************************************************************
+# Package the software for delivery.                                          *
+#******************************************************************************
+package: api_library_clean \
+         evel_unit_clean
+       @echo Packaging the software for delivery
+       @cd $(CODE_ROOT) && tar cfz output/evel-library-package.tgz  bldjobs \
+                                                      code \
+                                                      docs \
+                                                      libs/$(MACHINE_ARCH)/README \
+                                                      output/$(MACHINE_ARCH)/README \
+                                                      readme.md
+
+package_clean:
+       @echo Clean delivery packages
+       @$(RM) $(OUTPUTDIR)/*.tgz
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/double_list.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/double_list.c
new file mode 100644 (file)
index 0000000..cd171bc
--- /dev/null
@@ -0,0 +1,184 @@
+
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ *
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/double_list.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/double_list.h
new file mode 100644 (file)
index 0000000..5cf7e1a
--- /dev/null
@@ -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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel.c
new file mode 100644 (file)
index 0000000..fbe3de4
--- /dev/null
@@ -0,0 +1,518 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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   bakup_fqdn    The API's Backup FQDN or IP address.
+ * @param   bakup_port    The API's Backup port.
+ * @param   path    The optional path (may be NULL).
+ * @param   topic   The optional topic part of the URL (may be NULL).
+ * @param   ring buf size  Ring buffer size
+ * @param   secure  Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param   cert_file_path     Path to client certificate file
+ * @param   key_file_path      Path to client key file
+ * @param   ca_info            Path to CA cert file
+ * @param   ca_file_path       Path to CA cert files
+ * @param   verify_peer        SSL verification of peer 0 or 1
+ * @param   verify_host        SSL verification of host 0 or 1
+ * @param   username  Username for Basic Authentication of requests.
+ * @param   password  Password for Basic Authentication of requests.
+ * @param   bakup_username  Username for Basic Authentication of Bakup FQDN.
+ * @param   bakup_password  Password for Basic Authentication of Bakup FQDN.
+ * @param   source_ip       The ip of node we represent.(NULL for default ip)
+ * @param   bakup_source_ip The ip bakup fqdn interface.(NULL for default ip)
+ * @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 bakup_fqdn,
+                               int bakup_port,
+                               const char * const path,
+                               const char * const topic,
+                               int ring_buf_size,
+                               int secure,
+                               const char * const cert_file_path,
+                               const char * const key_file_path,
+                               const char * const ca_info,
+                               const char * const ca_file_path,
+                               long verify_peer,
+                               long verify_host,
+                               const char * const username,
+                               const char * const password,
+                               const char * const bakup_username,
+                               const char * const bakup_password,
+                               const char * const source_ip,
+                               const char * const bakup_source_ip,
+                               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 bakup_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;
+  char * bakup_coll = NULL;
+
+  /***************************************************************************/
+  /* Check assumptions.                                                      */
+  /***************************************************************************/
+  assert(fqdn != NULL);
+  assert(port > 0 && port <= 65535);
+  assert(source_type < EVEL_MAX_SOURCE_TYPES);
+  assert(role != NULL);
+
+  if( bakup_fqdn != NULL ) {
+    assert(bakup_port > 0 && bakup_port <= 65535);
+  }
+
+  /***************************************************************************/
+  /* Start logging so we can report on progress.                             */
+  /***************************************************************************/
+  if( verbosity >= EVEL_LOG_MIN && verbosity <= EVEL_LOG_MAX)
+     log_initialize(verbosity, "EVEL");
+  else
+     log_initialize(EVEL_LOG_MIN, "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");
+  if( secure ) {
+    assert( verify_peer >= 0 );
+    assert( verify_host >= 0 );
+    if (cert_file_path != NULL)
+    {
+      EVEL_INFO("Client cert is: %s", cert_file_path);
+    }
+    else
+    {
+      EVEL_INFO("No Client cert");
+    }
+    if (key_file_path != NULL)
+    {
+      EVEL_INFO("Key file is: %s", key_file_path);
+    }
+    else
+    {
+      EVEL_INFO("No Key file");
+    }
+    if (ca_file_path != NULL)
+    {
+      EVEL_INFO("Client CA certs path is: %s", ca_file_path);
+    }
+    else
+    {
+      EVEL_INFO("No CA certs path");
+    }
+    if (ca_info != NULL)
+    {
+      EVEL_INFO("Client CA cert file is: %s", ca_info);
+    }
+    else
+    {
+      EVEL_INFO("No CA cert file");
+    }
+  }
+  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 a common base of the Backup API URLs.                                    */
+  /***************************************************************************/
+  if( bakup_fqdn != NULL )
+  {
+    strcpy(path_url, "/");
+    snprintf(base_api_url,
+           EVEL_MAX_URL_LEN,
+           "%s://%s:%d%s/eventListener/v%s",
+           secure ? "https" : "http",
+           bakup_fqdn,
+           bakup_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(bakup_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 Backup Event Listener API is located at: %s", bakup_api_url);
+    bakup_coll = bakup_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,
+                                bakup_coll,
+                                throt_api_url,
+                                source_ip,
+                                bakup_source_ip,
+                                ring_buf_size,
+                                secure,
+                                cert_file_path,
+                                key_file_path,
+                                ca_info,
+                                ca_file_path,
+                                verify_peer,
+                                verify_host,
+                                username,
+                                password,
+                                bakup_username,
+                                bakup_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;
+
+    case EVEL_DOMAIN_BATCH:
+      EVEL_DEBUG("Event is a Batch at %lp", evt_ptr);
+      evel_free_batch((EVENT_HEADER *)evt_ptr);
+      memset(evt_ptr, 0, sizeof(EVENT_HEADER));
+      free(evt_ptr);
+      break;
+
+    default:
+      EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);
+      assert(0);
+    }
+  }
+  EVEL_EXIT();
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel.h
new file mode 100644 (file)
index 0000000..8cdc4b5
--- /dev/null
@@ -0,0 +1,4673 @@
+/*************************************************************************//**
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef EVEL_INCLUDED
+#define EVEL_INCLUDED
+
+#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           524288
+#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_BATCH,          /** Batch event, composite event.              */
+  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 3
+#define EVEL_HEADER_MINOR_VERSION 0
+
+#define EVEL_BATCH_MAJOR_VERSION 1
+#define EVEL_BATCH_MINOR_VERSION 0
+/**************************************************************************//**
+ * 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;
+  DLIST batch_events;
+
+} EVENT_HEADER;
+
+/**************************************************************************//**
+ * Initialize a newly created event header.
+ *
+ * @param header  Pointer to the header being initialized.
+ * @param eventname Eventname string
+ * @param eventid   Event id : unique id for classification and analysis
+ * @param header  Pointer to the header being initialized.
+ *****************************************************************************/
+void evel_init_header_nameid(EVENT_HEADER * const header,const char *const eventname, const char *eventid);
+
+/**************************************************************************//**
+ * Create a new Batch event.
+ *
+ * @note    The mandatory fields on the Batch 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
+ *          Batch has immutable properties. At this time evename and eventid
+ *          for batch events are set but not used in json encoding
+ * @returns pointer to the newly manufactured ::EVENT_HEADER.  If the event is
+ *          not used (i.e. posted) it must be released using ::evel_free_batch.
+ * @retval  NULL  Failed to create the event.
+ *****************************************************************************/
+EVENT_HEADER * evel_new_batch(const char* ev_name, const char *ev_id);
+
+
+/**************************************************************************//**
+ * Add an Event into Batch 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 other     Pointer to the Batch Event.
+ * @param jsonobj   Pointer to  additional Event
+ *****************************************************************************/
+void evel_batch_add_event(EVENT_HEADER * batchev, EVENT_HEADER *child);
+
+/**************************************************************************//**
+ * Free an Batch.
+ *
+ * Free off the Batch supplied.  Will free all the contained allocated memory.
+ *
+ * @note It does not free the Batch itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_batch(EVENT_HEADER * event);
+
+/*****************************************************************************/
+/* Supported Fault version.                                                  */
+/*****************************************************************************/
+#define EVEL_FAULT_MAJOR_VERSION 2
+#define EVEL_FAULT_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * 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;
+  EVEL_OPTION_ULL 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 0
+
+/**************************************************************************//**
+ * 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;
+
+
+
+/**************************************************************************//**
+ * 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);
+
+/**************************************************************************//**
+ * 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 measurement     Pointer to the ScalingMeasurement
+ * @param jsonobj   Pointer to json object
+ *****************************************************************************/
+void evel_measurement_addl_object_add(EVENT_MEASUREMENT * measurement, EVEL_JSON_OBJECT *jsonobj);
+
+/**************************************************************************//**
+ * 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 0
+
+/**************************************************************************//**
+ * 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 2
+#define EVEL_MOBILE_FLOW_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * 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 0
+
+/**************************************************************************//**
+ * 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 0
+
+
+/*****************************************************************************/
+/* Supported Signaling version.                                              */
+/*****************************************************************************/
+#define EVEL_SIGNALING_MAJOR_VERSION 1
+#define EVEL_SIGNALING_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * 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 2
+#define EVEL_STATE_CHANGE_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * 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 3
+#define EVEL_SYSLOG_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * 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   bakup_fqdn    The API's FQDN or IP address.
+ * @param   bakup_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   ring_buf_size   Ring buffer size (>=100) ~ Avg Messages in 1hr
+ * @param   secure  Whether to use HTTPS (0=HTTP, 1=HTTPS).
+ * @param   cert_file_path     Path to client certificate file
+ * @param   key_file_path      Path to client key file
+ * @param   ca_info            Path to CA info
+ * @param   ca_file_path       Path to CA file
+ * @param   verify_peer        SSL verification of peer 0 or 1
+ * @param   verify_host        SSL verification of host 0 or 1
+ * @param   username  Username for Basic Authentication of requests.
+ * @param   password  Password for Basic Authentication of requests.
+ * @param   bakup_username  Username for Basic Authentication of Bakup FQDN.
+ * @param   bakup_password  Password for Basic Authentication of Bakup FQDN.
+ * @param   source_ip       The ip of node we represent.(NULL for default ip)
+ * @param   bakup_source_ip The ip bakup fqdn interface.(NULL for default ip)
+ * @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 bakup_fqdn,
+                               int bakup_port,
+                               const char * const path,
+                               const char * const topic,
+                               int ring_buf_size,
+                               int secure,
+                               const char * const cert_file_path,
+                               const char * const key_file_path,
+                               const char * const ca_info,
+                               const char * const ca_file_path,
+                               long verify_peer,
+                               long verify_host,
+                               const char * const username,
+                               const char * const password,
+                               const char * const bakup_username,
+                               const char * const bakup_password,
+                               const char * const source_ip,
+                               const char * const bakup_source_ip,
+                               EVEL_SOURCE_TYPES source_type,
+                               const char * const role,
+                               int verbosity
+                               );
+
+/**************************************************************************//**
+ * Initialize value for vm_name for all coming events
+ * @param  source_name  Source name string.
+ *                      Must confirm with EVEL source name standard
+ * @returns Status code
+ * @retval  EVEL_SUCCESS      On success
+ * @retval  ::EVEL_ERR_CODES  On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_set_source_name(char * src_name);
+
+
+/**************************************************************************//**
+ * 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 mode      Event mode or Batch mode
+ * @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);
+int evel_json_encode_batch_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: {DomainAbbreviation}_{AsdcModel or ApplicationPlatform}_{DescriptionOfInfoBeingConveyed}
+ * @param event_id    A universal identifier of the event for: troubleshooting, cross-referencing of alarms for alarm correlation, offline log 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);
+
+/**************************************************************************//**
+ * 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 ev_name  Unique Event Name confirming Domain AsdcModel Description
+ * @param ev_id    A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @param interval    heartbeat interval
+ * @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);
+
+/**************************************************************************//**
+ * 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 next event_sequence to use.
+ *
+ * @param sequence      The next sequence number to use.
+ *****************************************************************************/
+void evel_set_global_event_sequence(const int sequence);
+
+/**************************************************************************//**
+ * Set the Event Sequence property of the event header.
+ *
+ * @note This is mainly for tracking fault event sequence numbers
+ *
+ * @param header        Pointer to the ::EVENT_HEADER.
+ * @param sequence_number
+ * 
+ *****************************************************************************/
+void evel_event_sequence_set(EVENT_HEADER * const header,const int sequence_number);
+
+/**************************************************************************//**
+ * 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 Source Name property of the event header.
+ *
+ * @note The Source Name defaults to the OpenStack VM Name.
+ *
+ * @param header        Pointer to the ::EVENT_HEADER.
+ * @param entity_name   The source name to set.
+ *****************************************************************************/
+void evel_source_name_set(EVENT_HEADER * const header,
+                          const char * const source_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 Source Id property of the event header.
+ *
+ * @note The Source Id defaults to the OpenStack VM UUID.
+ *
+ * @param header        Pointer to the ::EVENT_HEADER.
+ * @param entity_id     The Source id to set.
+ *****************************************************************************/
+void evel_source_id_set(EVENT_HEADER * const header,
+                        const char * const source_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 0
+
+/**************************************************************************//**
+ * 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 2
+#define EVEL_THRESHOLD_CROSS_MINOR_VERSION 0
+
+/**************************************************************************//**
+ * 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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_batch.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_batch.c
new file mode 100644 (file)
index 0000000..d1877dd
--- /dev/null
@@ -0,0 +1,151 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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 implementing EVEL Batch API.
+ *
+ * This file implements the EVEL Batch API which is intended to provide a
+ * simple wrapper around packaging multiple EVEL messages into single HTTP(S) package
+ * This is implemented per VES 5.3 standards. Currently max size of package is 160K
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Create a new empty Batch event.
+ *
+ * @note    The mandatory fields on the Batch 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
+ *          Batch has immutable properties.
+ * @params  Event name and Event id are dummy strings. Not encoded into JSON
+ * @returns pointer to the newly manufactured ::EVENT_HEADER.  If the event is
+ *          not used (i.e. posted) it must be released using ::evel_free_batch.
+ * @retval  NULL  Failed to create the event.
+ *****************************************************************************/
+EVENT_HEADER * evel_new_batch(const char* ev_name, const char *ev_id)
+{
+  EVENT_HEADER * other = NULL;
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+
+  /***************************************************************************/
+  /* Allocate the Batch.                                                     */
+  /***************************************************************************/
+  other = malloc(sizeof(EVENT_HEADER));
+  if (other == NULL)
+  {
+    log_error_state("Out of memory");
+    goto exit_label;
+  }
+  memset(other, 0, sizeof(EVENT_HEADER));
+  EVEL_DEBUG("New Batch is at %lp", other);
+
+  /***************************************************************************/
+  /* Initialize the header & the Batch fields.  Optional string values are   */
+  /* uninitialized (NULL).                                                   */
+  /***************************************************************************/
+  evel_init_header_nameid(other,ev_name,ev_id);
+  other->event_domain = EVEL_DOMAIN_BATCH;
+  other->major_version = EVEL_BATCH_MAJOR_VERSION;
+  other->minor_version = EVEL_BATCH_MINOR_VERSION;
+
+  dlist_initialize(&other->batch_events);
+
+exit_label:
+  EVEL_EXIT();
+  return other;
+}
+
+
+/**************************************************************************//**
+ * Add an additional VES Message into Batch Event
+ *
+ * The function may be called as many times without reaching 160K max json size
+ * limit.
+ * The max limit is only checked at encoding time and error generated
+ *
+ * @param batchev     Pointer to  already created new Batch Event.
+ * @param child       Pointer to  additional VES Event
+ *****************************************************************************/
+void evel_batch_add_event(EVENT_HEADER * batchev, EVENT_HEADER *child)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(batchev != NULL);
+  assert(batchev->event_domain == EVEL_DOMAIN_BATCH);
+  assert(child != NULL);
+
+  EVEL_DEBUG("Adding Batch event");
+
+  dlist_push_last(&batchev->batch_events, child);
+
+  EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Free a Batch Event.
+ *
+ * Free off the Batch supplied.  Will free all the contained VES message memory.
+ *
+ * @note It does not free the Batch itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_batch(EVENT_HEADER * event)
+{
+  EVENT_HEADER * batch_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->event_domain == EVEL_DOMAIN_BATCH);
+
+  /***************************************************************************/
+  /* Free all internal strings then the header itself.                       */
+  /***************************************************************************/
+  batch_field = dlist_pop_last(&event->batch_events);
+  while (batch_field != NULL)
+  {
+    EVEL_DEBUG("Freeing Batch Event (%s, %s)",
+               batch_field->event_name,
+               batch_field->event_id);
+    evel_free_event(batch_field);
+    batch_field = dlist_pop_last(&event->batch_events);
+  }
+  evel_free_header(event); 
+
+  EVEL_EXIT();
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_event.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_event.c
new file mode 100644 (file)
index 0000000..89c5c15
--- /dev/null
@@ -0,0 +1,932 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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_global_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 = 0;
+  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_init_option_string(&header->reporting_entity_id);
+  evel_init_option_string(&header->source_id);
+  evel_init_option_intheader(&header->internal_field);
+  dlist_initialize(&header->batch_events);
+
+  EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Initialize a newly created event header.
+ *
+ * @param header  Pointer to the header being initialized.
+ * @param eventname Eventname string
+ * @param eventid   Event id : unique id for classification and analysis
+ * @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.  Reset 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 = 0;
+  header->start_epoch_microsec = header->last_epoch_microsec;
+  header->major_version = EVEL_HEADER_MAJOR_VERSION;
+  header->minor_version = EVEL_HEADER_MINOR_VERSION;
+
+  /***************************************************************************/
+  /* Optional parameters.                                                    */
+  /***************************************************************************/
+  evel_init_option_string(&header->event_type);
+  evel_init_option_string(&header->nfcnaming_code);
+  evel_init_option_string(&header->nfnaming_code);
+  evel_init_option_string(&header->reporting_entity_id);
+  evel_init_option_string(&header->source_id);
+  evel_init_option_intheader(&header->internal_field);
+  dlist_initialize(&header->batch_events);
+
+  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 Event Sequence 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_event_sequence_set(EVENT_HEADER * const header,const int sequence_number)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions and assign the new value.                           */
+  /***************************************************************************/
+  assert(header != NULL);
+  header->sequence = sequence_number;
+
+  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 Source Name property of the event header.
+ *
+ * @note The Source Name defaults to the OpenStack VM Name.
+ *
+ * @param header        Pointer to the ::EVENT_HEADER.
+ * @param entity_name   The source name to set.
+ *****************************************************************************/
+void evel_source_name_set(EVENT_HEADER * const header,
+                                    const char * const source_name)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions and assign the new value.                           */
+  /***************************************************************************/
+  assert(header != NULL);
+  assert(source_name != NULL);
+
+  /***************************************************************************/
+  /* Free the previously allocated memory and replace it with a copy of the  */
+  /* provided one.                                                           */
+  /***************************************************************************/
+  free(header->source_name);
+  header->source_name = strdup(source_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();
+}
+
+/**************************************************************************//**
+ * Set the Source Id property of the event header.
+ *
+ * @note The Source Id defaults to the OpenStack VM UUID.
+ *
+ * @param header        Pointer to the ::EVENT_HEADER.
+ * @param entity_id     The Source id to set.
+ *****************************************************************************/
+void evel_source_id_set(EVENT_HEADER * const header,
+                        const char * const source_id)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions and assign the new value.                           */
+  /***************************************************************************/
+  assert(header != NULL);
+  assert(source_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->source_id);
+  evel_force_option_string(&header->source_id, source_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.
+ *****************************************************************************/
+void evel_json_encode_eventtype(
+                          EVEL_JSON_BUFFER * jbuf,
+                           EVENT_HEADER * 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);
+      }
+}
+
+
+
+/**************************************************************************//**
+ * 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");
+
+  evel_json_encode_eventtype(jbuf, event);
+
+  evel_json_close_object(jbuf);
+  evel_json_close_object(jbuf);
+
+  /***************************************************************************/
+  /* Sanity check.                                                           */
+  /***************************************************************************/
+  assert(jbuf->depth == 0);
+  if( jbuf->offset >= max_size ){
+          EVEL_ERROR("Event exceeded size limit %d", max_size);
+          assert(0);
+  }
+
+  EVEL_EXIT();
+
+  return jbuf->offset;
+}
+/**************************************************************************//**
+ * 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_batch_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;
+  int tot_size = 0;
+  EVENT_HEADER * batch_field = NULL;
+  DLIST_ITEM * batch_field_item = NULL;
+
+  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.              */
+  /***************************************************************************/
+  if (event->event_domain == EVEL_DOMAIN_BATCH){
+      evel_json_buffer_init(jbuf, json, max_size, throttle_spec);
+
+  if(dlist_count(&event->batch_events) > 0)
+  {
+    evel_json_open_object(jbuf);
+    evel_json_open_named_list(jbuf, "eventList");
+    batch_field_item = dlist_get_first(&event->batch_events);
+    while (batch_field_item != NULL)
+    {
+     batch_field = (EVENT_HEADER *) batch_field_item->item;
+     if(batch_field != NULL){
+       EVEL_DEBUG("Batch Event %p %p added curr fsize %d offset %d depth %d check %d", batch_field_item->item, batch_field, tot_size,jbuf->offset,jbuf->depth,jbuf->checkpoint);
+       evel_json_open_object(jbuf);
+       evel_json_encode_eventtype(jbuf, batch_field);
+       evel_json_close_object(jbuf);
+
+       tot_size += jbuf->offset;
+       EVEL_DEBUG("Batch Event result size %d offset %d depth %d check %d", tot_size,jbuf->offset,jbuf->depth,jbuf->checkpoint);
+       if( tot_size >= max_size ){
+          EVEL_ERROR("Batch Event exceeded size limit %d", tot_size);
+          assert(0);
+       }
+       batch_field_item = dlist_get_next(batch_field_item);
+     }
+    }
+    evel_json_close_list(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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_event_mgr.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_event_mgr.c
new file mode 100644 (file)
index 0000000..cc676a6
--- /dev/null
@@ -0,0 +1,1664 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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;
+
+/**************************************************************************//**
+ * Wait time if both the collectors are not responding
+ *****************************************************************************/
+static const int EVEL_COLLECTOR_RECONNECTION_WAIT_TIME = 120;
+
+/*****************************************************************************/
+/* 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);
+static EVEL_ERR_CODES evel_setup_curl();
+static EVEL_ERR_CODES evel_send_to_another_collector(const EVEL_EVENT_DOMAINS evel_domain, char * json_body, size_t json_size);
+
+/**************************************************************************//**
+ * 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;
+int curr_global_handles = 0;
+
+/**************************************************************************//**
+ * 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;
+static char * evel_batch_api_url;
+
+static char * evel_bevent_api_url;
+static char * evel_bthrot_api_url;
+static char * evel_bbatch_api_url;
+
+/**************************************************************************//**
+ * Storage for other CURL related parameters
+ *****************************************************************************/
+int evel_secure = -1;
+int evel_verbosity = -1;
+
+long evel_verify_peer = 0;
+long evel_verify_host = 0;
+
+static char * evel_source_ip = NULL;
+static char * evel_source_ip_bakup = NULL;
+static char * evel_cert_file_path = NULL;
+static char * evel_key_file_path = NULL;
+static char * evel_ca_info = NULL;
+static char * evel_ca_file_path = NULL;
+static char * evel_username = NULL;
+static char * evel_password = NULL;
+static char * evel_username2 = NULL;
+static char * evel_password2 = NULL;
+
+static long http_response_code = 0;
+static int evel_collector_id = 1;
+/**************************************************************************//**
+ * 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] source_ip  Source IP of VES Agent
+ * @param[in] ring_buf_size     Initial size of ring buffer
+ * @param[in] secure     Whether Using http or https
+ * @param[in] cert_file_path  Path to Client Certificate file
+ * @param[in] key_file_path   Path to Client key file
+ * @param[in] ca_info         Path to CA info file
+ * @param[in] ca_file_path    Path to CA file 
+ * @param[in] verify_peer     Using peer verification or not 0 or 1
+ * @param[in] verify_host     Using host verification or not 0 or 1
+ * @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 bakup_api_url,
+                                        const char * const throt_api_url,
+                                        const char * const source_ip,
+                                        const char * const source_ip_bakup,
+                                        int ring_buf_size,
+                                        int secure,
+                                        const char * const cert_file_path,
+                                        const char * const key_file_path,
+                                        const char * const ca_info,
+                                        const char * const ca_file_path,
+                                        long verify_peer,
+                                        long verify_host,
+                                        const char * const username,
+                                        const char * const password,
+                                        const char * const username2,
+                                        const char * const password2,
+                                        int verbosity)
+{
+  int rc = EVEL_SUCCESS;
+  char batch_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check assumptions.                                                      */
+  /***************************************************************************/
+  assert(event_api_url != NULL);
+  assert(throt_api_url != NULL);
+  assert(username != NULL);
+  assert(password != NULL);
+  if( bakup_api_url != NULL )
+  {
+    assert(username2 != NULL);
+    assert(password2 != NULL);
+  }
+
+  /***************************************************************************/
+  /* Store the API URLs.                                                     */
+  /***************************************************************************/
+  evel_event_api_url = strdup(event_api_url);
+  assert(evel_event_api_url != NULL);
+  sprintf(batch_api_url,"%s/eventBatch",event_api_url);
+  evel_batch_api_url = strdup(batch_api_url);
+  assert(evel_batch_api_url != NULL);
+  evel_throt_api_url = strdup(throt_api_url);
+  assert(evel_throt_api_url != NULL);
+
+  curr_global_handles = 1;
+
+  if( bakup_api_url != NULL )
+  {
+    evel_bevent_api_url = strdup(bakup_api_url);
+    assert(evel_bevent_api_url != NULL);
+    sprintf(batch_api_url,"%s/eventBatch",bakup_api_url);
+    evel_bbatch_api_url = strdup(batch_api_url);
+    assert(evel_bbatch_api_url != NULL);
+    evel_bthrot_api_url = strdup(throt_api_url);
+    assert(evel_bthrot_api_url != NULL);
+    curr_global_handles = 2;
+  }
+
+  /***************************************************************************/
+  /* Store other parameters                                                  */
+  /***************************************************************************/
+  evel_secure = secure;
+  evel_verbosity = verbosity;
+
+  evel_verify_peer = verify_peer;
+  evel_verify_host = verify_host;
+
+  evel_source_ip = NULL;
+  if (source_ip != NULL)
+  {
+    evel_source_ip = strdup(source_ip);
+    assert(evel_source_ip != NULL);
+  }
+
+  evel_source_ip_bakup = NULL;
+  if (source_ip_bakup != NULL)
+  {
+    evel_source_ip_bakup = strdup(source_ip_bakup);
+    assert(evel_source_ip_bakup != NULL);
+  }
+
+  evel_cert_file_path = NULL;
+  if (cert_file_path != NULL)
+  {
+    evel_cert_file_path = strdup(cert_file_path);
+    assert(evel_cert_file_path != NULL);
+  }
+
+  evel_key_file_path = NULL;
+  if (key_file_path != NULL)
+  {
+    evel_key_file_path = strdup(key_file_path);
+    assert(evel_key_file_path != NULL);
+  }
+
+  evel_ca_info = NULL;
+  if (ca_info != NULL)
+  {
+    evel_ca_info = strdup(ca_info);
+    assert(evel_ca_info != NULL);
+  }
+
+  evel_ca_file_path = NULL;
+  if (ca_file_path != NULL)
+  {
+    evel_ca_file_path = strdup(ca_file_path);
+    assert(evel_ca_file_path != NULL);
+  }
+
+  evel_username = NULL;
+  if (username != NULL)
+  {
+    evel_username = strdup(username);
+    assert(evel_username != NULL);
+  }
+
+  evel_password = NULL;
+  if (password != NULL)
+  {
+    evel_password = strdup(password);
+    assert(evel_password != NULL);
+  }
+
+  evel_username2 = NULL;
+  if (username2 != NULL)
+  {
+    evel_username2 = strdup(username2);
+    assert(evel_username2 != NULL);
+  }
+
+  evel_password2 = NULL;
+  if (password2 != NULL)
+  {
+    evel_password2 = strdup(password2);
+    assert(evel_password2 != 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.");
+  }
+
+  /***************************************************************************/
+  /* Initialize a message ring-buffer to be used between the foreground and  */
+  /* the thread which sends the messages.  This can't fail.                  */
+  /***************************************************************************/
+  if( ring_buf_size < EVEL_EVENT_BUFFER_DEPTH )
+  {
+    log_error_state("Warning: Failed to initialize Ring buffer size to %d. ",
+                    ring_buf_size);
+    goto exit_label;
+  }
+  ring_buffer_initialize(&event_buffer, EVEL_EVENT_BUFFER_DEPTH);
+
+exit_label:
+
+  EVEL_EXIT();
+
+  return rc;
+
+}
+/**************************************************************************//**
+ * Setup the curl connection to collector
+ *
+ * Primarily responsible for getting CURL ready to send message. Also it would
+ * be used to swithch over to other collector 
+ *****************************************************************************/
+static EVEL_ERR_CODES evel_setup_curl()
+{
+  int rc = EVEL_SUCCESS;
+  CURLcode curl_rc = CURLE_OK;
+  char local_address[64];
+  char * api_url = NULL;
+  char * username = NULL;
+  char * password = NULL;
+  char * source_ip = NULL;
+
+  EVEL_ENTER();
+
+  if (evel_collector_id > 2)
+  {
+    rc = EVEL_CURL_LIBRARY_FAIL;
+    log_error_state("Wrong evel_collector- value > 2");
+    goto exit_label;
+  }
+
+  /***************************************************************************/
+  /* Initialize the local variable with proper global variables that are     */
+  /* required to setup the connection                                        */
+  /***************************************************************************/
+  if (evel_collector_id == 1)
+  {
+     api_url = evel_event_api_url;
+     source_ip = evel_source_ip;
+     username = evel_username;
+     password = evel_password;
+  }
+  else if (evel_collector_id == 2)
+  {
+     api_url = evel_bevent_api_url;
+     source_ip = evel_source_ip_bakup;
+     username = evel_username2;
+     password = evel_password2;
+  }
+  /***************************************************************************/
+  /* 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;
+  }
+
+  /***************************************************************************/
+  /* 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 (evel_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, 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", 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;
+  }
+
+  /***************************************************************************/
+  /* configure local ip address if provided */
+  /* Default ip if NULL */
+  /***************************************************************************/
+  if( source_ip != NULL )
+  {
+    snprintf(local_address,sizeof(local_address),source_ip);
+    if( local_address[0] != '\0' )
+    {
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_INTERFACE,
+                             local_address);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with the local address. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+        goto exit_label;
+      }
+    }
+  }
+
+  /***************************************************************************/
+  /* configure SSL options for HTTPS transfers */
+  /***************************************************************************/
+  if( evel_secure )
+  {
+    if( evel_cert_file_path != NULL )
+    {
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_SSLCERT,
+                             evel_cert_file_path);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with the client cert. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+        goto exit_label;
+      }
+    }
+
+    if( evel_key_file_path != NULL )
+    {
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_SSLKEY,
+                             evel_key_file_path);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with the client key. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+        goto exit_label;
+      }
+    }
+
+    if( evel_ca_info != NULL )
+    {
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_CAINFO,
+                             evel_ca_info);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with the CA cert file. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+        goto exit_label;
+      }
+    }
+
+    if( evel_ca_file_path != NULL )
+    {
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_CAPATH,
+                             evel_ca_file_path);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with the CA cert path. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+        goto exit_label;
+      }
+    }
+
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_SSL_VERIFYPEER,
+                             evel_verify_peer);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with SSL Server verification. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+        goto exit_label;
+      }
+      curl_rc = curl_easy_setopt(curl_handle,
+                             CURLOPT_SSL_VERIFYHOST,
+                             evel_verify_host);
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with Client host verification. "
+                    "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 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_batch_api_url != NULL)
+  {
+    free(evel_batch_api_url);
+    evel_batch_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;
+
+  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!                               */
+  /***************************************************************************/
+  http_response_code = 0;
+
+  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);
+}
+
+/**************************************************************************//**
+ * Send event to another collector
+ *
+ * Identify the next collector and try sending the event to that collector
+ ****************************************************************************/
+static EVEL_ERR_CODES evel_send_to_another_collector(
+                        const EVEL_EVENT_DOMAINS evel_domain, 
+                        char * json_body, 
+                        size_t json_size)
+{
+  int rc = EVEL_SUCCESS;
+  CURLcode curl_rc;
+
+  EVEL_ENTER();
+
+  if ((evel_collector_id == 1) && (curr_global_handles == 2))
+  {
+     evel_collector_id =2;
+  }
+  else if (evel_collector_id == 2)
+  {
+     evel_collector_id =1;
+  }
+
+  rc = evel_setup_curl();
+
+  if ( rc == EVEL_SUCCESS)
+  {
+     if (evel_collector_id == 1)
+     {
+        if (evel_domain == EVEL_DOMAIN_BATCH)
+           curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_batch_api_url);
+        else
+           curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_event_api_url);
+     }
+     else if (evel_collector_id == 2)
+     {
+        if (evel_domain == EVEL_DOMAIN_BATCH)
+           curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_bbatch_api_url);
+        else
+           curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_bevent_api_url);
+     }
+
+     rc = evel_post_api(json_body, json_size);
+  }
+
+  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;
+  int collector_down_count = 0;
+  int switch_coll = 0;
+
+  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!");
+  }
+  /***************************************************************************/
+  /* Set the connection to collector                                         */
+  /***************************************************************************/
+  while (true)
+  {
+     evel_collector_id = 1;
+     rc = evel_setup_curl();
+
+     if ( rc != EVEL_SUCCESS)
+     {
+        EVEL_ERROR("Failed to setup the first collector. Error code=%d", rc);
+        if (curr_global_handles == 2)
+        {
+           EVEL_DEBUG("Switching to other collector");
+
+           evel_collector_id = 2;
+
+           rc = evel_setup_curl();
+           if ( rc != EVEL_SUCCESS)
+           {
+              EVEL_ERROR("Failed to setup the connection to second collector also, Error code%d", rc);
+              sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+              collector_down_count = collector_down_count + 1;
+              EVEL_ERROR("Collectors setup issue- retry count=%d", collector_down_count);
+           }
+           else
+           {
+              collector_down_count = 0;
+              break;
+           }
+        }
+        else
+        {
+           sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+           collector_down_count = collector_down_count + 1;
+           EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+         }
+     }
+     else
+     {
+        collector_down_count = 0;
+        break;
+     }
+  }
+
+  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_BATCH )
+    {
+      EVEL_DEBUG("Batch event received");
+
+      /***********************************************************************/
+      /* Encode the event in JSON.                                           */
+      /***********************************************************************/
+      json_size = evel_json_encode_batch_event(json_body, EVEL_MAX_JSON_BODY, msg);
+
+      /***************************************************************************/
+      /* Set the URL for the API.                                                */
+      /***************************************************************************/
+      if (evel_collector_id == 1)
+      {
+         curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_batch_api_url);
+      }
+      else
+      {
+         curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_bbatch_api_url);
+      }
+
+      if (curl_rc != CURLE_OK)
+      {
+        rc = EVEL_CURL_LIBRARY_FAIL;
+        log_error_state("Failed to initialize libCURL with the Batch API URL. "
+                    "Error code=%d (%s)", curl_rc, curl_err_string);
+      }
+
+      /***********************************************************************/
+      /* Send the JSON across the API.                                       */
+      /***********************************************************************/
+      EVEL_DEBUG("Sending Batch JSON of size %d is: %s", json_size, json_body);
+      rc = evel_post_api(json_body, json_size);
+
+      switch_coll = 0;
+      if ((rc == EVEL_SUCCESS) && ((http_response_code / 100) != 2))
+      {
+         switch_coll = 1;
+         if (http_response_code == 400) // 400 - Bad JSON related return code
+            switch_coll = 0;
+      }
+
+      if ((rc != EVEL_SUCCESS)  || (switch_coll == 1))
+      {
+        EVEL_ERROR("Failed to transfer the data. Error code=%d", rc);
+        EVEL_DEBUG("Switching to other collector if any");
+
+        while (true)
+        {
+           if (curr_global_handles == 2)
+           {
+              rc = evel_send_to_another_collector(msg->event_domain, json_body, json_size);
+
+              switch_coll = 0;
+              if ((rc == EVEL_SUCCESS) && ((http_response_code / 100) != 2))
+              {
+                 switch_coll = 1;
+                 if (http_response_code == 400) // 400 - Bad JSON related return code
+                    switch_coll = 0;
+              }
+              if ((rc != EVEL_SUCCESS)  || (switch_coll == 1))
+              {
+                 sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+                 collector_down_count = collector_down_count + 1;
+                 EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+              }
+              else
+              {
+                 break;
+              }
+           }
+           else
+           {
+              sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+              collector_down_count = collector_down_count + 1;
+              EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+           }
+
+           rc = evel_send_to_another_collector(msg->event_domain, json_body, json_size);
+
+           switch_coll = 0;
+           if ((rc == EVEL_SUCCESS) && ((http_response_code / 100) != 2))
+           {
+              switch_coll = 1;
+              if (http_response_code == 400) // 400 - Bad JSON related return code
+                 switch_coll = 0;
+           }
+           if ((rc != EVEL_SUCCESS)  || (switch_coll == 1))
+           {
+              collector_down_count = collector_down_count + 1;
+              EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+           }
+           else
+           {
+              break;
+           }
+        }
+      }
+    }
+    else 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);
+
+      /***************************************************************************/
+      /* Set the URL for the API.                                                */
+      /***************************************************************************/
+      if (evel_collector_id == 1)
+         curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_event_api_url);
+      else
+         curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_bevent_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);
+      }
+
+      /***********************************************************************/
+      /* 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);
+
+      switch_coll = 0;
+      if ((rc == EVEL_SUCCESS) && ((http_response_code / 100) != 2))
+      {
+         switch_coll = 1;
+         if (http_response_code == 400) // 400 - Bad JSON related return code
+            switch_coll = 0;
+      }
+
+      if ((rc != EVEL_SUCCESS)  || (switch_coll == 1))
+      {
+        EVEL_ERROR("Failed to transfer the data. Error code=%d", rc);
+        EVEL_DEBUG("Switching to other collector if any");
+
+        while (true)
+        {
+           if (curr_global_handles == 2)
+           {
+              rc = evel_send_to_another_collector(msg->event_domain, json_body, json_size);
+
+              switch_coll = 0;
+              if ((rc == EVEL_SUCCESS) && ((http_response_code / 100) != 2))
+              {
+                 switch_coll = 1;
+                 if (http_response_code == 400) // 400 - Bad JSON related return code
+                    switch_coll = 0;
+              }
+              if ((rc != EVEL_SUCCESS)  || (switch_coll == 1))
+              {
+                 sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+                 collector_down_count = collector_down_count + 1;
+                 EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+              }
+              else
+              {
+                 break;
+              }
+           }
+           else
+           {
+              sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+              collector_down_count = collector_down_count + 1;
+              EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+           }
+
+           rc = evel_send_to_another_collector(msg->event_domain, json_body, json_size);
+
+           switch_coll = 0;
+           if ((rc == EVEL_SUCCESS) && ((http_response_code / 100) != 2))
+           {
+              switch_coll = 1;
+              if (http_response_code == 400) // 400 - Bad JSON related return code
+                 switch_coll = 0;
+           }
+           if ((rc != EVEL_SUCCESS)  || (switch_coll == 1))
+           {
+              collector_down_count = collector_down_count + 1;
+              EVEL_ERROR("Collector setup issue-retry count=%d", collector_down_count);
+           }
+           else
+           {
+              break;
+           }
+        }
+      }
+    }
+    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 = true;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(chunk != NULL);
+  assert(json_tokens != NULL);
+  assert(num_tokens < EVEL_MAX_RESPONSE_TOKENS);
+
+  /***************************************************************************/
+  /* Peek at the tokens to decide what the response it, then call the        */
+  /* appropriate handler to handle it.  There is only one handler at this    */
+  /* point.                                                                  */
+  /***************************************************************************/
+  if (evel_tokens_match_command_list(chunk, json_tokens, num_tokens))
+  {
+    json_ok = evel_handle_command_list(chunk, json_tokens, num_tokens, post);
+  }
+
+  EVEL_EXIT();
+
+  return json_ok;
+}
+
+/**************************************************************************//**
+ * Determine whether a list of tokens looks like a "commandList" response.
+ *
+ * @param chunk         Memory chunk containing the JSON buffer.
+ * @param json_tokens   Token to check.
+ * @param num_tokens    The number of tokens to handle.
+ * @return true if the tokens look like a "commandList" match, or false.
+ *****************************************************************************/
+bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk,
+                                    const jsmntok_t * const json_tokens,
+                                    const int num_tokens)
+{
+  bool result = false;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Make some checks on the basic layout of the commandList.                */
+  /***************************************************************************/
+  if ((num_tokens > 3) &&
+      (json_tokens[0].type == JSMN_OBJECT) &&
+      (json_tokens[1].type == JSMN_STRING) &&
+      (json_tokens[2].type == JSMN_ARRAY) &&
+      (evel_token_equals_string(chunk, &json_tokens[1], "commandList")))
+  {
+    result = true;
+  }
+
+  EVEL_EXIT();
+
+  return result;
+}
+
+/**************************************************************************//**
+ * Check that a string token matches a given input string.
+ *
+ * @param chunk         Memory chunk containing the JSON buffer.
+ * @param json_token    Token to check.
+ * @param check_string  String to check it against.
+ * @return true if the strings match, or false.
+ *****************************************************************************/
+bool evel_token_equals_string(const MEMORY_CHUNK * const chunk,
+                              const jsmntok_t * json_token,
+                              const char * check_string)
+{
+  bool result = false;
+
+  EVEL_ENTER();
+
+  const int token_length = json_token->end - json_token->start;
+  const char * const token_string = chunk->memory + json_token->start;
+
+  if (token_length == (int)strlen(check_string))
+  {
+    result = (strncmp(token_string, check_string, token_length) == 0);
+  }
+
+  EVEL_EXIT();
+
+  return result;
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_fault.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_fault.c
new file mode 100644 (file)
index 0000000..401e4ad
--- /dev/null
@@ -0,0 +1,372 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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;
+  if( severity == EVEL_SEVERITY_NORMAL )
+     evel_event_sequence_set(&fault->header,0);
+  else
+     evel_event_sequence_set(&fault->header,1);
+  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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_heartbeat_fields.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_heartbeat_fields.c
new file mode 100644 (file)
index 0000000..be8527c
--- /dev/null
@@ -0,0 +1,269 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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 ev_name  Unique Event Name confirming Domain AsdcModel Description
+ * @param ev_id    A universal identifier of the event for: troubleshooting correlation, analysis, etc
+ * @param interval    heartbeat interval
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_internal.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_internal.h
new file mode 100644 (file)
index 0000000..14d224d
--- /dev/null
@@ -0,0 +1,886 @@
+/*************************************************************************//**
+ *
+ * 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] bakup_api_url
+ *                      The BakupURL where the Vendor Backup Listener is expected
+ *                      to be.
+ * @param[in] throt_api_url
+ *                      The URL where the Throttling API is expected to be.
+ * @param[in] source_ip        Source IP of VES Agent
+ * @param[in] bakup_source_ip  Backup Source IP of VES Agent
+ * @param[in] ring_buf_size    Initialization size of Ring Buffer
+ * @param[in] secure     Whether Using http or https
+ * @param[in] cert_file_path  Path to Client Certificate file
+ * @param[in] key_file_path   Path to Client key file
+ * @param[in] ca_info         Path to CA info file
+ * @param[in] ca_file_path    Path to CA file
+ * @param[in] verify_peer     Using peer verification or not
+ * @param[in] verify_host     Using host verification or not
+ * @param[in] username  The username for the Basic Authentication of requests.
+ * @param[in] password  The password for the Basic Authentication of requests.
+ * @param[in] username2  The username for the Bakup requests.
+ * @param[in] password2  The password for the Bakup 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 bakup_api_url,
+                                        const char * const throt_api_url,
+                                        const char * const source_ip,
+                                        const char * const bakup_source_ip,
+                                        int ring_buf_size,
+                                        int secure,
+                                        const char * const cert_file_path,
+                                        const char * const key_file_path,
+                                        const char * const ca_info,
+                                        const char * const ca_file_path,
+                                        long verify_peer,
+                                        long verify_host,
+                                        const char * const username,
+                                        const char * const password,
+                                        const char * const username2,
+                                        const char * const password2,
+                                        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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_internal_event.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_internal_event.c
new file mode 100644 (file)
index 0000000..dff2bae
--- /dev/null
@@ -0,0 +1,114 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_json_buffer.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_json_buffer.c
new file mode 100644 (file)
index 0000000..cf1323d
--- /dev/null
@@ -0,0 +1,872 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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)
+{
+  float ver;
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(key != NULL);
+
+  ver = (float)major_version + (float)minor_version/10.0;
+
+    jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                           jbuf->max_size - jbuf->offset,
+                           "%s\"%s\": %.1f",
+                           evel_json_kv_comma(jbuf),
+                           key,
+                           ver);
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the key and opening bracket of an optional named list to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key           Pointer to the key to encode.
+ * @return true if the list was opened, false if it was suppressed.
+ *****************************************************************************/
+bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf,
+                                   const char * const key)
+{
+  bool opened = false;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(key != NULL);
+
+  if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+      (jbuf->throttle_spec != NULL) &&
+      evel_throttle_suppress_field(jbuf->throttle_spec, key))
+  {
+    EVEL_INFO("Suppressed: %s", key);
+    opened = false;
+  }
+  else
+  {
+    evel_json_open_named_list(jbuf, key);
+    opened = true;
+  }
+
+  EVEL_EXIT();
+
+  return opened;
+}
+
+/**************************************************************************//**
+ * Add the key and opening bracket of a named list to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key           Pointer to the key to encode.
+ *****************************************************************************/
+void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
+                               const char * const key)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(key != NULL);
+
+  jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                           jbuf->max_size - jbuf->offset,
+                           "%s\"%s\": [",
+                           evel_json_kv_comma(jbuf),
+                           key);
+  jbuf->depth++;
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the closing bracket of a list to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+
+  jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                           jbuf->max_size - jbuf->offset,
+                           "]");
+  jbuf->depth--;
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format        Format string in standard printf format.
+ * @param ...           Variable parameters for format string.
+ *****************************************************************************/
+void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
+                        const char * const format,
+                        ...)
+{
+  va_list largs;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(format != NULL);
+
+  /***************************************************************************/
+  /* Add a comma unless we're at the start of the list.                      */
+  /***************************************************************************/
+  if (jbuf->json[jbuf->offset - 1] != '[')
+  {
+    jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                             jbuf->max_size - jbuf->offset,
+                             ", ");
+  }
+
+  va_start(largs, format);
+  jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
+                            jbuf->max_size - jbuf->offset,
+                            format,
+                            largs);
+  va_end(largs);
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an optional named object to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key           Pointer to the key to encode.
+ *****************************************************************************/
+bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf,
+                                     const char * const key)
+{
+  bool opened = false;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(key != NULL);
+
+  if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+      (jbuf->throttle_spec != NULL) &&
+      evel_throttle_suppress_field(jbuf->throttle_spec, key))
+  {
+    EVEL_INFO("Suppressed: %s", key);
+    opened = false;
+  }
+  else
+  {
+    evel_json_open_named_object(jbuf, key);
+    opened = true;
+  }
+
+  EVEL_EXIT();
+
+  return opened;
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key           Pointer to the key to encode.
+ * @return true if the object was opened, false if it was suppressed.
+ *****************************************************************************/
+void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
+                                 const char * const key)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(key != NULL);
+
+  jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                           jbuf->max_size - jbuf->offset,
+                           "%s\"%s\": {",
+                           evel_json_kv_comma(jbuf),
+                           key);
+  jbuf->depth++;
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
+{
+  char * comma;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+
+  if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}'))
+  {
+    comma = ", ";
+  }
+  else
+  {
+    comma = "";
+  }
+
+  jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                           jbuf->max_size - jbuf->offset,
+                           "%s{",
+                           comma);
+  jbuf->depth++;
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the closing bracket of an object to a JSON buffer.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+
+  jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+                           jbuf->max_size - jbuf->offset,
+                           "}");
+  jbuf->depth--;
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Determine whether to add a comma when adding a key-value pair.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ * @returns A string containing the comma if it is required.
+ *****************************************************************************/
+char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf)
+{
+  char * result;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+
+  if ((jbuf->offset == 0) ||
+      (jbuf->json[jbuf->offset-1] == '{') ||
+      (jbuf->json[jbuf->offset-1] == '['))
+  {
+    result = "";
+  }
+  else
+  {
+    result = ", ";
+  }
+
+  EVEL_EXIT();
+
+  return result;
+}
+
+/**************************************************************************//**
+ * Add a checkpoint - a stake in the ground to which we can rewind.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+
+  /***************************************************************************/
+  /* Store the current offset.                                               */
+  /***************************************************************************/
+  jbuf->checkpoint = jbuf->offset;
+
+  EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Rewind to the latest checkoint.
+ *
+ * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_rewind(EVEL_JSON_BUFFER * jbuf)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(jbuf != NULL);
+  assert(jbuf->checkpoint >= 0);
+  assert(jbuf->checkpoint <= jbuf->offset);
+
+  /***************************************************************************/
+  /* Reinstate the offset from the last checkpoint.                          */
+  /***************************************************************************/
+  jbuf->offset = jbuf->checkpoint;
+  jbuf->checkpoint = -1;
+
+  EVEL_EXIT();
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_jsonobject.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_jsonobject.c
new file mode 100644 (file)
index 0000000..df0b03c
--- /dev/null
@@ -0,0 +1,451 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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 );
+  evel_set_option_ull(&pinst->objinst_epoch_microsec , epmicrosec, "Json object instance microsec set");
+}
+
+/**************************************************************************//**
+ * 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 %p",jinst);
+
+  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);
+  free(keyp);
+  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);
+  }
+  free(objinst);
+
+  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);
+
+  EVEL_DEBUG("Freeing Json Object (%s)", jsobj->object_name);
+  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 jsonObject Instance Field %p (%s)",
+               other_field,other_field->jsonstring);
+    evel_free_jsonobjinst(other_field);
+    other_field = dlist_pop_last(&jsobj->jsonobjectinstances);
+  }
+  free(jsobj);
+
+  EVEL_EXIT();
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_logging.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_logging.c
new file mode 100644 (file)
index 0000000..cb07396
--- /dev/null
@@ -0,0 +1,168 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_mobile_flow.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_mobile_flow.c
new file mode 100644 (file)
index 0000000..90b1a44
--- /dev/null
@@ -0,0 +1,2123 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_option.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_option.c
new file mode 100644 (file)
index 0000000..7818fe1
--- /dev/null
@@ -0,0 +1,527 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_other.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_other.c
new file mode 100644 (file)
index 0000000..5f59c1d
--- /dev/null
@@ -0,0 +1,511 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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 domain.
+ *
+ *****************************************************************************/
+
+#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();
+}
+
+/**************************************************************************//**
+ * Set size of Named arrays hash table
+ *
+ * The max size of hash table is passed
+ *
+ * @param other         Pointer to the Other.
+ * @param size          size of hashtable
+ *****************************************************************************/
+void evel_other_field_set_namedarraysize(EVENT_OTHER * other, const int size)
+{
+  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 = (DLIST *)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,(void*)nlist);
+     EVEL_DEBUG("Created to new namedarray table %p",nlist);
+  }
+  else
+  {
+     dlist_push_last(list, other_field);
+     EVEL_DEBUG("Adding to existing table %p",list);
+  }
+
+  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)
+{
+  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 idx;
+  bool itm_added = false;
+  DLIST *itm_list = NULL;
+  ENTRY_T *entry = 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
+
+   evel_json_checkpoint(jbuf);
+   ht = event->namedarrays;
+   if( ht != NULL )
+   {
+     if( ht->size > 0)
+     {
+
+        evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays");
+        for( idx = 0; idx < ht->size; idx++ ) {
+             if( ht->table[idx] != NULL)
+            {
+                entry =  ht->table[idx]; 
+                EVEL_DEBUG("Encoding other %s %p",(char *) (entry->key), entry->value);
+
+               evel_json_open_object(jbuf);
+               evel_enc_kv_string(jbuf, "name", entry->key);
+
+               itm_list = (DLIST*)(entry->value);
+               evel_json_open_opt_named_list(jbuf, "arrayOfFields");
+
+    other_field_item = dlist_get_first(itm_list);
+    while (other_field_item != NULL)
+    {
+     other_field = (OTHER_FIELD *) other_field_item->item;
+     EVEL_DEBUG("Encoding other %s %s",(char *)other_field->name,(char*)other_field->value);
+     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_object(jbuf);
+
+            }
+        }
+        evel_json_close_list(jbuf);
+
+     } else {
+       evel_json_rewind(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_opt_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);
+  }
+
+  }
+
+  evel_json_checkpoint(jbuf);
+  if( evel_json_open_opt_named_list(jbuf, "nameValuePairs"))
+  {
+     bool item_added = false;
+
+  other_field_item = dlist_get_first(&event->namedvalues);
+  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);
+      item_added = true;
+    }
+    other_field_item = dlist_get_next(other_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, "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_JSON_OBJECT * jsonobjp = NULL;
+  DLIST_ITEM * other_field_item = 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);
+  }
+
+  jsonobjp = dlist_pop_last(&event->jsonobjects);
+  while (jsonobjp != NULL)
+  {
+    evel_free_jsonobject( jsonobjp );
+
+    jsonobjp = dlist_pop_last(&event->jsonobjects);
+  }
+
+  evel_free_header(&event->header);
+
+  EVEL_EXIT();
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_reporting_measurement.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_reporting_measurement.c
new file mode 100644 (file)
index 0000000..0f30372
--- /dev/null
@@ -0,0 +1,438 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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, "arrayOfFields");
+
+        /*********************************************************************/
+        /* 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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_scaling_measurement.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_scaling_measurement.c
new file mode 100644 (file)
index 0000000..04bed57
--- /dev/null
@@ -0,0 +1,3865 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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();
+}
+
+/**************************************************************************//**
+ * 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 measurement     Pointer to the ScalingMeasurement
+ * @param jsonobj   Pointer to json object
+ *****************************************************************************/
+void evel_measurement_addl_object_add(EVENT_MEASUREMENT * measurement, EVEL_JSON_OBJECT *jsonobj)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(measurement != NULL);
+  assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+  assert(jsonobj != NULL);
+
+  EVEL_DEBUG("Adding jsonObject %p",jsonobj);
+
+  dlist_push_last(&measurement->additional_objects, jsonobj);
+
+  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 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_mergewriteavg_set(MEASUREMENT_DISK_USE * const disk_use,
+                                    const double val)
+{
+  EVEL_ENTER();
+  evel_set_option_double(&disk_use->mergewriteavg, val, "Disk writeavg 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 mtx_ucast_packets_acc)
+{
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(mtx_ucast_packets_acc >= 0.0);
+
+  evel_set_option_double(&vnic_performance->tx_ucast_packets_acc,
+                      mtx_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;
+  DLIST_ITEM * other_field_item = NULL;
+  EVEL_JSON_OBJECT_INSTANCE * jsonobjinst = NULL;
+  EVEL_JSON_OBJECT * jsonobjp = NULL;
+  DLIST_ITEM * jsobj_field_item = NULL;
+  EVEL_INTERNAL_KEY * keyinst = NULL;
+  DLIST_ITEM * keyinst_field_item = NULL;
+
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check preconditions.                                                    */
+  /***************************************************************************/
+  assert(event != NULL);
+  assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+
+  evel_json_encode_header(jbuf, &event->header);
+  evel_json_open_named_object(jbuf, "measurementsForVfScalingFields");
+
+  /***************************************************************************/
+  /* Mandatory fields.                                                       */
+  /***************************************************************************/
+  evel_enc_kv_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);
+    }
+  }
+
+
+  evel_json_checkpoint(jbuf);
+  if(evel_json_open_opt_named_list(jbuf, "additionalObjects"))
+  {
+  bool item_added = false;
+  other_field_item = dlist_get_first(&event->additional_objects);
+  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_opt_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 = true;
+      }
+      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);
+  }
+  }
+
+
+  // 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, "vNicPerformanceArray"))
+  {
+    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, "arrayOfFields");
+
+        /*********************************************************************/
+        /* 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_JSON_OBJECT * jsonobjp = 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);
+  }
+
+  jsonobjp = dlist_pop_last(&event->additional_objects);
+  while (jsonobjp != NULL)
+  {
+    EVEL_DEBUG("Freeing jsonObject %p",jsonobjp);
+    evel_free_jsonobject( jsonobjp );
+    jsonobjp = dlist_pop_last(&event->additional_objects);
+  }
+
+  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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_sipsignaling.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_sipsignaling.c
new file mode 100644 (file)
index 0000000..efc62db
--- /dev/null
@@ -0,0 +1,576 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_state_change.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_state_change.c
new file mode 100644 (file)
index 0000000..eb81f97
--- /dev/null
@@ -0,0 +1,287 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_strings.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_strings.c
new file mode 100644 (file)
index 0000000..3f0e7a4
--- /dev/null
@@ -0,0 +1,474 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_syslog.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_syslog.c
new file mode 100644 (file)
index 0000000..06d8163
--- /dev/null
@@ -0,0 +1,506 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_threshold_cross.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_threshold_cross.c
new file mode 100644 (file)
index 0000000..c66b08c
--- /dev/null
@@ -0,0 +1,532 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_throttle.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_throttle.c
new file mode 100644 (file)
index 0000000..ac664a1
--- /dev/null
@@ -0,0 +1,2105 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+/**************************************************************************//**
+ * @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",
+  "batch",
+  "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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_throttle.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_throttle.h
new file mode 100644 (file)
index 0000000..c97b3c3
--- /dev/null
@@ -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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_voicequality.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/evel_voicequality.c
new file mode 100644 (file)
index 0000000..04238d1
--- /dev/null
@@ -0,0 +1,640 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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;
+
+  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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/hashtable.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/hashtable.c
new file mode 100644 (file)
index 0000000..d0017c9
--- /dev/null
@@ -0,0 +1,224 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/hashtable.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/hashtable.h
new file mode 100644 (file)
index 0000000..8be17dc
--- /dev/null
@@ -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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/jsmn.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/jsmn.c
new file mode 100644 (file)
index 0000000..ae08569
--- /dev/null
@@ -0,0 +1,329 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+
+#include "jsmn.h"
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+               jsmntok_t *tokens, size_t num_tokens) {
+       jsmntok_t *tok;
+       if (parser->toknext >= num_tokens) {
+               return NULL;
+       }
+       tok = &tokens[parser->toknext++];
+       tok->start = tok->end = -1;
+       tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+       tok->parent = -1;
+#endif
+       return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+                            int start, int end) {
+       token->type = type;
+       token->start = start;
+       token->end = end;
+       token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+               size_t len, jsmntok_t *tokens, size_t num_tokens) {
+       jsmntok_t *token;
+       int start;
+
+       start = parser->pos;
+
+       for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+               switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+                       /* In strict mode primitive must be followed by "," or "}" or "]" */
+                       case ':':
+#endif
+                       case '\t' : case '\r' : case '\n' : case ' ' :
+                       case ','  : case ']'  : case '}' :
+                               goto found;
+               }
+               if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+                       parser->pos = start;
+                       return JSMN_ERROR_INVAL;
+               }
+       }
+#ifdef JSMN_STRICT
+       /* In strict mode primitive must be followed by a comma/object/array */
+       parser->pos = start;
+       return JSMN_ERROR_PART;
+#endif
+
+found:
+       if (tokens == NULL) {
+               parser->pos--;
+               return 0;
+       }
+       token = jsmn_alloc_token(parser, tokens, num_tokens);
+       if (token == NULL) {
+               parser->pos = start;
+               return JSMN_ERROR_NOMEM;
+       }
+       jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+       token->parent = parser->toksuper;
+#endif
+       parser->pos--;
+       return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+               size_t len, jsmntok_t *tokens, size_t num_tokens) {
+       jsmntok_t *token;
+
+       int start = parser->pos;
+
+       parser->pos++;
+
+       /* Skip starting quote */
+       for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+               char c = js[parser->pos];
+
+               /* Quote: end of string */
+               if (c == '\"') {
+                       if (tokens == NULL) {
+                               return 0;
+                       }
+                       token = jsmn_alloc_token(parser, tokens, num_tokens);
+                       if (token == NULL) {
+                               parser->pos = start;
+                               return JSMN_ERROR_NOMEM;
+                       }
+                       jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+                       token->parent = parser->toksuper;
+#endif
+                       return 0;
+               }
+
+               /* Backslash: Quoted symbol expected */
+               if (c == '\\' && parser->pos + 1 < len) {
+                       int i;
+                       parser->pos++;
+                       switch (js[parser->pos]) {
+                               /* Allowed escaped symbols */
+                               case '\"': case '/' : case '\\' : case 'b' :
+                               case 'f' : case 'r' : case 'n'  : case 't' :
+                                       break;
+                               /* Allows escaped symbol \uXXXX */
+                               case 'u':
+                                       parser->pos++;
+                                       for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+                                               /* If it isn't a hex character we have an error */
+                                               if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+                                                                       (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+                                                                       (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+                                                       parser->pos = start;
+                                                       return JSMN_ERROR_INVAL;
+                                               }
+                                               parser->pos++;
+                                       }
+                                       parser->pos--;
+                                       break;
+                               /* Unexpected symbol */
+                               default:
+                                       parser->pos = start;
+                                       return JSMN_ERROR_INVAL;
+                       }
+               }
+       }
+       parser->pos = start;
+       return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+               jsmntok_t *tokens, unsigned int num_tokens) {
+       int r;
+       int i;
+       jsmntok_t *token;
+       int count = parser->toknext;
+
+       for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+               char c;
+               jsmntype_t type;
+
+               c = js[parser->pos];
+               switch (c) {
+                       case '{': case '[':
+                               count++;
+                               if (tokens == NULL) {
+                                       break;
+                               }
+                               token = jsmn_alloc_token(parser, tokens, num_tokens);
+                               if (token == NULL)
+                                       return JSMN_ERROR_NOMEM;
+                               if (parser->toksuper != -1) {
+                                       tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+                                       token->parent = parser->toksuper;
+#endif
+                               }
+                               token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+                               token->start = parser->pos;
+                               parser->toksuper = parser->toknext - 1;
+                               break;
+                       case '}': case ']':
+                               if (tokens == NULL)
+                                       break;
+                               type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+                               if (parser->toknext < 1) {
+                                       return JSMN_ERROR_INVAL;
+                               }
+                               token = &tokens[parser->toknext - 1];
+                               for (;;) {
+                                       if (token->start != -1 && token->end == -1) {
+                                               if (token->type != type) {
+                                                       return JSMN_ERROR_INVAL;
+                                               }
+                                               token->end = parser->pos + 1;
+                                               parser->toksuper = token->parent;
+                                               break;
+                                       }
+                                       if (token->parent == -1) {
+                                               break;
+                                       }
+                                       token = &tokens[token->parent];
+                               }
+#else
+                               for (i = parser->toknext - 1; i >= 0; i--) {
+                                       token = &tokens[i];
+                                       if (token->start != -1 && token->end == -1) {
+                                               if (token->type != type) {
+                                                       return JSMN_ERROR_INVAL;
+                                               }
+                                               parser->toksuper = -1;
+                                               token->end = parser->pos + 1;
+                                               break;
+                                       }
+                               }
+                               /* Error if unmatched closing bracket */
+                               if (i == -1) return JSMN_ERROR_INVAL;
+                               for (; i >= 0; i--) {
+                                       token = &tokens[i];
+                                       if (token->start != -1 && token->end == -1) {
+                                               parser->toksuper = i;
+                                               break;
+                                       }
+                               }
+#endif
+                               break;
+                       case '\"':
+                               r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+                               if (r < 0) return r;
+                               count++;
+                               if (parser->toksuper != -1 && tokens != NULL)
+                                       tokens[parser->toksuper].size++;
+                               break;
+                       case '\t' : case '\r' : case '\n' : case ' ':
+                               break;
+                       case ':':
+                               parser->toksuper = parser->toknext - 1;
+                               break;
+                       case ',':
+                               if (tokens != NULL && parser->toksuper != -1 &&
+                                               tokens[parser->toksuper].type != JSMN_ARRAY &&
+                                               tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+                                       parser->toksuper = tokens[parser->toksuper].parent;
+#else
+                                       for (i = parser->toknext - 1; i >= 0; i--) {
+                                               if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+                                                       if (tokens[i].start != -1 && tokens[i].end == -1) {
+                                                               parser->toksuper = i;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+#endif
+                               }
+                               break;
+#ifdef JSMN_STRICT
+                       /* In strict mode primitives are: numbers and booleans */
+                       case '-': case '0': case '1' : case '2': case '3' : case '4':
+                       case '5': case '6': case '7' : case '8': case '9':
+                       case 't': case 'f': case 'n' :
+                               /* And they must not be keys of the object */
+                               if (tokens != NULL && parser->toksuper != -1) {
+                                       jsmntok_t *t = &tokens[parser->toksuper];
+                                       if (t->type == JSMN_OBJECT ||
+                                                       (t->type == JSMN_STRING && t->size != 0)) {
+                                               return JSMN_ERROR_INVAL;
+                                       }
+                               }
+#else
+                       /* In non-strict mode every unquoted value is a primitive */
+                       default:
+#endif
+                               r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+                               if (r < 0) return r;
+                               count++;
+                               if (parser->toksuper != -1 && tokens != NULL)
+                                       tokens[parser->toksuper].size++;
+                               break;
+
+#ifdef JSMN_STRICT
+                       /* Unexpected char in strict mode */
+                       default:
+                               return JSMN_ERROR_INVAL;
+#endif
+               }
+       }
+
+       if (tokens != NULL) {
+               for (i = parser->toknext - 1; i >= 0; i--) {
+                       /* Unmatched opened object or array */
+                       if (tokens[i].start != -1 && tokens[i].end == -1) {
+                               return JSMN_ERROR_PART;
+                       }
+               }
+       }
+
+       return count;
+}
+
+/**
+ * Creates a new parser based over a given  buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser) {
+       parser->pos = 0;
+       parser->toknext = 0;
+       parser->toksuper = -1;
+}
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/jsmn.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/jsmn.h
new file mode 100644 (file)
index 0000000..4ae6d9b
--- /dev/null
@@ -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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/license.md b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/license.md
new file mode 100644 (file)
index 0000000..665344d
--- /dev/null
@@ -0,0 +1,85 @@
+# 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.
+
+
+Unless otherwise specified, all software contained herein is
+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.
+
+ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+## 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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/metadata.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/metadata.c
new file mode 100644 (file)
index 0000000..b865074
--- /dev/null
@@ -0,0 +1,636 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ ****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <malloc.h>
+#include <unistd.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()
+{
+  char hostname[MAX_METADATA_STRING];
+
+  FILE * f = fopen ("/proc/sys/kernel/random/uuid", "r");
+
+  strncpy(vm_uuid,
+          "Dummy VM UUID - No Metadata available",
+          MAX_METADATA_STRING);
+  strncpy(vm_name,
+          "Dummy VM name - No Metadata available",
+          MAX_METADATA_STRING);
+
+  if( gethostname(hostname, 1024) != -1 )
+      strcpy(vm_name,hostname);
+
+  if (f)
+  {
+    if (fgets(vm_uuid,MAX_METADATA_STRING, f)!=NULL)
+    {
+      vm_uuid[strlen( vm_uuid ) - 1 ] = '\0';
+      EVEL_DEBUG("VM UUID: %s", vm_uuid);
+    }
+    fclose (f);
+  }
+
+}
+
+/**************************************************************************//**
+ * Initialize value for vm_name for all coming events
+ * @param  source_name  Source name string.
+ *                      Must confirm with EVEL source name standard
+ * @returns Status code
+ * @retval  EVEL_SUCCESS      On success
+ * @retval  ::EVEL_ERR_CODES  On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_set_source_name(char * src_name)
+{
+  if( src_name && src_name[0] )
+  {
+      if( strlen(src_name) < MAX_METADATA_STRING ){
+          strcpy(vm_name,src_name);
+          return EVEL_SUCCESS;
+       } else 
+          EVEL_DEBUG("Event Source Name too long");
+  }
+  else
+     EVEL_DEBUG("Invalid Event Source Name string");
+  return EVEL_ERR_GEN_FAIL;
+}
+
+/**************************************************************************//**
+ * Get a string value from supplied JSON by matching the key.
+ *
+ * As the structure of the metadata we're looking at is pretty straightforward
+ * we don't do anything complex (a la XPath) to extract nested keys with the
+ * same leaf name, for example.  Simply walk the structure until we find a
+ * string with the correct value.
+ *
+ * @param[in] json_string   The string which contains the JSON and has already
+ *                          been parsed.
+ * @param[in] tokens        The tokens which the JSON parser found in the JSON.
+ * @param[in] json_token_count  How many tokens were found.
+ * @param[in] key           The key we're looking for.
+ * @param[out] value        The string we found at @p key.
+ *
+ * @returns Status code
+ * @retval  EVEL_SUCCESS      On success - contents of @p value updated.
+ * @retval  EVEL_JSON_KEY_NOT_FOUND  Key not found - @p value not updated.
+ * @retval  EVEL_BAD_JSON     Parser hit unexpected data - @p value not
+ *                            updated.
+ *****************************************************************************/
+static EVEL_ERR_CODES json_get_string(const char * json_string,
+                                      const jsmntok_t * tokens,
+                                      int json_token_count,
+                                      const char * key,
+                                      char * value)
+{
+  EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND;
+  int token_num = 0;
+  int token_len = 0;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check assumptions.                                                      */
+  /***************************************************************************/
+  assert(json_string != NULL);
+  assert(tokens != NULL);
+  assert(json_token_count >= 0);
+  assert(key != NULL);
+  assert(value != NULL);
+
+  for (token_num = 0; token_num < json_token_count; token_num++)
+  {
+    switch(tokens[token_num].type)
+    {
+    case JSMN_OBJECT:
+      EVEL_DEBUG("Skipping object");
+      break;
+
+    case JSMN_ARRAY:
+      EVEL_DEBUG("Skipping array");
+      break;
+
+    case JSMN_STRING:
+      /***********************************************************************/
+      /* This is a string, so may be what we want.  Compare keys.            */
+      /***********************************************************************/
+      if (jsoneq(json_string, &tokens[token_num], key) == 0)
+      {
+        token_len = tokens[token_num + 1].end - tokens[token_num + 1].start;
+        EVEL_DEBUG("Token %d len %d matches at %d to %d", token_num,
+                                                   tokens[token_num + 1].start,
+                                                   tokens[token_num + 1].end);
+        strncpy(value, json_string + tokens[token_num + 1].start, token_len);
+        value[token_len] = '\0';
+        EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value);
+        rc = EVEL_SUCCESS;
+        goto exit_label;
+      }
+      else
+      {
+        EVEL_DEBUG("String key did not match");
+      }
+
+      /***********************************************************************/
+      /* Step over the value, whether we used it or not.                     */
+      /***********************************************************************/
+      token_num++;
+      break;
+
+    case JSMN_PRIMITIVE:
+      EVEL_INFO("Skipping primitive");
+      break;
+
+    case JSMN_UNDEFINED:
+    default:
+      rc = EVEL_BAD_JSON_FORMAT;
+      EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+                  token_num,
+                  tokens[token_num].type);
+      goto exit_label;
+    }
+  }
+
+exit_label:
+  EVEL_EXIT();
+  return rc;
+}
+
+/**************************************************************************//**
+ * Get a top-level string value from supplied JSON by matching the key.
+ *
+ * Unlike json_get_string, this only returns a value that is in the top-level
+ * JSON object.
+ *
+ * @param[in] json_string   The string which contains the JSON and has already
+ *                          been parsed.
+ * @param[in] tokens        The tokens which the JSON parser found in the JSON.
+ * @param[in] json_token_count  How many tokens were found.
+ * @param[in] key           The key we're looking for.
+ * @param[out] value        The string we found at @p key.
+ *
+ * @returns Status code
+ * @retval  EVEL_SUCCESS      On success - contents of @p value updated.
+ * @retval  EVEL_JSON_KEY_NOT_FOUND  Key not found - @p value not updated.
+ * @retval  EVEL_BAD_JSON     Parser hit unexpected data - @p value not
+ *                            updated.
+ *****************************************************************************/
+static EVEL_ERR_CODES json_get_top_level_string(const char * json_string,
+                                                const jsmntok_t * tokens,
+                                                int json_token_count,
+                                                const char * key,
+                                                char * value)
+{
+  EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND;
+  int token_num = 0;
+  int token_len = 0;
+  int bracket_count = 0;
+  int string_index = 0;
+  int increment = 0;
+
+  EVEL_ENTER();
+
+  /***************************************************************************/
+  /* Check assumptions.                                                      */
+  /***************************************************************************/
+  assert(json_string != NULL);
+  assert(tokens != NULL);
+  assert(json_token_count >= 0);
+  assert(key != NULL);
+  assert(value != NULL);
+
+  for (token_num = 0; token_num < json_token_count; token_num++)
+  {
+    switch(tokens[token_num].type)
+    {
+    case JSMN_OBJECT:
+      EVEL_DEBUG("Skipping object");
+      break;
+
+    case JSMN_ARRAY:
+      EVEL_DEBUG("Skipping array");
+      break;
+
+    case JSMN_STRING:
+      /***********************************************************************/
+      /* This is a string, so may be what we want.  Compare keys.            */
+      /***********************************************************************/
+      if (jsoneq(json_string, &tokens[token_num], key) == 0)
+      {
+        /*********************************************************************/
+        /* Count the difference in the number of opening and closing         */
+        /* brackets up to this token.  This needs to be 1 for a top-level    */
+        /* string.  Let's just hope we don't have any strings containing     */
+        /* brackets.                                                         */
+        /*********************************************************************/
+        increment = ((string_index < tokens[token_num].start) ? 1 : -1);
+
+        while (string_index != tokens[token_num].start)
+        {
+          if (json_string[string_index] == '{')
+          {
+            bracket_count += increment;
+          }
+          else if (json_string[string_index] == '}')
+          {
+            bracket_count -= increment;
+          }
+
+          string_index += increment;
+        }
+
+        if (bracket_count == 1)
+        {
+          token_len = tokens[token_num + 1].end - tokens[token_num + 1].start;
+          EVEL_DEBUG("Token %d len %d matches at top level at %d to %d",
+                     token_num,
+                     tokens[token_num + 1].start,
+                     tokens[token_num + 1].end);
+          strncpy(value, json_string + tokens[token_num + 1].start, token_len);
+          value[token_len] = '\0';
+          EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value);
+          rc = EVEL_SUCCESS;
+          goto exit_label;
+        }
+        else
+        {
+          EVEL_DEBUG("String key did match, but not at top level");
+        }
+      }
+      else
+      {
+        EVEL_DEBUG("String key did not match");
+      }
+
+      /***********************************************************************/
+      /* Step over the value, whether we used it or not.                     */
+      /***********************************************************************/
+      token_num++;
+      break;
+
+    case JSMN_PRIMITIVE:
+      EVEL_INFO("Skipping primitive");
+      break;
+
+    case JSMN_UNDEFINED:
+    default:
+      rc = EVEL_BAD_JSON_FORMAT;
+      EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+                  token_num,
+                  tokens[token_num].type);
+      goto exit_label;
+    }
+  }
+
+exit_label:
+  EVEL_EXIT();
+  return rc;
+}
+
+/**************************************************************************//**
+ * Compare a JSON string token with a value.
+ *
+ * @param[in] json The string which contains the JSON and has already been
+ *                 parsed.
+ * @param[in] tok  The token which the JSON parser found in the JSON.
+ * @param[in] s    The string we're looking for.
+ *
+ * @returns        Whether the token matches the string or not.
+ * @retval  0      Value matches
+ * @retval  -1     Value does not match.
+ *****************************************************************************/
+static int jsoneq(const char *json, const jsmntok_t *tok, const char *s) {
+  if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+      strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+    return 0;
+  }
+  return -1;
+}
+
+/**************************************************************************//**
+ * Get the VM name provided by the metadata service.
+ *
+ * @returns VM name
+ *****************************************************************************/
+const char *openstack_vm_name()
+{
+  return vm_name;
+}
+
+/**************************************************************************//**
+ * Get the VM UUID provided by the metadata service.
+ *
+ * @returns VM UUID
+ *****************************************************************************/
+const char *openstack_vm_uuid()
+{
+  return vm_uuid;
+}
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/metadata.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/metadata.h
new file mode 100644 (file)
index 0000000..1ee4409
--- /dev/null
@@ -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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/quickstart.md b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/quickstart.md
new file mode 100644 (file)
index 0000000..1c735cc
--- /dev/null
@@ -0,0 +1,445 @@
+# Quick Start Guide {#quickstart}
+
+# Introduction {#qs_intro}
+
+This Quick-Start section describes how to:
+
+  *  Install and compile the supplied library code
+  *  Integrate an existing project to use the EVEL library
+  
+# Installation {#qs_install}
+
+The library is supplied as a source-code compressed-tar file. It is 
+straightforward to install and build to integrate with an existing or new
+development project.
+
+## Unpack the Source Code {#qs_unpack}
+
+The file should unpacked into your development environment:
+```
+$ mkdir evel
+$ cd evel
+$ tar zxvf evel-library-package.tgz
+```
+### Satisfy Dependencies {#qs_depend}
+
+Note that all commands in this section are based on CentOS package management
+tools and you may need to substitute the appropriate tools/packages for your
+distribution, for example `apt-get` for Ubuntu.
+
+Ensure that GCC development tools are available.
+
+```
+$ sudo yum install gcc
+```
+Additionally, the library has a dependency on the cURL library, so you'll need 
+the development tools for libCurl installed. (At runtime, only the runtime 
+library is required, of course.)
+
+```
+$ sudo yum install libcurl-devel
+```
+If you wish to make the project documentation, then Doxygen and Graphviz are
+required. (Again, this is only in the development environment, not the runtime 
+environment!)
+
+```
+$ sudo yum install doxygen graphviz
+```
+
+Note that some distributions have quite old versions of Doxygen by default and 
+it may be necessary to install a later version to use all the features.
+
+If you want to build PDFs from the LaTeX you will need a texlive install.
+
+```
+$ sudo yum install texlive
+```
+
+### Test Build {#qs_build}
+Make sure that the library makes cleanly:
+
+```
+$ cd bldjobs
+$ make
+Making dependency file evel_unit.d for evel_unit.c
+Making dependency file evel_test_control.d for evel_test_control.c
+Making dependency file evel_demo.d for evel_demo.c
+Making dependency file jsmn.d for jsmn.c
+Making dependency file evel_logging.d for evel_logging.c
+Making dependency file evel_event_mgr.d for evel_event_mgr.c
+Making dependency file evel_internal_event.d for evel_internal_event.c
+Making dependency file evel_throttle.d for evel_throttle.c
+Making dependency file evel_syslog.d for evel_syslog.c
+Making dependency file evel_strings.d for evel_strings.c
+Making dependency file evel_state_change.d for evel_state_change.c
+Making dependency file evel_scaling_measurement.d for evel_scaling_measurement.c
+Making dependency file evel_signaling.d for evel_signaling.c
+Making dependency file evel_service.d for evel_service.c
+Making dependency file evel_reporting_measurement.d for evel_reporting_measurement.c
+Making dependency file evel_json_buffer.d for evel_json_buffer.c
+Making dependency file evel_other.d for evel_other.c
+Making dependency file evel_option.d for evel_option.c
+Making dependency file evel_mobile_flow.d for evel_mobile_flow.c
+Making dependency file evel_fault.d for evel_fault.c
+Making dependency file evel_event.d for evel_event.c
+Making dependency file double_list.d for double_list.c
+Making dependency file ring_buffer.d for ring_buffer.c
+Making dependency file metadata.d for metadata.c
+Making dependency file evel.d for evel.c
+Making evel.o from evel.c
+Making metadata.o from metadata.c
+Making ring_buffer.o from ring_buffer.c
+Making double_list.o from double_list.c
+Making evel_event.o from evel_event.c
+Making evel_fault.o from evel_fault.c
+Making evel_mobile_flow.o from evel_mobile_flow.c
+Making evel_option.o from evel_option.c
+Making evel_other.o from evel_other.c
+Making evel_json_buffer.o from evel_json_buffer.c
+Making evel_reporting_measurement.o from evel_reporting_measurement.c
+Making evel_service.o from evel_service.c
+Making evel_signaling.o from evel_signaling.c
+Making evel_scaling_measurement.o from evel_scaling_measurement.c
+Making evel_state_change.o from evel_state_change.c
+Making evel_strings.o from evel_strings.c
+Making evel_syslog.o from evel_syslog.c
+Making evel_throttle.o from evel_throttle.c
+Making evel_internal_event.o from evel_internal_event.c
+Making evel_event_mgr.o from evel_event_mgr.c
+Making evel_logging.o from evel_logging.c
+Making jsmn.o from jsmn.c
+Linking API Shared Library
+Linking API Static Library
+Making evel_demo.o from evel_demo.c
+Making evel_test_control.o from evel_test_control.c
+Linking EVEL demo
+Making EVEL training
+$
+``` 
+You should now be able to run the demo CLI application.  Since it will want to
+dynamically link to the library that you've just made, you will need to set 
+your `LD_LIBRARY_PATH` appropriately first. Make sure that you specify
+your actual directory paths correctly in the following:
+
+```
+$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/centos/evel/libs/x86_64
+$ ../output/x86_64/evel_demo
+evel_demo [--help]
+          --fqdn <domain>
+          --port <port_number>
+          [--path <path>]
+          [--topic <topic>]
+          [--username <username>]
+          [--password <password>]
+          [--https]
+          [--cycles <cycles>]
+          [--nothrott]
+
+Demonstrate use of the ECOMP Vendor Event Listener API.
+
+  -h         Display this usage message.
+  --help
+
+  -f         The FQDN or IP address to the RESTful API.
+  --fqdn
+
+  -n         The port number the RESTful API.
+  --port
+
+  -p         The optional path prefix to the RESTful API.
+  --path
+
+  -t         The optional topic part of the RESTful API.
+  --topic
+
+  -u         The optional username for basic authentication of requests.
+  --username
+
+  -w         The optional password for basic authentication of requests.
+  --password
+
+  -s         Use HTTPS rather than HTTP for the transport.
+  --https
+
+  -c         Loop <cycles> times round the main loop.  Default = 1.
+  --cycles
+
+  -v         Generate much chattier logs.
+  --verbose
+
+  -x         Exclude throttling commands from demonstration.
+  --nothrott
+
+$
+```
+Assuming that all worked as expected, you are ready to start integrating with 
+your application. It probably makes sense to make the LD_LIBRARY_PATH change
+above permanent by incorporating it into your `.bash_profile` file.
+
+### Project Documentation {#qs_build_docs}
+
+The source comes with its own documentation included. The documentation can be
+built using the `docs` target in the Makefile. By default this builds HTML
+and LaTeX documentation, the latter being used to prepare PDFs.
+
+To make the documentation:
+```
+$ cd bldjobs
+$ make docs
+Cleaning docs...
+Making Doxygen documentation
+$ 
+```
+
+There is a make target that is intended to install the documentation on a
+"team server" - it will need adaptation for your team's environment - see the 
+`docs_install` target in the Makefile:
+
+```
+$ make docs_install
+Cleaning docs...
+Making Doxygen documentation
+Copying docs to team web-server...
+Enter passphrase for key '/data/home/.ssh/id_rsa':
+annotated.html                           100% 8088     7.9KB/s   00:00    
+arrowdown.png                            100%  246     0.2KB/s   00:00    
+arrowright.png                           100%  229     0.2KB/s   00:00    
+  ...
+$
+```
+
+# Project Integration {#qs_integrate}
+
+There are two key steps to the integration which have to be undertaken:
+
+  * Initialization/Termination of the library.
+  * Creation & posting of individual events.
+  
+Additionally, it may be necessary to consider changes to the EVEL library's
+source code if assumptions made by the library are either not satisfied or 
+inconvenient.  In particular:
+
+  * If the project already uses libcurl then the global initialization of the
+    library should be removed from the _EVEL Library_.
+  * The _EVEL Library_ uses `syslog` for event logging. If the project uses a
+    different event logging process, then EVEL's event logging macros should be
+    rewritten appropriately.
+
+These steps are considered in the [Normal Use](@ref qs_normal_use) and 
+[EVEL Adaptation](@ref qs_adaptation) sections below.
+
+## Normal Use         {#qs_normal_use}
+
+The _EVEL Library_ should be integrated with your project at a per-process 
+level: each process is an independent client of the ECOMP Vendor Event Listener
+API.
+
+### Initialization {#qs_initialize}
+
+The _EVEL Library_ should be initialized before the process becomes 
+multi-threaded. This constraint arises from the use of libcurl which imposes 
+the constraint that initialization occurs before the system is multi-threaded.
+This is described in more detail in the libcurl documentation for the
+[curl_global_init](https://curl.haxx.se/libcurl/c/curl_global_init.html) 
+function.
+
+Initialization stores configuration of the Vendor Event Listener API's details,
+such as the FQDN or IP address of the service, so the initializing process must
+have either extracted this information from its configuration or have this 
+information "hard-wired" into the application, so that it is available at the 
+point the `evel_initialize()` function is called:
+
+```C
+  #include "evel.h"
+  ...
+  if (evel_initialize(api_fqdn,
+                      api_port,
+                      api_path,
+                      api_topic,
+                      api_secure,
+                      "Alice",
+                      "This isn't very secure!",
+                      EVEL_SOURCE_VIRTUAL_MACHINE,
+                      "EVEL demo client",
+                      verbose_mode))
+  {
+    fprintf(stderr, "Failed to initialize the EVEL library!!!");
+    exit(-1);
+  }
+  ...
+```
+Once initialization has occurred successfully, the application may raise events
+and may also use the logging functions such as EVEL_INFO().
+
+Initialization is entirely local (there is no interaction with the service) so
+it is very unlikely to fail, unless the application environment is seriously 
+degraded.
+
+### Event Generation {#qs_generate}
+
+Generating events is a two stage process:
+
+  1.  Firstly, the _EVEL Library_ is called to allocate an event of the correct
+      type. 
+    * If this is successful, the caller is given a pointer to the event.
+    * All mandatory fields on the event are provided to this factory function
+      and are thereafter immutable.
+    * The application may add any necessary optional fields to the event, using
+      the pointer previously returned.
+  2.  The event is sent to the JSON API using the evel_post_event() function.
+    * At this point, the application relinquishes all responsibility for the 
+      event:
+      * It will be posted to the JSON API, if possible.
+      * Whether or not the posting is successful, the memory used will be 
+        freed.
+        
+In practice this looks like:
+
+```C
+  #include "evel.h"
+  ...
+
+  /***************************************************************************/
+  /* Create a new Fault object, setting mandatory fields as we do so...      */
+  /***************************************************************************/
+  fault = evel_new_fault("My alarm condition",
+                         "It broke very badly",
+                         EVEL_PRIORITY_NORMAL,
+                         EVEL_SEVERITY_MAJOR);
+  if (fault != NULL)
+  {
+    /*************************************************************************/
+    /* We have a Fault object - add some optional fields to it...            */
+    /*************************************************************************/
+    evel_fault_type_set(fault, "Bad things happen...");
+    evel_fault_interface_set(fault, "My Interface Card");
+    evel_fault_addl_info_add(fault, "name1", "value1");
+    evel_fault_addl_info_add(fault, "name2", "value2");
+    
+    /*************************************************************************/
+    /* Finally, post the Fault.  In practice this will only ever fail if     */
+    /* local ring-buffer is full because of event overload.                  */
+    /*************************************************************************/
+    evel_rc = evel_post_event((EVENT_HEADER *)fault);
+    if (evel_rc != EVEL_SUCCESS)
+    {
+      EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+    }
+  }
+  ...
+```
+### Event Types {#qs_event_types}
+
+The _EVEL Library_ supports the following types of events:
+
+  1.  Faults
+  
+      These represent the **fault** domain in the event schema.
+      
+  2.  Measurements
+  
+      These represent the **measurementsForVfScaling** domain in the event
+      schema.
+      
+  3.  Reports
+  
+      This is an experimental type, designed to allow VNFs to report 
+      application-level statistics unencumbered with platform measurements.
+      The formal AT&T schema has been updated to include this experimental
+      type as **measurementsForVfReporting**. 
+
+  4.  Mobile Flow
+
+      These represent the **mobileFlow** domain in the event schema.
+
+  5.  Other
+
+      These represent the **other** domain in the event schema.
+
+  6.  Service Events
+
+      These represent the **serviceEvents** domain in the event schema.
+
+  7.  Signaling
+
+      These represent the **signaling** domain in the event schema.
+
+  8.  State Change
+
+      These represent the **stateChange** domain in the event schema.
+
+  9.  Syslog
+
+      These represent the **syslog** domain in the event schema.
+
+### Throttling {#qs_throttling}
+
+The _EVEL library_ supports the following command types as defined in the JSON API:
+
+  1.  commandType: throttlingSpecification
+
+    This is handled internally by the EVEL library, which stores the provided
+    throttling specification internally and applies it to all subsequent events.
+
+  2. commandType: provideThrottlingState
+
+    This is handled internally by the EVEL library, which returns the current
+    throttling specification for each domain.
+
+  3. commandType: measurementIntervalChange
+
+    This is handled by the EVEL library, which makes the latest measurement
+    interval available via the ::evel_get_measurement_interval function.
+    The application is responsible for checking and adhering to the latest
+    provided interval.
+
+### Termination {#qs_termination}
+
+Termination of the _EVEL Library_ is swift and brutal!  Events in the buffer
+at the time are "dropped on the floor" rather than waiting for the buffer to 
+deplete first.
+
+```C
+  #include "evel.h"
+  ...
+  
+  /***************************************************************************/
+  /* Shutdown the library.                                                   */
+  /***************************************************************************/
+  evel_terminate();
+  
+  ...
+``` 
+
+## EVEL Adaptation       {#qs_adaptation}
+
+The _EVEL Library_ is relatively simple and should be easy to adapt into other
+project environments.
+
+### LibcURL Lifecycle
+
+There are two circumstances where initialization of libcurl may be required:
+
+  1.  If libcurl is used by the project already, and therefore already takes 
+      responsibility of its initialization, then the libcurl initialization and 
+      termination functions should be removed from evel_initialize() and 
+      evel_terminate() respectively.
+  2.  If the project is unable to satisfy the constraint that libcurl 
+      initialization takes place in a single-threaded environment at the point
+      that the _EVEL Library_ can be initialized (for example, if MT code is 
+      necessary to read the configuration parameters required for 
+      _EVEL Library_ initialization) then it may be necessary to extract the 
+      libcurl functions and call them separately, earlier in the program's 
+      operation.
+      
+### Event Logging
+
+The _EVEL Library_ uses `syslog` for logging.  If this is inappropriate then
+the log_debug() and log_initialize() functions should be rewritten accordingly.
+
+**Note**: it would be a really bad idea to use the _EVEL Library_ itself for this 
+logging function. 
+[Turtles all the way down...](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)
+  
+  
\ No newline at end of file
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/readme.md b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/readme.md
new file mode 100644 (file)
index 0000000..2033cfc
--- /dev/null
@@ -0,0 +1,249 @@
+# 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
+
+EVEL_ERR_CODES evel_initialize(const char * const fqdn,
+                               int port,
+                               const char * const bakup_fqdn,
+                               int bakup_port,
+                               const char * const path,
+                               const char * const topic,
+                               int ring_buf_size,
+                               int secure,
+                               const char * const cert_file_path,
+                               const char * const key_file_path,
+                               const char * const ca_info,
+                               const char * const ca_file_path,
+                               long verify_peer,
+                               long verify_host,
+                               const char * const username,
+                               const char * const password,
+                               const char * const bakup_username,
+                               const char * const bakup_password,
+                               const char * const source_ip,
+                               const char * const bakup_source_ip,
+                               EVEL_SOURCE_TYPES source_type,
+                               const char * const role,
+                               int verbosity
+                               )  {
+    fprintf(stderr, "Failed to initialize the EVEL library!!!");
+    exit(-1);
+  }
+
+  ...
+
+  fault = evel_new_fault("My alarm condition",
+                         "It broke very badly",
+                         EVEL_PRIORITY_NORMAL,
+                         EVEL_SEVERITY_MAJOR);
+  if (fault != NULL)
+  {
+    evel_fault_type_set(fault, "Bad things happen...");
+    evel_fault_interface_set(fault, "My Interface Card");
+    evel_fault_addl_info_add(fault, "name1", "value1");
+    evel_fault_addl_info_add(fault, "name2", "value2");
+    evel_rc = evel_post_event((EVENT_HEADER *)fault);
+    if (evel_rc != EVEL_SUCCESS)
+    {
+      EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+    }
+  }
+
+```
+
+The public API to the library is defined in evel.h.  The internal APIs
+within library are defined in separate headers (<em>e.g.</em>
+evel_internal.h), but these should not need to be included by the code
+using the library.
+
+# Example Application
+
+A simple command-line application to generate events is provided as part of
+the source package (the above code fragment is taken from that application).
+
+The following illustrates its operation to a co-located "test-collector":
+```
+$ ./evel_demo --fqdn 127.0.0.1 --port 30000 --path vendor_event_listener --topic example_vnf --verbose
+./evel_demo built Feb 26 2016 18:14:48
+* About to connect() to 169.254.169.254 port 80 (#0)
+*   Trying 169.254.169.254... * Timeout
+* connect() timed out!
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+*   Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 510
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+< 
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+*   Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 865
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+< 
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+*   Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 2325
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+< 
+* Closing connection #0
+^C
+
+Interrupted - quitting!
+$
+```
+
+# Restrictions and Limitations
+
+## Constraint Validation
+
+The _EVEL Library_ has been designed to be production-safe code with the
+emphasis at this stage being in correctness of operation rather than
+raw performance.
+
+The API tries to check as much information as possible to avoid misuse and
+will **assert()** if constraints are not satisfied.  This is likely to lead
+to the rapid discovery of coding errors by programmers, but does mean that
+the application can fail abruptly if the library is misused in any way.
+
+## Performance
+
+The default Makefile avoids aggressive optimizations so that any core-files
+are easy to interpret.  Production code should use greater optimization
+levels.
+
+As described above, the HTTP client is single threaded and will run all
+transactions synchronously.  As transactions are serialized, a client that
+generates a lot of events will be paced by the round-trip time.
+
+It would be a straightforward enhancement to use the multi-thread API into
+libcurl and use a pool of client threads to run transactions in parallel if
+this ever became a bottleneck.
+
+## Logging
+
+The initialization of the library includes the log verbosity.  The verbose
+operation makes the library very chatty so syslog may get rather clogged
+with detailed diagnostics.  It is possible to configure syslog to put these
+events into a separate file.  A trivial syslog.conf file would be:
+
+```
+
+# Log all user messages so debug information is captured.
+
+user.*      /var/log/debug
+```
+
+If verbose logging is enabled, the cURL library will generate information 
+about the HTTP operations on **stdout**. 
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/ring_buffer.c b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/ring_buffer.c
new file mode 100644 (file)
index 0000000..248baf2
--- /dev/null
@@ -0,0 +1,193 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Unless otherwise specified, all software contained herein is
+ * 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.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ****************************************************************************/
+/**************************************************************************//**
+ * @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;
+      pthread_mutex_unlock(&buffer->ring_mutex);
+      EVEL_DEBUG("RBR: next read location is %d data %lp", buffer->next_read,msg);
+      return msg;
+    }
+    else
+    {
+      EVEL_DEBUG("RBR: Waiting for condition variable");
+      pthread_cond_wait(&buffer->ring_cv, &buffer->ring_mutex);
+      EVEL_DEBUG("RBR: Condition variable wait completed");
+    }
+  }
+  pthread_mutex_unlock(&buffer->ring_mutex);
+  return msg;
+}
+
+/**************************************************************************//**
+ * Write an element into a ring_buffer.
+ *
+ * Writes an element into the ring_buffer, advancing the next-write position.
+ * Operation is synchronized and therefore MT-safe.  Fails if the buffer is
+ * full without blocking.
+ *
+ * @param   buffer  Pointer to the ring-buffer to be written.
+ * @param   msg     Pointer to data to be stored in the ring_buffer.
+ *
+ * @returns Number of items written.
+ * @retval  1       The data was written successfully.
+ * @retval  0       The ring_buffer was full so no data written.
+******************************************************************************/
+int ring_buffer_write(ring_buffer * buffer, void * msg)
+{
+  int item_count = 0;
+  int items_written = 0;
+  EVEL_DEBUG("RBW: Ring Buffer Write message at %lp", msg);
+
+  pthread_mutex_lock(&buffer->ring_mutex);
+  EVEL_DEBUG("RBW: got lock. NR=%d NW=%d SZ=%d",
+             buffer->next_read,
+             buffer->next_write,
+             buffer->size);
+
+  item_count = (buffer->next_write - buffer->next_read) % buffer->size;
+  if (item_count < 0)
+  {
+    item_count += buffer->size;
+  }
+  if (item_count < buffer->size - 1)
+  {
+    EVEL_DEBUG("RBW: %d items in buffer", item_count);
+    buffer->ring[buffer->next_write] = msg;
+    buffer->next_write = (buffer->next_write + 1) % buffer->size;
+    EVEL_DEBUG("RBW: next write location is %d", buffer->next_write);
+    items_written = 1;
+  }
+  else
+  {
+    EVEL_ERROR("RBW: ring buffer full - unable to write event");
+  }
+
+  pthread_mutex_unlock(&buffer->ring_mutex);
+  EVEL_DEBUG("RBW: released lock");
+  pthread_cond_signal(&buffer->ring_cv);
+
+  return items_written;
+}
+
+/**************************************************************************//**
+ * Tests whether there is data in the ring_buffer.
+ *
+ * Tests whether there is currently data in the ring_buffer without blocking.
+ *
+ * @param   buffer  Pointer to the ring-buffer to be tested.
+ *
+ * @returns Whether there is data in the ring_buffer.
+ * @retval  0       There isn't any data in the ring_buffer.
+ * @retval  1       There is data in the ring_buffer.
+******************************************************************************/
+int ring_buffer_is_empty(ring_buffer * buffer)
+{
+  int is_empty = 0;
+  EVEL_DEBUG("RBE: Ring empty check");
+
+  pthread_mutex_lock(&buffer->ring_mutex);
+  is_empty = (buffer->next_read == buffer->next_write);
+  pthread_mutex_unlock(&buffer->ring_mutex);
+
+  EVEL_DEBUG("RBE: Ring state= %d", is_empty);
+  return is_empty;
+}
+
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/ring_buffer.h b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/code/evel_library/ring_buffer.h
new file mode 100644 (file)
index 0000000..1236b78
--- /dev/null
@@ -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/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/docs/source/evel/README b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/docs/source/evel/README
new file mode 100644 (file)
index 0000000..89e7a3a
--- /dev/null
@@ -0,0 +1 @@
+Generated source code documentation.
\ No newline at end of file
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/aarch64/libevel.a b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/aarch64/libevel.a
new file mode 100755 (executable)
index 0000000..a3783ee
Binary files /dev/null and b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/aarch64/libevel.a differ
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/README b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/README
new file mode 100644 (file)
index 0000000..760fdc1
--- /dev/null
@@ -0,0 +1 @@
+Generated libraries.
\ No newline at end of file
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.a b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.a
new file mode 100755 (executable)
index 0000000..5470cd5
Binary files /dev/null and b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.a differ
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.so b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.so
new file mode 100755 (executable)
index 0000000..5470cd5
Binary files /dev/null and b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/libs/x86_64/libevel.so differ
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/output/x86_64/README b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/output/x86_64/README
new file mode 100644 (file)
index 0000000..d1c9f1f
--- /dev/null
@@ -0,0 +1 @@
+Generated executables.
\ No newline at end of file
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/readme.md b/vnfs/VESreporting_vFW5.0_DANOS/evel/evel-library/readme.md
new file mode 100644 (file)
index 0000000..65ce4ef
--- /dev/null
@@ -0,0 +1,28 @@
+# ECOMP Vendor Event Listener Library
+
+This project contains a C library that supports interfacing to AT&T's ECOMP
+Vendor Event Listener. For an overview of ECOMP, see the 
+[ECOMP White Paper](http://att.com/ECOMP).
+
+Developed in 2016 for AT&T by:
+ * Alok Gupta (https://github.com/ag1367)
+ * Paul Potochniak (https://github.com/pp8491)
+ * Gayathri Patrachari(https://github.com/gp2421)
+
+Current Maintainers: 
+ * Alok Gupta (https://github.com/ag1367)
+ * Paul Potochniak (https://github.com/pp8491)
+ * Gayathri Patrachari(https://github.com/gp2421)
+
+# Installation
+
+For installation instructions, clone this repo and load the 
+[installation guide](./docs/source/evel/html/quickstart.html) in your web browser.
+
+Full source-code documentation is included with the code and can be built from 
+the included Makefile. See the [readme file](./code/evel_library/readme.md).
+
+# Use
+
+Clone this repo and load the [user guide](./docs/source/evel/html/index.html)
+in your web browser.
\ No newline at end of file
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/log_file b/vnfs/VESreporting_vFW5.0_DANOS/log_file
new file mode 100644 (file)
index 0000000..08eaca5
--- /dev/null
@@ -0,0 +1,599 @@
+2020/04/22 21:57:38 pulling environment registry.hub.docker.com/jsouthworth/danos-buildpackage:1908
+{"status":"Pulling from jsouthworth/danos-buildpackage","id":"1908"}\r
+{"status":"Digest: sha256:a412799a35cf331b9d1e74fa1fac373ebd942bad1911f3045f89dc2e8f634f7d"}\r
+{"status":"Status: Image is up to date for registry.hub.docker.com/jsouthworth/danos-buildpackage:1908"}\r
+2020/04/22 21:57:38 creating environment registry.hub.docker.com/jsouthworth/danos-buildpackage:1908
+2020/04/22 21:57:38 containerID 8fbe0bf389490690698f807a7224d975619f7fd776444985578b42a9dc98ede8
+2020/04/22 21:57:38 building package 8fbe0bf389490690698f807a7224d975619f7fd776444985578b42a9dc98ede8
+cp: cannot stat '/mnt/pkgs/*.deb': No such file or directory
+/tmp/pkgs /build/src
+dpkg-scanpackages: info: Wrote 0 entries to output Packages file.
+/build/src
+Get:1 file:/tmp/pkgs  InRelease
+Ign:1 file:/tmp/pkgs  InRelease
+Get:2 file:/tmp/pkgs  Release
+Ign:2 file:/tmp/pkgs  Release
+Get:3 file:/tmp/pkgs  Packages
+Ign:3 file:/tmp/pkgs  Packages
+Get:3 file:/tmp/pkgs  Packages
+Ign:3 file:/tmp/pkgs  Packages
+Get:3 file:/tmp/pkgs  Packages
+Ign:3 file:/tmp/pkgs  Packages
+Get:3 file:/tmp/pkgs  Packages [20 B]
+Get:4 http://security.debian.org/debian-security stretch/updates InRelease [94.3 kB]
+Ign:5 http://deb.debian.org/debian stretch InRelease
+Get:6 http://deb.debian.org/debian stretch-updates InRelease [91.0 kB]
+Get:7 http://deb.debian.org/debian stretch Release [118 kB]
+Get:8 http://deb.debian.org/debian stretch Release.gpg [2410 B]
+Hit:9 http://s3-us-west-1.amazonaws.com/repos.danosproject.org/standard 1908 InRelease
+Get:10 http://security.debian.org/debian-security stretch/updates/main amd64 Packages [521 kB]
+Hit:11 http://s3-us-west-1.amazonaws.com/repos.danosproject.org/bootstrap 1908 InRelease
+Get:12 http://deb.debian.org/debian stretch-updates/main amd64 Packages.diff/Index [13.0 kB]
+Get:13 http://deb.debian.org/debian stretch-updates/main amd64 Packages 2020-02-23-2017.41.pdiff [1539 B]
+Get:13 http://deb.debian.org/debian stretch-updates/main amd64 Packages 2020-02-23-2017.41.pdiff [1539 B]
+Get:14 http://deb.debian.org/debian stretch/main amd64 Packages [7083 kB]
+Fetched 7925 kB in 4s (1862 kB/s)
+Reading package lists...
+dh_testdir
+dh_testroot
+dh_prep
+dh_testdir
+dh_testroot
+dh_install
+dh_install: Compatibility levels before 9 are deprecated (level 7 in use)
+dh_installdocs
+dh_installdocs: Compatibility levels before 9 are deprecated (level 7 in use)
+dh_installchangelogs
+dh_compress
+dh_fixperms
+dh_installdeb
+dh_installdeb: Compatibility levels before 9 are deprecated (level 7 in use)
+dh_gencontrol
+dh_md5sums
+dh_builddeb
+dpkg-deb: building package 'vpp-measurement-reporter-danos-build-deps' in '../vpp-measurement-reporter-danos-build-deps_0.1_all.deb'.
+
+The package has been created.
+Attention, the package has been created in the current directory,
+not in ".." as indicated by the message above!
+Selecting previously unselected package vpp-measurement-reporter-danos-build-deps.
+(Reading database ... 26880 files and directories currently installed.)
+Preparing to unpack vpp-measurement-reporter-danos-build-deps_0.1_all.deb ...
+Unpacking vpp-measurement-reporter-danos-build-deps (0.1) ...
+Reading package lists...
+Building dependency tree...
+Reading state information...
+Correcting dependencies...Starting pkgProblemResolver with broken count: 0
+Starting 2 pkgProblemResolver with broken count: 0
+Done
+ Done
+Starting pkgProblemResolver with broken count: 0
+Starting 2 pkgProblemResolver with broken count: 0
+Done
+The following additional packages will be installed:
+  libcurl3 libcurl4-openssl-dev libjansson4 liburiparser1 libvyatta-cfg-dev
+  libvyatta-cfg1 libvyatta-util1
+Suggested packages:
+  libcurl4-doc libcurl3-dbg libidn11-dev libkrb5-dev libldap2-dev librtmp-dev
+  libssh2-1-dev libssl1.0-dev | libssl-dev pkg-config zlib1g-dev
+Recommended packages:
+  configd
+The following NEW packages will be installed:
+  libcurl3 libcurl4-openssl-dev libjansson4 liburiparser1 libvyatta-cfg-dev
+  libvyatta-cfg1 libvyatta-util1
+0 upgraded, 7 newly installed, 0 to remove and 24 not upgraded.
+1 not fully installed or removed.
+Need to get 939 kB of archives.
+After this operation, 3527 kB of additional disk space will be used.
+Get:1 http://deb.debian.org/debian stretch/main amd64 libjansson4 amd64 2.9-1 [28.1 kB]
+Get:2 http://deb.debian.org/debian stretch/main amd64 liburiparser1 amd64 0.8.4-1+deb9u1 [42.2 kB]
+Get:3 http://security.debian.org/debian-security stretch/updates/main amd64 libcurl3 amd64 7.52.1-5+deb9u10 [292 kB]
+Get:4 http://security.debian.org/debian-security stretch/updates/main amd64 libcurl4-openssl-dev amd64 7.52.1-5+deb9u10 [375 kB]
+Get:5 http://s3-us-west-1.amazonaws.com/repos.danosproject.org/standard 1908/main amd64 libvyatta-util1 amd64 0.29 [8792 B]
+Get:6 http://s3-us-west-1.amazonaws.com/repos.danosproject.org/standard 1908/main amd64 libvyatta-cfg1 amd64 1.23.1.1 [70.3 kB]
+Get:7 http://s3-us-west-1.amazonaws.com/repos.danosproject.org/standard 1908/main amd64 libvyatta-cfg-dev amd64 1.23.1.1 [123 kB]
+debconf: delaying package configuration, since apt-utils is not installed
+Fetched 939 kB in 0s (2048 kB/s)
+Selecting previously unselected package libjansson4:amd64.\r
+(Reading database ... \r(Reading database ... 5%\r(Reading database ... 10%\r(Reading database ... 15%\r(Reading database ... 20%\r(Reading database ... 25%\r(Reading database ... 30%\r(Reading database ... 35%\r(Reading database ... 40%\r(Reading database ... 45%\r(Reading database ... 50%\r(Reading database ... 55%\r(Reading database ... 60%\r(Reading database ... 65%\r(Reading database ... 70%\r(Reading database ... 75%\r(Reading database ... 80%\r(Reading database ... 85%\r(Reading database ... 90%\r(Reading database ... 95%\r(Reading database ... 100%\r(Reading database ... 26884 files and directories currently installed.)\r
+Preparing to unpack .../0-libjansson4_2.9-1_amd64.deb ...\r
+Unpacking libjansson4:amd64 (2.9-1) ...\r
+Selecting previously unselected package liburiparser1:amd64.\r
+Preparing to unpack .../1-liburiparser1_0.8.4-1+deb9u1_amd64.deb ...\r
+Unpacking liburiparser1:amd64 (0.8.4-1+deb9u1) ...\r
+Selecting previously unselected package libvyatta-util1.\r
+Preparing to unpack .../2-libvyatta-util1_0.29_amd64.deb ...\r
+Unpacking libvyatta-util1 (0.29) ...\r
+Selecting previously unselected package libvyatta-cfg1.\r
+Preparing to unpack .../3-libvyatta-cfg1_1.23.1.1_amd64.deb ...\r
+Unpacking libvyatta-cfg1 (1.23.1.1) ...\r
+Selecting previously unselected package libvyatta-cfg-dev.\r
+Preparing to unpack .../4-libvyatta-cfg-dev_1.23.1.1_amd64.deb ...\r
+Unpacking libvyatta-cfg-dev (1.23.1.1) ...\r
+Selecting previously unselected package libcurl3:amd64.\r
+Preparing to unpack .../5-libcurl3_7.52.1-5+deb9u10_amd64.deb ...\r
+Unpacking libcurl3:amd64 (7.52.1-5+deb9u10) ...\r
+Selecting previously unselected package libcurl4-openssl-dev:amd64.\r
+Preparing to unpack .../6-libcurl4-openssl-dev_7.52.1-5+deb9u10_amd64.deb ...\r
+Unpacking libcurl4-openssl-dev:amd64 (7.52.1-5+deb9u10) ...\r
+Setting up libcurl3:amd64 (7.52.1-5+deb9u10) ...\r
+Setting up libjansson4:amd64 (2.9-1) ...\r
+Processing triggers for libc-bin (2.24-11+deb9u4) ...\r
+Processing triggers for man-db (2.7.6.1-2) ...\r
+Setting up libcurl4-openssl-dev:amd64 (7.52.1-5+deb9u10) ...\r
+Setting up liburiparser1:amd64 (0.8.4-1+deb9u1) ...\r
+Setting up libvyatta-util1 (0.29) ...\r
+Setting up libvyatta-cfg1 (1.23.1.1) ...\r
+Setting up libvyatta-cfg-dev (1.23.1.1) ...\r
+Setting up vpp-measurement-reporter-danos-build-deps (0.1) ...\r
+Processing triggers for libc-bin (2.24-11+deb9u4) ...\r
+ dpkg-buildpackage -rfakeroot -us -uc -i -b
+dpkg-buildpackage: info: source package vpp-measurement-reporter-danos
+dpkg-buildpackage: info: source version 0.1
+dpkg-buildpackage: info: source distribution unstable
+dpkg-buildpackage: info: source changed by Brian Freeman <bf1936@att.com>
+ dpkg-source -i --before-build src
+dpkg-buildpackage: info: host architecture amd64
+ fakeroot debian/rules clean
+dh --list
+autoreconf
+autotools-dev
+bash-completion
+build-stamp
+perl-openssl
+pypy
+python-support
+python2
+python3
+systemd
+xml-core
+ls /build/src/evel/evel-library/libs/x86_64
+README
+libevel.a
+libevel.so
+ls /usr/lib/
+apt
+compat-ld
+dpkg
+exim4
+file
+gcc
+gettext
+git-core
+gnupg
+gnupg2
+gold-ld
+groff
+ldscripts
+libCfgClient.a
+libCfgClient.so
+libCfgClientPerl.a
+libCfgClientPerl.so
+libgettextlib-0.19.8.1.so
+libgettextsrc-0.19.8.1.so
+libgsasl.so.7
+libgsasl.so.7.9.6
+libvyatta-config.a
+libvyatta-config.so
+libvyatta-config.so.1
+libvyatta-config.so.1.0.0
+libvyatta-cstore-compat.a
+libvyatta-cstore-compat.so
+libvyatta-cstore-compat.so.1
+libvyatta-cstore-compat.so.1.0.0
+libvyatta-util.so.1
+libvyatta-util.so.1.0.0
+locale
+man-db
+mime
+openssh
+os-release
+preloadable_libintl.so
+python2.7
+python3
+python3.5
+sasl2
+sendmail
+ssl
+systemd
+tar
+tc
+tmpfiles.d
+valgrind
+x86_64-linux-gnu
+ls 
+LICENSE.TXT
+Makefile
+README.md
+debian
+dep.xml
+evel
+junk
+log_file
+onap-ca.crt
+pom.xml
+target
+vpp-measurement-reporter-danos-build-deps_0.1_all.deb
+vpp-measurement-reporter-danos.c
+dh clean --with=systemd
+   dh_testdir
+   dh_auto_clean
+       make -j1 clean
+make[1]: Entering directory '/build/src'
+rm -f vpp-measurement-reporter-danos
+make[1]: Leaving directory '/build/src'
+   dh_clean
+ debian/rules build
+dh --list
+autoreconf
+autotools-dev
+bash-completion
+build-stamp
+perl-openssl
+pypy
+python-support
+python2
+python3
+systemd
+xml-core
+ls /build/src/evel/evel-library/libs/x86_64
+README
+libevel.a
+libevel.so
+ls /usr/lib/
+apt
+compat-ld
+dpkg
+exim4
+file
+gcc
+gettext
+git-core
+gnupg
+gnupg2
+gold-ld
+groff
+ldscripts
+libCfgClient.a
+libCfgClient.so
+libCfgClientPerl.a
+libCfgClientPerl.so
+libgettextlib-0.19.8.1.so
+libgettextsrc-0.19.8.1.so
+libgsasl.so.7
+libgsasl.so.7.9.6
+libvyatta-config.a
+libvyatta-config.so
+libvyatta-config.so.1
+libvyatta-config.so.1.0.0
+libvyatta-cstore-compat.a
+libvyatta-cstore-compat.so
+libvyatta-cstore-compat.so.1
+libvyatta-cstore-compat.so.1.0.0
+libvyatta-util.so.1
+libvyatta-util.so.1.0.0
+locale
+man-db
+mime
+openssh
+os-release
+preloadable_libintl.so
+python2.7
+python3
+python3.5
+sasl2
+sendmail
+ssl
+systemd
+tar
+tc
+tmpfiles.d
+valgrind
+x86_64-linux-gnu
+ls 
+LICENSE.TXT
+Makefile
+README.md
+debian
+dep.xml
+evel
+junk
+log_file
+onap-ca.crt
+pom.xml
+target
+vpp-measurement-reporter-danos-build-deps_0.1_all.deb
+vpp-measurement-reporter-danos.c
+dh build --with=systemd
+   dh_testdir
+   dh_update_autotools_config
+   dh_auto_configure
+   dh_auto_build
+       make -j1
+make[1]: Entering directory '/build/src'
+make -C /build/src/evel/evel-library/bldjobs  all
+make[2]: Entering directory '/build/src/evel/evel-library/bldjobs'
+Making dependency file jsmn.d for jsmn.c
+Making dependency file evel_batch.d for evel_batch.c
+Making dependency file evel_logging.d for evel_logging.c
+Making dependency file evel_voicequality.d for evel_voicequality.c
+Making dependency file evel_threshold_cross.d for evel_threshold_cross.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_sipsignaling.d for evel_sipsignaling.c
+Making dependency file evel_heartbeat_fields.d for evel_heartbeat_fields.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_jsonobject.d for evel_jsonobject.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 hashtable.d for hashtable.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
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel.c: In function 'evel_free_event':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel.c:458:7: warning: implicit declaration of function 'evel_free_hrtbt_field' [-Wimplicit-function-declaration]
+       evel_free_hrtbt_field((EVENT_HEARTBEAT_FIELD *)evt_ptr);
+       ^~~~~~~~~~~~~~~~~~~~~
+Making metadata.o from metadata.c
+Making ring_buffer.o from ring_buffer.c
+Making double_list.o from double_list.c
+Making hashtable.o from hashtable.c
+Making evel_event.o from evel_event.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event.c: In function 'evel_json_encode_eventtype':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event.c:649:11: warning: implicit declaration of function 'evel_json_encode_voice_quality' [-Wimplicit-function-declaration]
+           evel_json_encode_voice_quality(jbuf, (EVENT_VOICE_QUALITY *)event);
+           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event.c:653:11: warning: implicit declaration of function 'evel_json_encode_threshold_cross' [-Wimplicit-function-declaration]
+           evel_json_encode_threshold_cross(jbuf, (EVENT_THRESHOLD_CROSS *)event);
+           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Making evel_fault.o from evel_fault.c
+Making evel_mobile_flow.o from evel_mobile_flow.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_mobile_flow.c: In function 'evel_json_encode_mobile_flow':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_mobile_flow.c:965:12: warning: implicit declaration of function 'evel_throttle_suppress_nv_pair' [-Wimplicit-function-declaration]
+       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Making evel_option.o from evel_option.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_option.c: In function 'evel_force_option_intheader':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_option.c:393:18: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
+   option->object = value;
+                  ^
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_option.c: In function 'evel_set_option_intheader':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_option.c:426:20: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
+     option->object = value;
+                    ^
+Making evel_jsonobject.o from evel_jsonobject.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_jsonobject.c: In function 'evel_new_jsonobjinstance':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_jsonobject.c:99:14: warning: unused variable 'key' [-Wunused-variable]
+   jsmntok_t *key;
+              ^~~
+Making evel_other.o from evel_other.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c: In function 'evel_other_field_add_namedarray':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:172:46: warning: passing argument 2 of 'ht_get' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
+   list = (DLIST *)ht_get(other->namedarrays, hashname);
+                                              ^~~~~~~~
+In file included from /build/src/evel/evel-library/bldjobs/../code/evel_library/evel.h:44:0,
+                 from /build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:29:
+/build/src/evel/evel-library/bldjobs/../code/evel_library/hashtable.h:95:7: note: expected 'char *' but argument is of type 'const char *'
+ void *ht_get( HASHTABLE_T *hashtable, char *key );
+       ^~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:178:33: warning: passing argument 2 of 'ht_set' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
+      ht_set(other->namedarrays, hashname,(void*)nlist);
+                                 ^~~~~~~~
+In file included from /build/src/evel/evel-library/bldjobs/../code/evel_library/evel.h:44:0,
+                 from /build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:29:
+/build/src/evel/evel-library/bldjobs/../code/evel_library/hashtable.h:86:6: note: expected 'char *' but argument is of type 'const char *'
+ void ht_set( HASHTABLE_T *hashtable, char *key, void *value );
+      ^~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c: In function 'evel_json_encode_other':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:302:27: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
+         for( idx = 0; idx < ht->size; idx++ ) {
+                           ^
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:347:25: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
+     if(jsonobjp != NULL);
+                         ^
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:347:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
+     if(jsonobjp != NULL);
+     ^~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:348:5: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if'
+     {
+     ^
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:361:15: warning: implicit declaration of function 'evel_enc_kv_object' [-Wimplicit-function-declaration]
+               evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring);
+               ^~~~~~~~~~~~~~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:366:10: warning: variable 'item_added3' set but not used [-Wunused-but-set-variable]
+     bool item_added3 = false;
+          ^~~~~~~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:277:8: warning: unused variable 'itm_added' [-Wunused-variable]
+   bool itm_added = false;
+        ^~~~~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c: In function 'evel_free_other':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_other.c:474:16: warning: unused variable 'other_field_item' [-Wunused-variable]
+   DLIST_ITEM * other_field_item = NULL;
+                ^~~~~~~~~~~~~~~~
+Making evel_json_buffer.o from evel_json_buffer.c
+Making evel_reporting_measurement.o from evel_reporting_measurement.c
+Making evel_heartbeat_fields.o from evel_heartbeat_fields.c
+Making evel_sipsignaling.o from evel_sipsignaling.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_sipsignaling.c: In function 'evel_json_encode_signaling':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_sipsignaling.c:485:3: warning: implicit declaration of function 'evel_json_encode_vendor_field' [-Wimplicit-function-declaration]
+   evel_json_encode_vendor_field(jbuf, &event->vnfname_field);
+   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Making evel_scaling_measurement.o from evel_scaling_measurement.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_scaling_measurement.c: In function 'evel_json_encode_measurement':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_scaling_measurement.c:3140:15: warning: implicit declaration of function 'evel_enc_kv_object' [-Wimplicit-function-declaration]
+               evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring);
+               ^~~~~~~~~~~~~~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_scaling_measurement.c:3145:10: warning: variable 'item_added3' set but not used [-Wunused-but-set-variable]
+     bool item_added3 = false;
+          ^~~~~~~~~~~
+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
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event_mgr.c: In function 'evel_send_to_another_collector':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event_mgr.c:1020:12: warning: variable 'curl_rc' set but not used [-Wunused-but-set-variable]
+   CURLcode curl_rc;
+            ^~~~~~~
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event_mgr.c: In function 'event_handler':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_event_mgr.c:1196:15: warning: implicit declaration of function 'sleep' [-Wimplicit-function-declaration]
+               sleep(EVEL_COLLECTOR_RECONNECTION_WAIT_TIME);
+               ^~~~~
+Making evel_threshold_cross.o from evel_threshold_cross.c
+Making evel_voicequality.o from evel_voicequality.c
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_voicequality.c: In function 'evel_json_encode_voice_quality':
+/build/src/evel/evel-library/bldjobs/../code/evel_library/evel_voicequality.c:489:3: warning: implicit declaration of function 'evel_json_encode_vendor_field' [-Wimplicit-function-declaration]
+   evel_json_encode_vendor_field(jbuf, &event->vendorVnfNameFields);
+   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Making evel_logging.o from evel_logging.c
+Making evel_batch.o from evel_batch.c
+Making jsmn.o from jsmn.c
+Linking API Shared Library
+Linking API Static Library
+make[2]: Leaving directory '/build/src/evel/evel-library/bldjobs'
+gcc  -Wall -g -fPIC -o vpp-measurement-reporter-danos \
+                                    -L /build/src/evel/evel-library/libs/x86_64 \
+                                    -I /build/src/evel/evel-library/code/evel_library \
+                               vpp-measurement-reporter-danos.c \
+                              -lpthread \
+                              -level \
+                     -lvyatta-config \
+                              -lcurl
+ls -l /build/src/evel/evel-library/libs
+total 8
+drwxr-xr-x 2 builduser builduser 4096 Apr 22 21:57 aarch64
+drwxr-xr-x 2 builduser builduser 4096 Apr 22 21:58 x86_64
+ls -l /build/src/evel/evel-library/libs/x86_64/
+total 1148
+-rw-r--r-- 1 builduser builduser     20 Apr 22 21:57 README
+-rwxr-xr-x 1 builduser builduser 582096 Apr 22 21:58 libevel.a
+-rwxr-xr-x 1 builduser builduser 582096 Apr 22 21:58 libevel.so
+ls -l
+total 88
+-rw-r--r-- 1 builduser builduser  1059 Apr 22 21:57 LICENSE.TXT
+-rw-r--r-- 1 builduser builduser  2089 Apr 22 21:57 Makefile
+-rw-r--r-- 1 builduser builduser  1534 Apr 22 21:57 README.md
+drwxr-xr-x 3 builduser builduser  4096 Apr 22 21:57 debian
+-rw-r--r-- 1 builduser builduser   759 Apr 22 21:57 dep.xml
+drwxr-xr-x 3 builduser builduser  4096 Apr 22 21:57 evel
+-rw-r--r-- 1 builduser builduser   527 Apr 22 21:57 junk
+-rw-r--r-- 1 builduser builduser  2219 Apr 22 21:57 log_file
+-rw-r--r-- 1 builduser builduser  6124 Apr 22 21:57 onap-ca.crt
+-rw-r--r-- 1 builduser builduser  2747 Apr 22 21:57 pom.xml
+drwxr-xr-x 4 builduser builduser  4096 Apr 22 21:57 target
+-rwxr-xr-x 1 builduser builduser 24184 Apr 22 21:58 vpp-measurement-reporter-danos
+-rw-r--r-- 1 root      root       2050 Apr 22 21:57 vpp-measurement-reporter-danos-build-deps_0.1_all.deb
+-rw-r--r-- 1 builduser builduser 10104 Apr 22 21:57 vpp-measurement-reporter-danos.c
+make[1]: Leaving directory '/build/src'
+   dh_auto_test
+   create-stamp debian/debhelper-build-stamp
+ fakeroot debian/rules binary
+dh --list
+autoreconf
+autotools-dev
+bash-completion
+build-stamp
+perl-openssl
+pypy
+python-support
+python2
+python3
+systemd
+xml-core
+ls /build/src/evel/evel-library/libs/x86_64
+README
+libevel.a
+libevel.so
+ls /usr/lib/
+apt
+compat-ld
+dpkg
+exim4
+file
+gcc
+gettext
+git-core
+gnupg
+gnupg2
+gold-ld
+groff
+ldscripts
+libCfgClient.a
+libCfgClient.so
+libCfgClientPerl.a
+libCfgClientPerl.so
+libgettextlib-0.19.8.1.so
+libgettextsrc-0.19.8.1.so
+libgsasl.so.7
+libgsasl.so.7.9.6
+libvyatta-config.a
+libvyatta-config.so
+libvyatta-config.so.1
+libvyatta-config.so.1.0.0
+libvyatta-cstore-compat.a
+libvyatta-cstore-compat.so
+libvyatta-cstore-compat.so.1
+libvyatta-cstore-compat.so.1.0.0
+libvyatta-util.so.1
+libvyatta-util.so.1.0.0
+locale
+man-db
+mime
+openssh
+os-release
+preloadable_libintl.so
+python2.7
+python3
+python3.5
+sasl2
+sendmail
+ssl
+systemd
+tar
+tc
+tmpfiles.d
+valgrind
+x86_64-linux-gnu
+ls 
+LICENSE.TXT
+Makefile
+README.md
+debian
+dep.xml
+evel
+junk
+log_file
+onap-ca.crt
+pom.xml
+target
+vpp-measurement-reporter-danos
+vpp-measurement-reporter-danos-build-deps_0.1_all.deb
+vpp-measurement-reporter-danos.c
+dh binary --with=systemd
+   create-stamp debian/debhelper-build-stamp
+   dh_testroot
+   dh_prep
+   dh_auto_install
+   dh_install
+Segmentation fault
+/build/src/vpp-measurement-reporter-danos: error while loading shared libraries: libevel.so: cannot open shared object file: No such file or directory
+dh_install: debian/vpp-measurement-reporter-danos.install (executable config) returned exit code 127
+debian/rules:7: recipe for target 'binary' failed
+make: *** [binary] Error 127
+dpkg-buildpackage: error: fakeroot debian/rules binary gave error exit status 2
+debuild: fatal error at line 1116:
+dpkg-buildpackage -rfakeroot -us -uc -i -b failed
+cp: cannot stat '../*.deb': No such file or directory
+2020/04/22 21:58:07 deleting environment 8fbe0bf389490690698f807a7224d975619f7fd776444985578b42a9dc98ede8
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/onap-ca.crt b/vnfs/VESreporting_vFW5.0_DANOS/onap-ca.crt
new file mode 100644 (file)
index 0000000..51e19b5
--- /dev/null
@@ -0,0 +1,100 @@
+-----BEGIN CERTIFICATE-----
+MIIFpTCCA42gAwIBAgIJAJqx8dKnCZZoMA0GCSqGSIb3DQEBCwUAMIG9MQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCTkoxEzARBgNVBAcMCkJlZG1pbnN0ZXIxEjAQBgNV
+BAoMCU9wZW5FQ09NUDETMBEGA1UECwwKc2ltcGxlZGVtbzE6MDgGA1UEAwwxT3Bl
+bkVDT01QIHNpbXBsZWRlbW8gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEn
+MCUGCSqGSIb3DQEJARYYc2ltcGxlZGVtb0BvcGVuZWNvbXAub3JnMB4XDTE2MTEy
+ODIxMTQyNloXDTIxMTEyNzIxMTQyNlowga0xCzAJBgNVBAYTAlVTMQswCQYDVQQI
+DAJOSjETMBEGA1UEBwwKQmVkbWluc3RlcjESMBAGA1UECgwJT3BlbkVDT01QMRMw
+EQYDVQQLDApzaW1wbGVkZW1vMSowKAYDVQQDDCFPcGVuRUNPTVAgc2ltcGxlZGVt
+byBTZXJ2ZXIgQ0EgWDExJzAlBgkqhkiG9w0BCQEWGHNpbXBsZWRlbW9Ab3BlbmVj
+b21wLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr4rivKQuRk
+YNf5Ig40e1nqj6s6LB1vgMOYbKfRziOFpPcUpsHPOhusHowiUsrU1vdFSzPz6Ej7
+PjlmNSg2Qka8YCn9kd6QgM7U0KcPJvIucBp+qjifH3EvP0jgDPhDeVRYxzV454dv
+5kQ9uCpswJP7YAnX51dkWeH8nwPUoagt31bOl9LXENSrgxEThxdLYMJnQJWk2CmV
+otXM4tT1dxyJxFUrZ6uJCEAYw5VtlplqihHf8lHy+sWQavtsLz/4dc+sGeXSTfoI
+voKvoh3uZ5gEhGV8yfJxk1veX5y5/AxP80vQ+smWYjTnQL5QQ57y4bciez4XVBmQ
+SWimWtOi4e8CAwEAAaOBtTCBsjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBhjAdBgNVHQ4EFgQUTqdsYgGNGubdJHq9tsaJhM9HE5wwcAYDVR0gBGkwZzBl
+BgRVHSAAMF0wWwYIKwYBBQUHAgIwTxpNSWYgeW91IHRydXN0IHRoaXMgY2VydCB0
+aGVuIHdlIGhhdmUgYSBicmlkZ2UgdGhhdCB5b3UgbWlnaHQgYmUgaW50ZXJlc3Rl
+ZCBpbi4wDQYJKoZIhvcNAQELBQADggIBAKNNlRqFuE/JgV1BHyYK0xoSXH4aZP/7
+IoHtDVcSaZAOOuFOUrwVMUbzRBebbb6RpFwt/X+NLFUGysd+XNLF7W7lzxKtmFNX
+n4OpNkBe0y5O7yurus8rERHzu3jiOSgVo+WzDlGpYSRnG3hI2qPWqD+Puzx/WwI8
+XUTuzEQQ3gUSyVFfXHpay3VpYmLZiLJ9WKY5SDw7Ie6Sxrju4Qm1HwnFY8wHZGcs
+2KMQzorJ1ZNQf523yUTghbT0rKaSFaD8zugPtI2ONfFG/QgrkQXo78opzPsHnHwa
+SxGSiAgeLbwAUCvPNl27zr6k6+7TcNjV0VUivAs0OG3VEAdgi7UWYB+30KfWwHwE
+zGmvd4IAGqIqlqLcSVArN5z8JK1B5nfjQn5UrclU1vK+dnuiKE2X4rKuBTRYRFR/
+km+mj4koYFPKFHndmJl1uv2OCJK9l5CSIuKWeI1qv8BASKqgNdoT/SKBXqxgYlCb
+o+j4IDjxrxChRO+e5vl9lA7INfRrbljCkUjfLRa+v2q9tWQ3+EQUwwnSrSfihh2T
+j0Tksr6b8dDsvMlCdOKG1B+JPcEXORSFKNXVTEfjqpJG8s16kFAocWt3S6xO0k1t
+qbQp+3tWQgW2TGnX0rMZzB6NGRNfWhlYmq2zHgXkiCIZ26Ztgt/LNbwEvN3+VlLo
+z/Rd+SKtlrfb
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIGQTCCBCmgAwIBAgIJANSi/bsXEOI5MA0GCSqGSIb3DQEBCwUAMIG9MQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCTkoxEzARBgNVBAcMCkJlZG1pbnN0ZXIxEjAQBgNV
+BAoMCU9wZW5FQ09NUDETMBEGA1UECwwKc2ltcGxlZGVtbzE6MDgGA1UEAwwxT3Bl
+bkVDT01QIHNpbXBsZWRlbW8gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEn
+MCUGCSqGSIb3DQEJARYYc2ltcGxlZGVtb0BvcGVuZWNvbXAub3JnMB4XDTE2MTEy
+ODIxMTQyNVoXDTI2MTEyNjIxMTQyNVowgb0xCzAJBgNVBAYTAlVTMQswCQYDVQQI
+DAJOSjETMBEGA1UEBwwKQmVkbWluc3RlcjESMBAGA1UECgwJT3BlbkVDT01QMRMw
+EQYDVQQLDApzaW1wbGVkZW1vMTowOAYDVQQDDDFPcGVuRUNPTVAgc2ltcGxlZGVt
+byBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MScwJQYJKoZIhvcNAQkBFhhz
+aW1wbGVkZW1vQG9wZW5lY29tcC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDLgdDTCZX5xlMFIo+tjj5DItAwbutQE3NMchx/CRIuYwRCBOEO0yOs
+AdnZAuheYrjv/Dw4wKNzcvtIlYbfiPsGWVvx5j6+xoGBLLwIOnDyzD2B62uCvMs9
+47MAuiqpPojPwDDb9fF5EIhlC+cBzSYKm7D5ihYxmUCnh9yHIPEMq0IoVj2illlK
+eCTLW+bZKeaKoWdkFxyyzykOoMFgZTUm01EhDIt1DHTve675Qq80UgzrZdSK6Zjv
+3wLV7tkJSGmCkbUELpxsTLKYuaGUkE0m5n3SMUcvBDa6WNQpWlUbZlTwWotOrxfN
+Gib3nGiqyCmQXrVvuuBDzmZifZaJpBGiiGiOxp0j79E/OZkfk/9V3Hvfy78Ss9H5
+uhf/ACGKsUq9nN25u+Wpz7EzAQm/OBubBrBCMP/8pm+y1jCfQ6Bwd0Nm48KrJkTe
+ySkferISNmpQZ2dyZXQVXMarbRfagQ6XdJw6EVnDwydVzb5LAqam3JUXjsHIj7Gv
+2DmXwJtwV+cnKB/OxRsP/JWwlyC9pFGy17HWc7EwPqXm1UNdDM36UaoBDzsh3DcI
+vg5+BOOtYPmiZ2+CMD2JxAXmtCMAmQA1mSsW7beTuHKy+7EdCAWcregE60PE3w2l
+G8n50YSXb0WZ2IaQUsBhhpZmu6VVTEcoi5eMglI6QyO21y0oKPYWPQIDAQABo0Iw
+QDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmmQF
+QD3oWZUOVE81Qc9WSfcyqwwwDQYJKoZIhvcNAQELBQADggIBAE1ArwZwMVVJe1Pj
+p1R9+Q766Qhzh4EN9RFCsktCcf4pB23lPtFhMhIZJP5eZKLB4MUIvtmleU+DmOWf
+jcEcgauMrc9Ihacra+IRJsr4JQjQSDHoEgl/yR6VUd9vbGH66ElIg9nP7XWAE6h5
+DTAxA8X1qyUOVGsKAps2uhBwNtl8RdX6GrZahkSOUMOq3H4wyEEPQlpU2AewZqOU
+p0vdbQ/is6cbJh6dgxFrSzBti/MKj/EPM6yJwlO+RfGlJmEI7J7bLEYIeNssLnv6
+FGiOgyWQ+gmwVK827F4Jwoght2BCcNsG/oPkAPbdw4yRIyi92QSWMEBKibECypQE
+a1DYvfHWGQLQifGzFuJTOca9vgu2B/BQ+0Ii4DqMS8hc2rw1CAD5zHAT/BIgAKM6
+ygL5Oyvrj8AQLgOkjhFh0HFKneh4j7wBtibpmDnBoSv227PAtdytCoRgivjhmF5B
+Ryx7BswcTEtZHWHxD/i2wlMEGNqGbcRmCCy9hhCxitAz70aq3Y/pC46n7w5bOmvJ
+Ap9D+WmTJ9PdpDjiwCXCkMD3QaTuUV1W3Zr4mLLj6gRLb6ycgDrsqXnY6/JB/AOd
+gxFK9q1vjhm02FAABIa+kL10CKPuRdlE/GsWl03WKMeT5bY3MTO3odsNXhKWA19h
+wUAp0gnljuFHPX7jWwruZ1eD8mQv
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFPjCCAyagAwIBAgIJAJ6u7cCnzrWdMA0GCSqGSIb3DQEBCwUAMCwxDjAMBgNV
+BAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJVUzAeFw0xODA0MDUx
+NDE1MjhaFw0zODAzMzExNDE1MjhaMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQK
+DARPTkFQMQswCQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAMA5pkgRs7NhGG4ew5JouhyYakgYUyFaG121+/h8qbSdt0hVQv56+EA41Yq7
+XGie7RYDQK9NmAFF3gruE+6X7wvJiChp+Cyd7sFMnb65uWhxEdxWTM2BJFrgfzUn
+H8ZCxgaCo3XH4PzlKRy2LQQJEJECwl/RZmRCXijMt5e9h8XoZY/fKkKcZZUsWNCM
+pTo266wjvA9MXLmdgReRj0+vrCjrNqy+htwJDztoiHWiYPqT6o8EvGcgjNqjlZx7
+NUNf8MfLDByqKF6+wRbHv1GKjn3/Vijd45Fv8riyRYROiFanvbV6jIfBkv8PZbXg
+2VDWsYsgp8NAvMxK+iV8cO+Ck3lBI2GOPZbCEqpPVTYbLUz6sczAlCXwQoPzDIZY
+wYa3eR/gYLY1gP2iEVHORag3bLPap9ZX5E8DZkzTNTjovvLk8KaCmfcaUMJsBtDd
+ApcUitz10cnRyZc1sX3gE1f3DpzQM6t9C5sOVyRhDcSrKqqwb9m0Ss04XAS9FsqM
+P3UWYQyqDXSxlUAYaX892u8mV1hxnt2gjb22RloXMM6TovM3sSrJS0wH+l1nznd6
+aFXftS/G4ZVIVZ/LfT1is4StoyPWZCwwwly1z8qJQ/zhip5NgZTxQw4mi7ww35DY
+PdAQOCoajfSvFjqslQ/cPRi/MRCu079heVb5fQnnzVtnpFQRAgMBAAGjYzBhMB0G
+A1UdDgQWBBRTVTPyS+vQUbHBeJrBKDF77+rtSTAfBgNVHSMEGDAWgBRTVTPyS+vQ
+UbHBeJrBKDF77+rtSTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAN
+BgkqhkiG9w0BAQsFAAOCAgEAPx/IaK94n02wPxpnYTy+LVLIxwdq/kawNd6IbiMz
+L87zmNMDmHcGbfoRCj8OkhuggX9Lx1/CkhpXimuYsZOFQi5blr/u+v4mIbsgbmi9
+7j+cUHDP0zLycvSvxKHty51LwmaX9a4wkJl5zBU4O1sd/H9tWcEmwJ39ltKoBKBx
+c94Zc3iMm5ytRWGj+0rKzLDAXEWpoZ5bE5PLJauA6UDCxDLfs3FwhbS7uDggxYvf
+jySF5FCNET94oJ+m8s7VeHvoa8iPGKvXrIqdd7XDHnqJJlVKr7m9S0fMbyEB8ci2
+RtOXDt93ifY1uhoEtEykn4dqBSp8ezvNMnwoXdYPDvTd9uCAFeWFLVreBAWxd25h
+PsBTkZA5hpa/rA+mKv6Af4VBViYr8cz4dZCsFChuioVebe9ighrfjB//qKepFjPF
+CyjzKN1u0JKm/2x/ORqxkTONG8p3uDwoIOyimUcTtTMv42bfYD88RKakqSFXE9G+
+Z0LlaKABqfjK49o/tsAp+c5LoNlYllKhnetO3QAdraHwdmC36BhoghzR1jpX751A
+cZn2VH3Q4XKyp01cJNCJIrua+A+bx6zh3RyW6zIIkbRCbET+UD+4mr8WIcSE3mtR
+ZVlnhUDO4z9//WKMVzwS9Rh8/kuszrGFI1KQozXCHLrce3YP6RYZfOed79LXaRwX
+dYY=
+-----END CERTIFICATE-----
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/pom.xml b/vnfs/VESreporting_vFW5.0_DANOS/pom.xml
new file mode 100644 (file)
index 0000000..0de77e8
--- /dev/null
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ============LICENSE_START==========================================
+ ===================================================================
+ 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.
+ ============LICENSE_END============================================
+
+ ECOMP and OpenECOMP are trademarks
+ and service marks of AT&T Intellectual Property.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+<parent>
+    <groupId>org.onap.demo.vnf</groupId>
+    <artifactId>demo-aggregator</artifactId>
+    <version>1.6.0-SNAPSHOT</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.onap.demo.vnf.ves5</groupId>
+  <artifactId>ves_vfw_reporting_danos</artifactId>
+
+  <build>
+    <plugins>
+
+       <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.3.2</version>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <phase>never</phase>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.5.3</version>
+        <configuration>
+          <descriptor>dep.xml</descriptor>
+        </configuration>
+        <executions>
+          <execution>
+            <id>create-archive</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+        <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>exec-maven-plugin</artifactId>
+           <version>1.6.0</version>
+            <executions>
+                <execution>
+                    <phase>none</phase>
+                </execution>
+            </executions>
+            <configuration>
+                <skip>true</skip>
+            </configuration>
+        </plugin>
+
+    </plugins>
+  </build>
+
+</project>
diff --git a/vnfs/VESreporting_vFW5.0_DANOS/vpp-measurement-reporter-danos.c b/vnfs/VESreporting_vFW5.0_DANOS/vpp-measurement-reporter-danos.c
new file mode 100644 (file)
index 0000000..eb74660
--- /dev/null
@@ -0,0 +1,343 @@
+/*************************************************************************//**
+ *
+ * Copyright © 2020 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <jansson.h>
+
+#include <vyatta-cfg/client/rpc.h>
+#include <vyatta-cfg/client/error.h>
+#include <vyatta-cfg/client/connect.h>
+#include <vyatta-cfg/client/node.h>
+
+#include <evel.h>
+
+#define BUFSIZE 128
+#define READ_INTERVAL 10
+
+typedef struct dummy_vpp_metrics_struct {
+  int bytes_in;
+  int bytes_out;
+  int packets_in;
+  int packets_out;
+} vpp_metrics_struct;
+
+
+void read_vpp_metrics_danos(vpp_metrics_struct *, char *);
+
+int main(int argc, char** argv)
+{
+  EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+  EVENT_MEASUREMENT* vpp_m = NULL;
+  EVENT_HEADER* vpp_m_header = NULL;
+  EVENT_HEADER* batch_header = NULL;
+  MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
+  int bytes_in_this_round;
+  int bytes_out_this_round;
+  int packets_in_this_round;
+  int packets_out_this_round;
+  vpp_metrics_struct* last_vpp_metrics = malloc(sizeof(vpp_metrics_struct));
+  vpp_metrics_struct* curr_vpp_metrics = malloc(sizeof(vpp_metrics_struct));
+  struct timeval time_val;
+  time_t start_epoch;
+  time_t last_epoch;
+  char hostname[BUFSIZE];
+  char eventName[BUFSIZE];
+  char eventId[BUFSIZE];
+  char* fqdn2 = NULL;
+  int port2 = 0;
+  char * vnic = NULL;
+  memset(eventName, 0, BUFSIZE);
+  memset(eventId, 0, BUFSIZE);
+  memset(hostname, 0, BUFSIZE);
+
+  strcpy(eventName, "vFirewallBroadcastPackets");
+  strcpy(eventId, "mvfs00000001");
+
+  char* fqdn = argv[1];
+  int port = atoi(argv[2]);
+  char* caFile = "/opt/VES/config/onap-ca.crt";
+  char* userName = "sample1";
+  char* passWord = "sample1";
+
+  if(argc == 6)
+  {
+     fqdn2 = argv[3];
+     port2 = atoi(argv[4]);
+     vnic = argv[5];
+  }
+  else
+     vnic = argv[3];
+
+
+
+
+
+  printf("\nVector Packet Processing (VPP) measurement collection\n");
+  fflush(stdout);
+
+  if (!((argc == 4) || (argc == 6)))
+  {
+    fprintf(stderr, "Usage: %s <FQDN>|<IP address> <port> <FQDN>|<IP address> <port> <interface> \n", argv[0]);
+    fprintf(stderr, "OR\n");
+    fprintf(stderr, "Usage: %s <FQDN>|<IP address> <port> <interface>\n", argv[0]);
+    exit(-1);
+  }
+
+  /**************************************************************************/
+  /* Initialize                                                             */
+  /**************************************************************************/
+  if(evel_initialize(fqdn,                         /* FQDN                  */
+                     port,                        /* Port                  */
+                     fqdn2,                       /* Backup FQDN           */
+                     port2,                       /* Backup port           */
+                     NULL,                         /* optional path         */
+                     NULL,                         /* optional topic        */
+                     100,                          /* Ring Buffer size      */
+                     1,                            /* HTTPS?                */
+                     NULL,                         /* cert file             */
+                     NULL,                         /* key  file             */
+                     caFile,                       /* ca   file             */
+                     NULL,                         /* ca   directory        */
+                     0,                            /* verify peer           */
+                     0,                            /* verify host           */
+                     userName,                     /* Username              */
+                     passWord,                     /* Password              */
+                     "sample1",                    /* Username2             */
+                     "sample1",                    /* Password2             */
+                     NULL,                         /* Source ip             */
+                     NULL,                         /* Source ip2            */
+                     EVEL_SOURCE_VIRTUAL_MACHINE,  /* Source type           */
+                     "vFirewall",                         /* Role                  */
+                     1))                           /* Verbosity             */
+
+  {
+    fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+    exit(-1);
+  }
+  else
+  {
+    printf("\nInitialization completed\n");
+  }
+
+
+  gethostname(hostname, BUFSIZE);
+  memset(last_vpp_metrics, 0, sizeof(vpp_metrics_struct));
+  read_vpp_metrics_danos(last_vpp_metrics, vnic);
+  gettimeofday(&time_val, NULL);
+  start_epoch = time_val.tv_sec * 1000000 + time_val.tv_usec;
+  sleep(READ_INTERVAL);
+
+  /***************************************************************************/
+  /* Collect metrics from the VNIC                                           */
+  /***************************************************************************/
+  while(1) {
+    memset(curr_vpp_metrics, 0, sizeof(vpp_metrics_struct));
+    read_vpp_metrics_danos(curr_vpp_metrics, vnic );
+
+    if(curr_vpp_metrics->bytes_in - last_vpp_metrics->bytes_in > 0) {
+      bytes_in_this_round = curr_vpp_metrics->bytes_in - last_vpp_metrics->bytes_in;
+    }
+    else {
+      bytes_in_this_round = 0;
+    }
+    if(curr_vpp_metrics->bytes_out - last_vpp_metrics->bytes_out > 0) {
+      bytes_out_this_round = curr_vpp_metrics->bytes_out - last_vpp_metrics->bytes_out;
+    }
+    else {
+      bytes_out_this_round = 0;
+    }
+    if(curr_vpp_metrics->packets_in - last_vpp_metrics->packets_in > 0) {
+      packets_in_this_round = curr_vpp_metrics->packets_in - last_vpp_metrics->packets_in;
+    }
+    else {
+      packets_in_this_round = 0;
+    }
+    if(curr_vpp_metrics->packets_out - last_vpp_metrics->packets_out > 0) {
+      packets_out_this_round = curr_vpp_metrics->packets_out - last_vpp_metrics->packets_out;
+    }
+    else {
+      packets_out_this_round = 0;
+    }
+
+    vpp_m = evel_new_measurement(READ_INTERVAL, eventName, eventId);
+
+    if(vpp_m != NULL) {
+      printf("New measurement report created...\n");
+      vnic_performance = (MEASUREMENT_VNIC_PERFORMANCE *)evel_measurement_new_vnic_performance(vnic, "true");
+      evel_meas_vnic_performance_add(vpp_m, vnic_performance);
+      evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, packets_in_this_round);
+      evel_vnic_performance_tx_total_pkt_delta_set(vnic_performance, packets_out_this_round);
+
+      evel_vnic_performance_rx_octets_delta_set(vnic_performance, bytes_in_this_round);
+      evel_vnic_performance_tx_octets_delta_set(vnic_performance, bytes_out_this_round);
+
+      /***************************************************************************/
+      /* Set parameters in the MEASUREMENT header packet                         */
+      /***************************************************************************/
+      last_epoch = start_epoch + READ_INTERVAL * 1000000;
+      vpp_m_header = (EVENT_HEADER *)vpp_m;
+      vpp_m_header->start_epoch_microsec = start_epoch;
+      vpp_m_header->last_epoch_microsec = last_epoch;
+      evel_reporting_entity_id_set(vpp_m_header, "No UUID available");
+      evel_reporting_entity_name_set(vpp_m_header, hostname);
+      batch_header = evel_new_batch("batch_event_name", "bevent_id");
+      evel_batch_add_event(batch_header, vpp_m_header);
+      evel_rc = evel_post_event(batch_header);
+
+      if(evel_rc == EVEL_SUCCESS) {
+        printf("Measurement report correctly sent to the collector!\n");
+      }
+      else {
+        printf("Post report failed %d (%s)\n", evel_rc, evel_error_string());
+      }
+    }
+    else {
+      printf("New measurement report failed (%s)\n", evel_error_string());
+    }
+
+    last_vpp_metrics->bytes_in = curr_vpp_metrics->bytes_in;
+    last_vpp_metrics->bytes_out = curr_vpp_metrics->bytes_out;
+    last_vpp_metrics->packets_in = curr_vpp_metrics->packets_in;
+    last_vpp_metrics->packets_out = curr_vpp_metrics->packets_out;
+    gettimeofday(&time_val, NULL);
+    start_epoch = time_val.tv_sec * 1000000 + time_val.tv_usec;
+
+    sleep(READ_INTERVAL);
+  }
+
+  /***************************************************************************/
+  /* Terminate                                                               */
+  /***************************************************************************/
+  sleep(1);
+  free(last_vpp_metrics);
+  free(curr_vpp_metrics);
+  evel_terminate();
+  printf("Terminated\n");
+
+  return 0;
+}
+
+void read_vpp_metrics_danos(vpp_metrics_struct *vpp_metrics, char *vnic) {
+
+     // structures for the DANOS stats
+     struct configd_conn conn;
+     struct configd_error err;
+     // will open and close the connection on each call for statistics
+     configd_open_connection(&conn);
+
+     //   /interfaces/statistics/interface/dp0s4
+     char xpath[50];
+     strcpy(xpath, "/interfaces/statistics/interface/");
+     strcat(xpath, vnic);
+     char * data = configd_tree_get_full_encoding(&conn, RUNNING, xpath, "rfc7951", &err);
+
+     if (data == NULL) {
+        printf("failed to get data: %s %s\n", err.source, err.text);
+        exit(1);
+     }
+     printf("%s\n", data);
+
+    // Do something with the RFC7951 encoded JSON data.
+    // Store metrics read from the vNIC in the struct passed from the main function
+    //
+    // "vyatta-interfaces-v1:statistics": {
+    //                 "interface": [{
+    //                                         "name": "dp0s3",
+    //
+    //
+    //  bytes_in : interface[i].receive-statistics.bytes
+    //  packets_in : interface[i].receive-statistics.packets
+    //  bytes_out : interface[i].transmit-statistics.bytes
+    //  packets_in : interface[i].transmit-statistics.packets
+    //
+
+    json_t *receive , *receive_bytes, *receive_packets;
+    json_t *transmit, *transmit_bytes , *transmit_packets;
+
+    json_error_t error;
+    json_t *node= json_loads(data,0,&error);
+    if(!node){
+          fprintf(stderr, "node not found error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+
+    receive = json_object_get(node, "vyatta-interfaces-v1:receive-statistics");
+    if(!receive){
+          fprintf(stderr, "receive not found error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+
+    receive_bytes= json_object_get(receive,"bytes");
+    if(!receive_bytes){
+          fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+
+    receive_packets= json_object_get(receive,"packets");
+    if(!receive_packets){
+          fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+
+    transmit = json_object_get(node, "vyatta-interfaces-v1:transmit-statistics");
+    if(!transmit){
+          fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+
+    transmit_bytes= json_object_get(transmit,"bytes");
+    if(!transmit_bytes){
+          fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+    transmit_packets= json_object_get(transmit,"packets");
+    if(!transmit_packets){
+          fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
+          exit(1);
+    }
+
+    fprintf(stdout, "Starting to convert json_integer_values\n") ;
+    fprintf(stdout, "receive_bytes %" JSON_INTEGER_FORMAT "\n", receive_bytes) ; 
+
+    const char *receive_bytes_string;
+    receive_bytes_string=  json_string_value(receive_bytes);
+    fprintf(stdout, "receive_bytes_string %s \n", receive_bytes_string) ; 
+
+    const char *receive_packets_string;
+    receive_packets_string=  json_string_value(receive_packets);
+    fprintf(stdout, "receive_packets_string %s \n", receive_packets_string) ; 
+
+    const char *transmit_bytes_string;
+    transmit_bytes_string=  json_string_value(transmit_bytes);
+    fprintf(stdout, "transmit_bytes_string %s \n", transmit_bytes_string) ; 
+
+    const char *transmit_packets_string;
+    transmit_packets_string=  json_string_value(transmit_packets);
+    fprintf(stdout, "transmit_packets_string %s \n", transmit_packets_string) ; 
+
+    vpp_metrics->bytes_in = atoi(receive_bytes_string);
+    vpp_metrics->packets_in = atoi(receive_packets_string);
+    vpp_metrics->bytes_out = atoi(transmit_bytes_string);
+    vpp_metrics->packets_out = atoi(transmit_packets_string);
+    
+    configd_close_connection(&conn);
+}